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>");
        }
    }
View Code

 

2.以特性方式添加到Controller中的Action上:

[MyAction]
public ActionResult Index()
{
    Response.Write("行为执行中<br>");
    return View();
}
View Code

注:行为过滤器同样可以在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>
View Code

注: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();
                        }
                    }
                });
View Code

 

服务器端:

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)
        {
        }
    }
}
View Code

浏览器请求返回结果:

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) 视图呈现

 

posted @ 2015-10-19 13:53  IT浪潮之巅  阅读(361)  评论(0编辑  收藏  举报
   友情链接: 淘宝优惠券