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)
MVC4学习笔记
最新推荐文章于 2019-01-08 05:56:13 发布