ASP.NET MVC4学习笔记
一、MVC简介
备注:
过去MVC模式并不适合小型甚至中等规模的应用程序,这样会带来额外的工作量,增加应用的复杂性。但现在多数软件设计框架,能直接快速提供MVC骨架,供中小型应用程序开发,此问题不再存在。对于开发存在大量用户界面,并且逻辑复杂的大型应用程序,MVC将会使软件在健壮性、代码重用和结构方面上一个新的台阶。尽管在最初构建MVC模式框架时会花费一定的工作量,但从长远的角度来看,它会大大提高后期软件开发的效率。
二、First Demo
三、Web开发方式对比
四、View详解
笔记:
-》Razor的使用:C#代码与html混编
-》HtmlHelper:快速完成表单布局
-》行为向视图传递数据:ViewData["键"],可以简写为ViewBag.键
-》强类型页面
为什么要使用强类型页面:实现了编译时错误检查,防止对于对象的属性的编写错误
怎么用:@model 类型,写在页面的最上面
访问:ViewData.Model(可简写为Model),Html.***For(c=>c.***)
-》难点:扩展方法,lambda表达式
五、Controller详解
笔记:
-》行为的本质就是方法
-》返回类型:ActionResult
-》行为的重载必须同时符合两点:1.参数不同;2.请求方式不同 (为啥参数不能区分呢 因为参数可以自动装配 无法仅仅通过参数来区分)
-》数据的传递与接收:
传递:支持get、post方式传递
接收:Request["键"],自动装配(post的name和行为参名一样才能实现)
其他补充:
1.做列表页面:(这种方式自己试了好像不行)
controller里面行为返回ViewBag.Model = List<Person> list;
view页面强类型设置为@using model List<**.Person>
然后遍历
@foreach(var item in Model)
{
遍历输出...
item.xxx;
}
自己尝试这个写法可以:
控制器:
public ActionResult CoachList() { List<UserDTO> coachList = _userBLL.GetCoachList(); return View(coachList); }
页面:
头部:
@model List<XX.DTO.UserDTO>
内容:
@foreach (var item in Model) { <a>@item.NickName</a> }
其他方式:
控制器中:
public ActionResult CoachList() { List<UserDTO> coachList = _userBLL.GetCoachList(); CoachListViewModel viewModel = new CoachListViewModel(); //CoachListViewModel为自定义视图实体类型 viewModel.CoachList = coachList; return View(viewModel); }
自定义视图实体类型CoachListViewModel
namespace Web.Models.ViewModel { public class CoachListViewModel { public List<UserDTO> CoachList { get; set; } } }
页面中:
顶部:@model Web.Models.ViewModel.CoachListViewModel
内容:
@foreach (var item in Model.CoachList) { <a>@item.NickName</a> }
2.controller中行为的自定义类型参数自动装配:(view中页面强类型请求过来)
public ActionResult Add(Person person)
{
装配过程:
1.先创建并初始化一个Person对象
2.然后把post过来的值,通过name作为键去找值,如果有的话自动装配赋值给Person对象属性。
}
六、路由Route
备注:
如果使用的是RouteDebugger,则不需要在Global中注册,而是通过web.config中为appsettings添加子节点<add key="RouteDebugger:Enabled" value="true"/>
备注:
#region 路由规则示例 //新闻显示页 routes.MapRoute( name: "NewsShow", url: "News/{year}-{month}-{day}-{id}", defaults: new { controller = "NewsHome", action = "Show" }, constraints: new { year = @"^\d{4}$", month = @"^\d{1,2}$", day = @"^\d{1,2}$" } ); //新闻列表页 routes.MapRoute( name: "NewsList", url: "News/{type}-{pageindex}-{pagesize}", defaults: new { controller = "NewsHome", action = "List" } ); //新闻首页 routes.MapRoute( name: "NewsIndex", url: "News/{*values}", defaults: new { controller = "NewsHome", action = "Index" } ); //网站首页 routes.MapRoute( name: "Index", url: "{*values}", defaults: new { controller = "Home", action = "Index" } ); #endregion
笔记:
-》4个类型:Route,RouteData,RouteCollection,RouteTable
-》参数传递与接收
-》自定义路由规则与调试
七、异步
笔记:
-》两种方式:使用jquery的异步方法;使用AjaxHelper
-》行为的返回值:
如果返回纯文件,使用Content("");
如果返回Json对象,使用Json(obj,...)
使用AjaxHelper需要先引入:
1.jquery.min.js
2.query.unobtrusive-ajax.min.js
示例:
View:
@using (Ajax.BeginForm("Add", "Person", new AjaxOptions() { OnSuccess = "Success", //这里是ajax完成后指定回调的JS回调函数 如: function Success(data){...} data是返回的数据
HttpMethod = "Post" //这种默认的Ajax是Get方式的请求,根据需求可以指定为Post
})) { <span>ID:</span>@Html.TextBoxFor(p => p.Id) @Html.ValidationMessageFor(model => model.Id) <br /> <span>Name:</span>@Html.TextBoxFor(p => p.Name) @Html.ValidationMessageFor(p => p.Name) <br /> <span>Age:</span>@Html.TextBoxFor(p => p.Age) @Html.ValidationMessageFor(p => p.Age) <br /> <input type="submit" id="btn" name="btn" value="提交" /> }
Controller:
[HttpPost] public ActionResult Add(Person person) { var json = new Person { Id = 2, Name = "test", Age = "11", }; return Json(json, JsonRequestBehavior.AllowGet); //需要设置json允许get方式请求,默认是只允许post方式 }
响应结果json数据:
{"Id":2,"Name":"test","Age":"11"}
八、校验
笔记:
-》引入相关的js脚本:1.jquery.min.js 2.jquery.validate.min.js 3.jquery.validate.unobtrusive.min.js(异步验证)
-》为模型对象添加校验特性
九、区域Area
笔记:
-》作用:将大项目的内容进行更好的管理
本质:就是个子文件夹
-》注意:区域的路由规则注册
练习:
1.基本Demo:控制器,行为(重载),视图,强类型页面,参数的传递与接收
Person,Add(展示表单),Add(添加处理)
2.异步:视图使用异步(jquery,ajaxhelper),返回值用content,json
十、过滤器
一、过滤器实现方式:自定义过滤器作为特性来使用
行为和类过滤:
[MyAuthorization] //整个类过滤,类下的所有方法都会过滤 public class HomeController : Controller { [MyAuthorization] //单个行为进行过滤 public ActionResult Index() { return View(); } }
全局过滤在项目App_Start文件夹下的FilterConfig.cs文件添加自定义的过滤器:
public static void RegisterGlobalFilters(GlobalFilterCollection filters) { filters.Add(new HandleErrorAttribute()); filters.Add(new MyAuthorzation()); //自定义的过滤器 }
二、过滤器实现方式:控制器中重写方法
在控制器中重写方法:
public class HomeController : Controller { [MyAuthorization] //单个行为进行过滤 public ActionResult Index() { return View(); } //重写方法实现过滤器:(缺点:整个类中的方法都会过滤) protected override void OnAuthorization(AuthorizationContext filterContext) { //处理代码... filterContext.HttpContext.Response.Write("输出"); } }
添加异常处理过滤器步骤:
1.如果没有Filter文件夹可以先新建,然后在文件夹下新建类MyException.cs文件,继承HandleErrorAttribute,然后重新OnException方法:
public class MyException:HandleErrorAttribute { public override void OnException(ExceptionContext filterContext) { //如下代码不可以被删除,所以捕获不到异常 base.OnException(filterContext); //记录日志 //页面跳转 filterContext.Result=new RedirectResult("/Error/400.html"); } }
可以以特性的方式加到类或行为上:
[MyException] public ActionResult Index() { throw new Exception(""); }
如果想全局异常过滤,修改App_Start文件夹下的FilterConfig.cs文件:
public class FilterConfig { public static void RegisterGlobalFilters(GlobalFilterCollection filters) { //系统默认的异常处理过滤器,如果使用自定义异常处理,要将如下代码删除 //filters.Add(new HandleErrorAttribute()); //这个是系统自带的,如果采用自定义的,这行需要删除 filters.Add(new MyException());//自定义的异常处理 } }
2.在Web.config中<system.web>下添加配置:
<customErrors mode="On">
注:异常处理过滤还可以在Controller类里重写OnException方法来实现,用法和身份验证一样。
添加行为过滤器实现步骤:
1.在Filter文件夹下新建MyAction.cs类文件,继承ActionFilterAttribute,重写OnActionExecuting、OnActionExecuted方法:
public class MyAction:ActionFilterAttribute { //表示行为执行前,需要处理的代码 public override void OnActionExecuting(ActionExecutingContext filterContext) { filterContext.HttpContext.Response.Write("ing<br>"); } //表示行为执行后,需要处理的代码 public override void OnActionExecuted(ActionExecutedContext filterContext) { filterContext.HttpContext.Response.Write("ed<br>"); } }
2.以特性方式添加到Controller中的Action上:
[MyAction] public ActionResult Index() { Response.Write("行为执行中<br>"); return View(); }
注:行为过滤器同样可以在Controller里重写OnActionExcuting、OnActionExcuted方法来实现。
结果过滤器的结果指的是View的执行:
结果过滤器添加步骤:
同样两种实现方式:1.特性类(行为、控制器、全局) 2.重写Controller类的方法
十一、模板页
十二、WebAPI
通过Jquery的ajax方法调用WebAPI示例:(这种方式不支持跨域请求)
浏览器端请求:(Api控制器中哪个行为被执行,要看请求的地址和请求方式来决定,而不是指定行为名称来调用)
1.查询数据
<!DOCTYPE html> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <title>WebApi测试</title> <script src="Scripts/jquery-1.8.2.min.js"></script> <!--<script src="Scripts/jquery-1.8.2.intellisense.js"></script>--> <script type="text/javascript"> //页面加载完成后执行 $(function () { LoadList(); }); //加载List列表 function LoadList() { //ajax开始 $.ajax({ url: "http://localhost:5274/api/person", //请求的地址 type: "get", //请求方式,默认为get。另外还有post,put,delete contentType: "application/json; charset=utf-8",//请求报文头数据类型,发送给服务器的数据类型 data: "",//发送到服务器的数据,一般为Json格式字符串 dataType: "json",//服务器返回数据的类型 success: function (list) //请求成功后调用的回调函数,回调函数参数list为请求返回的数据 { //获取页面元素,并先清空 var obj = $("#list"); obj.empty(); //遍历数据添加到元素中 $.each(list, function (index, item) { //each方法为每个匹配到的元素指定运行的函数,list为需要遍历的对象,匿名函数function是匹配到的每个元素需要执行的函数,index为遍历到的元素index,item是遍历到的元素 obj.append('<li>' + item.Name + ' | ' + item.Age + '</li>'); }); } }); //ajax结束 } </script> </head> <body> <div> <ul id="list"></ul> </div> </body> </html>
注:ajax参数contentType和dataType测试不写也可以,浏览器应该自动去判断类型了,规范写法建议还是加上。
2.更新数据:
var data = '{"UserId":"' + $('#userId').val() + '","UserName":"' + $('#userName').val() + '"}'; $.ajax({ type: 'PUT',//请求类型。get,post,put,delete url: 'api/UserInfo/' + $('#userId').val(),//请求地址 data: data,//参数 contentType: "application/json; charset=utf-8",//数据类型 dataType: 'text',//返回数据类型 success: function (msg) { if (eval(msg) == '1') { InitData(); } } });
服务器端:
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Web.Http; using WebApiStudy.Models; namespace WebApiStudy.Controllers { public class PersonController : ApiController { // GET api/person public IEnumerable<Person> Get() { List<Person> list = new List<Person>() { new Person(){Name="张三",Age=22}, new Person(){Name="李四",Age=33} }; return list; //return new string[] { "value1", "value2" }; } // GET api/person/5 public string Get(int id) { return "value"; } // POST api/person public void Post([FromBody]string value) { } // PUT api/person/5 public void Put(int id, [FromBody]string value) { } // DELETE api/person/5 public void Delete(int id) { } } }
浏览器请求返回结果:
WebAPI返回的原始数据:
WebAPI返回的Json格式数据:
[{"Name":"张三","Age":22},{"Name":"李四","Age":33}]
备注:
创建并初始化对象: client.BaseAddress = new Uri(url); client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json")); 读集合: HttpResponseMessage response = client.GetAsync(url).Result; var userList = response.Content.ReadAsAsync<IEnumerable<数据类型>>().Result; 根据编号读对象 HttpResponseMessage response1 = client.GetAsync(url).Result; var userInfo = response1.Content.ReadAsAsync<数据类型>().Result; 增加: HttpResponseMessage response = client.PostAsJsonAsync("api/userinfo", userInfo).Result; 使用response.IsSuccessStatusCode判断是否成功 使用response.Content.ToString()获取返回值 修改: HttpResponseMessage response = client.PutAsJsonAsync("api/userinfo/"+userInfo.UserId, userInfo).Result; 使用response.IsSuccessStatusCode判断是否成功 使用response.Content.ToString()获取返回值 删除: HttpResponseMessage response = client.DeleteAsync("api/userinfo/" + uid).Result; 使用response.IsSuccessStatusCode判断是否成功 使用response.Content.ToString()获取返回值
十三、原理(管道执行过程)
MVC原理之获取处理器对象:
备注:
当一个asp.net mvc应用程序提出请求,为了响应请求,包含一些请求执行流程步骤! 在asp.net mvc应用程序Http request和Http response 过程中,主要包含8个步骤:
1)RouteTable(路由表)的创建
2)UrlRoutingModule 请求拦截
3)Routing engine 确定route
4)route handler 创建相关的IHttpHandler实例
5)IHttpHandler实例确定Controller(控制器)
6)Controller执行
7)一个视图引擎创建
8) 视图呈现