MVC4学习笔记

MVC4学习笔记

1.URL Routing——URL路由

1.1. 路由系统是神奇的,它由一组路由规则构成。对于一个应用程序来说,这些路由规则完全地匹配那些你的应用程序需要识别并且响应的URL请求。

1.2.URL地址可以被分割成一组字符串片段。比如:http://aa.com/bb/cc/...,其中bb即为该URL地址的第一部分片段,cc即为该URL地址的第二部分片段,依此类推。

1.3.路由系统通过“{controller}/{action}”(即“{控制器}/{行为}”)来识别URL地址的第一部分片段和第二部分片段间的关系。比如1.2中的地址的意思是调用名称为bb的控制器的名称为cc的行为来对该URL请求进行响应。

1.4.路由系统就是通过上面的这种模式,将URL地址中的各个字符串片段提取出来,然后映射到相应的{controller}及{action}参数上,然后调用相应的{controller}下的{action}。

1.5.这种URL地址的匹配模式是一种保守的匹配模式,也就是说,它将只匹配那些拥有相同片段数的URL地址。假定有一种模式{controller}/{action},那么它只能匹配拥有两个URL片段的URL地址,如http://aa.com/bb/cc或http://aa.com/xx/yy,而不能匹配http://aa.com/bb或http://aa.com/bb/cc这样的地址,因为前面两个都是由两组URL片段组成,而后面两个的URL片段都不是两组,所以不能匹配,这就叫做保守匹配。

1.6.RouteConfig.cs文件存储着程序的路由规则,它会在应用程序开始的时候由Global.asax.cs调用。

1.7.创建一个路由规则,比如:
            routes.MapRoute(
                name: "myRoute",        //名为myRoute的路由规则
                url: "{controller}/{action}"       //匹配只拥有两段URL片段的URL
            );

1.8.创建一个带默认值的路由规则,比如:
            routes.MapRoute(
                name: "myRoute",        //名为myRoute的路由规则
                url: "{controller}/{action}",       //匹配只拥有两段URL片段的URL
                defaults: new { action = "index" }      //设定{action}的默认值为index
            );
所谓默认值,即是当该URL片段缺省时,将使用默认值。比如当请求的URL为http://aa.com/bb时,路由系统将调用bb控制器下的index行为,而当URL为http://aa.com/bb/cc时,路由系统将调用bb控制器下的cc行为,这就是默认值的作用。

1.9.创建一个带静态URL片段的路由规则,比如:
            routes.MapRoute(
                name: "myRoute",        //名为myRoute的路由规则
                url: "admin/{controller}/{action}",    //其中的“admin”即为静态路由片段
                defaults: new { controller = "default", action = "index" }  //设定默认值
            );
或者
            routes.MapRoute(
                name: "myRoute",        //名为myRoute的路由规则
                url: "{controller}/{action}.html",     //其中的“.html”即为静态路由片段
                defaults: new { controller = "default"}      //设定默认值
            );

1.10.路由规则的匹配是按照路由规则在RouteCollection中的顺序进行的,也就是说,路由规则在RouteCollection中注册得越早,URL地址就将优先匹配该规则。路由系统会试图将请求的URL地址的模式去匹配最先注册的路由规则,除非规则不匹配才会跳到下一个注册的路由规则来进行匹配。比如:
            routes.MapRoute(
                name: "myRoute1",
                url: "/{controller}/{action}",
                defaults: new { action = "index" }
            );
            routes.MapRoute(
                name: "myRoute2",
                url: "/{controller}/{action}",
                defaults: new { action = "main" }
            );
当有URL请求http://aa.com//bb发生时,路由系统是选择bb控制器下的index行为,还是main行为呢,因为它们都能处理请求的URL地址。这时,路由规则的注册顺序就就决定了哪个路由规则会被使用,myRoute1先行进行了注册,所以路由系统会选择myRoute1作为http://aa.com//bb请求的处理规则。

1.11.创建混合的路由规则示例
            routes.MapRoute(
                name: "myRoute",
                url: "admin/{controller}/{action}",
                defaults: new { action = "index" }
            );
这里既有admin(静态路由规则)又有action=index这样的默认路由规则,所有可以多种路由规则共用。

1.12.创建不限制URL长度的路由规则,如:
            routes.MapRoute(
                name: "myRoute",
                url: "{controller}/{action}/{id}/{*other}",
                defaults: new { action = "index", other = UrlParameter.Optional }
            );
“*”表示从该处开始向后的所有URL字符串,“other”是URL片段名。如:http://aa.com/bb/cc/123/xx/yy/zz,那么
string other = RouteData.Values["other"].ToString();
的值为xx/yy/zz。

1.13.创建使用正则表达式的路由规则,例:
            routes.MapRoute(
                name: "myRoute",
                url: "{controller}/{action}/{id}",
                defaults: new { action = "index" },
                constraints: new { id = "^1|2|3$" }
            );
我们可以在constraints参数中定义各个URL片段的正则表达式匹配规则,上面的规则定义了id为1、2、3其中的一个,如果id不为其中的值则不匹配该规则。

1.14.通过RouteData.Values获取URL地址的属性值(片段值),例:请求的URL地址为http://aa.com/bb/cc/123,那么
string id = RouteData.Values["id"].ToString();
获得的值为123。

1.15.创建自定义的路由基类
1.15.1.自定义路由基类继承自RouteBase类,它能让您知道URL地址是如何匹配的、URL片段是如何提取的、动态的URL输出链接是如何生成的。
1.15.2.自定义路由必须重写
public override RouteData GetRouteData(HttpContextBase httpContext)
方法,该方法揭示了请求的URL匹配的原理,即路由是如何匹配的。
1.15.3.自定义路由也必须重写
public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
方法,该方法揭示了输出的URL的生成原理。
1.15.4.示例
public class MyRoute : RouteBase
    {
        //处理请求
        public override RouteData GetRouteData(HttpContextBase httpContext)
        {
            RouteData routeData = null;

            //获取所有的URL片段组
            string[] urls = httpContext.Request.Url.Segments;
            //片段URL片段组的长度
            if (urls.Length == 1)
            {
                //实例化RouteData对象,实例化时参数不能缺省
                routeData = new RouteData(this, new MvcRouteHandler());

                //添加URL片段
                routeData.Values.Add("controller", "default");
                routeData.Values.Add("action", "index");
                routeData.Values.Add("id", DateTime.Now.Second);
            }

            return routeData;
        }

        //输出URL
        public override VirtualPathData GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
        {
            //不进行处理时,直接返回null
            return null;
        }
    }
声明好了自定义的路由规则,需要将它注册到RouteCollection中,如下
routes.Add(new MyRoute());
然后调试一下试试看。

2. 在细分工作区中工作
2.1.MVC支持工作区的划分,对于一个大的项目而言,工作区的划分能大大增加项目管理的便捷性
2.2.工作区是一个单独的文件夹,它是一个MVC项目下的子项目
2.3.右击项目->添加->“Area”
2.4.工作区的路由规则需要特别注意,由于暂时用不上这里就不说了,要用时再查查

3.Controllers and actions(控制器与行为)
3.1.所有的URL请求最终将由控制器来进行处理
3.2.控制器包含三个重要的要素
3.2.1.行为方法(action)
3.2.2.行为结果(action result)
3.2.3.过滤器(filters)
3.2.3.1.AcceptVerbs,规定页面访问形式get/post等
3.2.3.2.ActionName,当不想使用方法名作为actionName时,可以使用该过滤器来设定其ActionName
3.2.3.3.Nonaction,当不想让controller下的方法为Action时使用,使用后方法仅为方法
3.2.3.4.Outputcache,用于缓存一个action的输出,这样,相同的请求对应的相同的响应就可以被重复使用了
3.2.3.4.1.Duration,秒,缓存的时间
3.2.3.4.2.Location,缓存类型,客户端|服务器端|。。。
3.2.3.4.3.例:[OutputCache(Duration=10)],缓存10秒钟

3.3.从请求对象中获取输入的参数
3.3.1.Form
3.3.2.QueryString
3.3.3.Cookie
3.3.4.Url
3.3.5.RouteData.Values
3.3.6.Cache
3.3.7.Session
3.3.8.......

3.4.从controller中向view中传递视图对象,例
Controller中:
        public ActionResult Index()
        {
            //获取一个datetime对象
            DateTime tm = DateTime.Now;

            //将datetime对象传递给视图index.cshtml
            //这样tm就为index视图的默认视图对象了
            return View(tm);
        }
Index.csthml中:
<!--model为视图对象关键字,在此声明其类型-->
@model DateTime

<!--Model为从controller中获取的视图对象,通过上面的类型声明可直接访问其属性和方法-->
<div>@Model.Second</div>

3.5.从controller中向view中传递任意对象,使用ViewBag,例
Controller中:
        public ActionResult Index()
        {
            ViewBag.time = DateTime.Now;
            ViewBag.msg = "hello";

            return View();
        }
Index.cshtml中:
@{
    //通过ViewBag获取controller中的time对象
    DateTime time = ViewBag.time;
    
    //将time的属性值输出
    //(注意,当需要执行cs代码时都需要@符号,
    //判断是否为cs代码看其背景是否为灰色就可知)
    <div>@time.Date</div>
    <div>@time.Second</div>
}
<div>@ViewBag.time</div>
<div>@ViewBag.msg</div>
ViewBag非常有用,是我们最常使用的controller到view间的数据传递媒介。

3.6.异常时的重定向处理
  <system.web>
      <customErrors mode="On" defaultRedirect="Error"></customErrors>
  </system.web>
当处理请求发生错误时,请求将转向名为Error的controller页面,所以,需要建立一个ErrorController和其想对应的action及view。

4.视图(view)
4.1.Section,可以控制一个框架(layout)的部分内容,当我们使用了layout页面时,其中的某个或者某几个页面需要单独地控制部分的layout中的代码时可以使用section,示例:
Layout的内容如下:
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width" />
    <title>@ViewBag.Title</title>
</head>
<body>
    <!--在此处加载名为sectionTest的section-->
    <!--false表示section是否必须,一般为false,否则就成layout了-->
    @RenderSection("sectionTest", false)

    <br />
    <!--view的内容将在此处加载-->
    @RenderBody()
</body>
</html>
View的内容如下:
<!--定义名为sectionTest的section-->
@section sectionTest{
    <div>这是来自view的section的内容</div>
}
<div>这是来自view的内容</div>
如上,执行后可知,view中的非section内容由renderBody()函数进行了呈现,而“sectionTest”的内容由“RenderSection("sectionTest", false)”进行了呈现。
其中,false的意思是别的页面没有定义名为sectionTest的section的话,也没关系,layout中这部分就不管了,但是如果是true而页面中又没定义相应的section的话则会报错。

4.2.Partial view(局部视图)
4.2.1.局部视图是分离的视图文件,它包含了部分的视图代码,并且可以被加载到其它的view中
4.2.2.新建名为“myPart”的PartView文件
<div>
    这是来自part view的代码
</div>

4.2.3.加载PartView
<!--partial有返回值,它会将结果返回到页面中来,然后再拼接输出-->
@Html.Partial("loginPart")
<!--renderPartial没有返回值,它直接向Response输出结果-->
@{Html.RenderPartial("loginPart");

4.3.Child Action(子行为)
4.3.1.子行为(child action)与行为(action)的关系就像局部视图(part view)与视图(view)间的关系
4.3.2.子行为关键字,[ChildActionOnly],使用了该关键字的为子行为
4.3.3.示例
在controller中添加以下代码:
        [ChildActionOnly]
        public ActionResult Msg()
        {
            return PartialView("Msg", DateTime.Now);
        }
添加上面的Action对应的View,代码如下:
@model DateTime
<div>@Model.Second</div>
在view中通过Action或RenderAction调用该子行为:
<!--Action有返回值,它会将结果返回到页面中来,然后再拼接输出-->
@Html.Action("Msg")
<!--RenderAction没有返回值,它直接向Response输出结果-->
@{Html.RenderAction("Msg");}

通过以上的对比,我们可以发现,当我们只进行html页面的操作时,我们使用Part view;当我们需要在part view中与cs代码进行交互时,我们采用child action。这是这二者最大的区别。

5.Helper methods
5.1.我们可以使用helper关键字在view中建立函数并调用
5.2.示例
<!--使用@helper关键字创建函数-->
@helper showTimes(int count){
    for (int i = 0; i < count; i++)
    {
        <div>@i-------------------@DateTime.Now</div>
    }
}

<!--调用函数-->
@showTimes(10)








  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值