MVC
M(Model 模型) V(View 视图) C(Controllers 控制器)
控制器命名是必须带Controlls
一个控制器对应views中的一个文件夹(文件夹名称会自动去除Controlls)
控制器中的Action(行为)对应一个视图(页面)
调用行为时直接使用路径
/home/index
/控制器/行为
在App_Start中的RouteConfig文件中有路径的默认值,如果没有填相应的名称,就会使用默认值
还可以在那里修改路径格式
可以限制Action(行为)只能被某种方式访问到,例如Post,Get等
[HttpGet] or [HttpPost] public ActionResult index() { }
RedirctToAction("行为"); 重定向到某个行为
View(); 显示页面
如果一些行为不需要显示页面,则把返回值改为void,不加view即可
public void index() { }
如果想要把行为中的数据推送到页面上,可以使用 ViewBag
ViewBag是一个全局变量,可以在此页面的任何地方调用
ViewBag是一个动态变量,可以存放任何类型
ViewBag.Id = 1; ViewBag.Name = "张三"; ViewBag.stu = new Student(); .......
在页面上使用C#代码时使用
@{
ViewBag.Name
}
or
@ViewBag.Name
如果在C#代码中要编译器识别一条HTML时使用
@:这是一条HTML代码
ViewData和ViewBag是一样的东西,只是格式不同
ViewData["Name"] = "李四";
ViewDate和ViewBag只能在一个页面中调用,如果我们要可以在所有页面都可以调用时,使用TempData
TempData实质为session
但是它在使用一次后就会清空(session值赋null),所以是一个一次性的session
session过期时间此会话20分钟不使用后
TempData["Name"] = "赵六";
我们还可以直接把要推送的数据放在View()中,这样也可以推送到页面上
同样也是什么类型都可以
但是只能推送一个数据
return View(1); return View("陈七"); return View(new Student()); ..........
View()推送的数据默认为弱类型,如果要它变成强类型,要在页面上添加引用
@model model.Student;
MAC接收post,get请求时不需要使用Requery.Form或Requery.QueryString
直接在行为中添加上和数据相同的参数名称即可
public ActionResult index(int Id,String Name) { }
如果参数是对象,则不会对照对象名,而是对照对象中的属性名称
public ActionResult index(Student stu) { }
路由通过MapRoute()注册,也可以自定义路由
自定义的路由要放着默认路由上面
name 路由的名称
url 路径的书写格式,符合格式时才会采取这个路由,如果都不符合则使用默认路由
defaults 指定控制器,行为,参数等,参数Id可有可无
constraints 规定的参数的格式(正则)
routes.MapRoute( name:"new_Route", url:"new/{id}", defaults:new {controller="News",action="Index",Id=UrlParameter.Optional}, constraints:new {id = @"\d+"} //至少一个数字 );
高版本的mvc可以使用特性注册路由
[RoutePrefix("xxx")]//为这个控制器中所有路由添加一个前缀 public class news{ [Route("new/{id}")]//为这个行为添加路由 public ActionResult GetOne(string id) { return Content("xxxx"); //使用字符串创建一个视图结果 } }
如果要更改一个路由的路径的格式,所有页面的链接都要一个个改过来,这很麻烦,所以我们可以用这种方式给超链接,来避免
Url.Action("行为","控制器") 它会根据行为和控制器自动生成对应的路径
<a href="@Url.Action("行为","控制器")">超链接</a>
但如果我们想要使用指定的一个路由,那么可以使用
Url.RouteUrl("路由名称",new {controller="控制器",action=行为",Id=参数});
<a href="@Url.RouteUrl("路由名称",new {controller="控制器",action="行为",Id="参数"})">超链接</a>
Views文件夹中的Shared文件夹中放着公用的文件(如:模板页,分部页,错误页等)
无法独立运行的文件,名字前面加 _
母版页的@RenderBody() 代表子页面内容的位置
给子页面设置母版页
return View("子页面","母版页");
或者在子页面上写
@{ Layout = "母版页"; //此处要写全部路径 }
母版页中除了RenderBody()还有一个RenderSection()方法
RenderSection("名称",required:true or false //是否必须放东西 );
渲染区域,将子页面的一个区域放着母版页上
一般用于把子页面的css和js放着母版页中
@section 名称{
.......
}
在母版页中存储一个ViewBag,所有的子页面都可以使用
如果我们不想使用母版页,但是却有的部分是公共的,这时可以使用分部页
在要使用的页面通过
@Html.Partial("分部页名称",要给分部页的参数); or @Html.RenderPartial("分部页名称",要给分部页的参数);//效率更高
将分部页渲染过来
传给分部页的参数,再分布页中通过Model调用
@Model
允许在路径后加后缀名 (如news/index.jsp),需要在web.config中配置
<system.webServer> <modules runAllManagedModulesForAllRequests="true"/> </system.webServer>
在mvc的中行为是有很多返回值类型的,但是这些类型都是ActionResult的子类,所有直接写ActionResult就可以了
return View() ViewResult
return RedirectToAction() RedirctToRoutreResult
return Json(); JsonResult
return File(); FileContentResult
返回值是Json时,默认是不允许get请求的
return Json(new List<Models.Student>(){ ........... },JsonRequestBehavior.DenyGet //默认,不允许get or AllowGet //允许get);
使用ajax接收Json
$.ajax({ url:"请求地址", type:"get" //请求类型 dateType:"json" //结果类型 }).done(function(date){ //请求成功时触发 }).fail(function(err){ //请求失败时触发 });
console.warn(); 在控制台中输出
返回值是文件时
File() 的参数形式有很多
File(二进制数组,内容类型),File(文件流,内容类型),File(文件路径,内容类型),File(文件流,内容类型,下载后的文件名) 等等 Content Type 内容类型 类型有很多,自己百度
如果返回值是一张图片,可以直接放在img标签中
视频,音乐等文件同理
<img src="/控制器/行为" />
return new HttpNotFoundResult() //返回一个404页面 return JavaScriptResult() //返回一段js return EmptyResult() //返回空 null return new HttpStatusCodeResult(错误号,错误消息) //自定义报错
return PartialView() 返回分部页
它和之前的分部页不同,它是有一个行为方法的,可以进行一些处理
在页面上调用它
@Html.Action("行为名"); or @Html.RenderAction("行为名"); //效率更高
RenderPage和RenderPartial类似,但是它无法使用原视图的Model和ViewData,只能通过参数传递,而RenderPartial可以使用原视图的Model和ViewData
mvc过程
HTTP请求 → 路由 → 控制器 → Action → 视图结果 → 视图引擎 → 视图 → 响应
视图引擎紧跟Action方法执行后,目的是获取从控制器传递的数据,并生成经过格式化的输出
cshtml页面在被访问时也编译成了页面类,继承与WebViewPage<T>
创建一个表单
@Html.BeginForm("提交地址的行为名称","提交地址的控制器名称",FormMethod.Get or Post,new{@class = "要添加上去的样式名称",onsubmit = "要添加上去的事件方法名"})
Action可以返回一个json结果到页面,然后用ajax接收
但是返回的json的格式可能不太合适,在使用时需要在页面上处理
这时我们可以自己写一个json返回类,他要继承原本的JsonResult
return new JsonNetResult(){ Data=new List<XXX>(){ new XXX(){}, new XXX(){} },JsonRequestBehavior = JsonRequestBehaivor.AllowGet }
在页面上可以使用forEach来循环接收到的json
$.ajax({ url:"请求地址", type:"post or get", //请求类型 dataType:'json' //请求数据的类型 }).done( function(data){ data.forEach( function(值,下标,这个集合){ } ); } );
自己写模板
var temp = '<div>{{id}}</div>'; temp.replace("{{id}}",实际值); //把占位符替换为真实的值
生成一个a标签
@Html.ActionLink("链接显示的文字","要链接到的视图名字是");
@Html.ActionLink("这是一个链接","link"); //会生成 <a href="/index/link">这是一个超链接</a>
但是微软爸爸还为我们提供了一种ajax的生成a标签方式
前两个参数和之前的一样,但是它多了一个AjaxOptions,
AjaxOptions中有一些属性需要设置
UpdateTargetId = 'id' 请求后返回的数据显示在哪个容器里
Confirm = '弹框内容' 点击链接时弹个框提醒一下
LoadingElementId = 'id' 加载时显示的内容
InsertionMode = InsertionMode.InsertAfter or Replace 数据是向后追加还是替换掉原来的
@Ajax.ActionLink("链接显示的文字","要链接到的视图的名字",new AjaxOptions{ UpdateTargetId = 'id', Confirm = '弹框内容', LoadingElementId = 'id', InsertionMode = InsertionMode.InsertAfter or Replace });
查看源代码会发现这样生成的a标签会多几个属性,这些属性是需要jquery.unobtrusive-ajax.js支持的,否则没有任何作用
Html.AntiForgeryToken(); 和 特性 [ValidateAntiForgeryToken] 一样是防止别人恶意提交数据的
Ajax.BeginForm("行为","控制器", new AjaxOptions{ },new{ }) Ajax的方式生成表单
AjaxOptions中有一些属性需要设置
OnSuccess = "js方法名" 请求成功后执行js方法
HttpMethod = "post or get" 请求方式
在new{}当中可以添加id,class等属性
Html.LabelFor(d=>d.属性名,htmlAttributes:new { }) 通过某个实体类的属性生成label标签,默认是显示属性名,也可以在属性上加特性 [DisplayName("XXX")] 来设置显示什么
htmlAttributes:new{ }则是用来给标签添加id,class等属性
Html.EditorFor(d=>d.属性名,htmlAttributes:new{ }) 通过某个实体类的属性生成对应的input标签,input标签的类型由特性决定,例如 [DataType(DataType.Password)] 为密码框
Html.ValidationMessageFor(d=>d.属性名,"",new {@class="xxx"}) 某个实体类的属性验证错误时,把错误消息显示出来,错误消息可以通过特性设置
特性的常见验证
[Required(ErrorMessage = "错误消息")] 必填
[StringLength(100)] 至多n位
[StringLength(100,MinimumLength=1)] 至少n位
[RegularExpression(@"^[A-Z]$")] 正则验证
[Range(1,100)] 范围验证
[Range(typeof(decimal),"1.1","100.0")] 有小数的范围验证
[Remote("行为","控制器")] 服务端参与的验证