3.路由
1)分析路由/controller/action
这段代码忽略了以.axd为文件后缀的URL
routes.IgnoreRoute("{resource}.axd/{*pathInfo}")
而每一个routes.MapRoute对象中name的值是要唯一的
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
)
多创建一条路由规则,如果名称相同,会出现错误
路由规则定义了{controller}/{action}/,如果只有一个HomeController和Index的action的话。交换来输入/Index/Home在url上,会提示无法找到资源。
URL中的controller和action是关键字,无法删除或修改。
修改成controller1和action1,出现错误。
但是顺序是可以交换的。我们把action和controller换过来。在地址栏写入/index/home成功访问页面。但是一般开发着都遵循/controller/action这种规则。
url中controller,action,id的值会以key,value的方式存储到字典中,可用RouteData.value[“id”]取出。
2)id传值
最后这个id参数是可选参数,与我们常看到在url后面加上?id=1是一样的意思。把id的值提交给了对应的action。
1.Request.QueryString只能获取以?分隔的参数值。
2.RouteData.Values[“id”]就是当前字典上的路由数据,通过访问键名的方式得到键值。
3.Action方法的参数和路由字典的参数是对应的,MVC框架在执行action之前会首先为这些参数赋值。
先试验Request.QueryString方法,Index代码修改成如下。
ViewData看起来就是视图数据的意思,[“”]内写上键名,后面给出得到的view值。转到视图,添加
ViewData["idValue"]数据。运行,地址栏输入/Home/Index/?id=99。
试验RouteData.Values[“id”]方法,Index代码修改成如下。
运行,地址栏输入/Home/Index/8859。
试验Action方法参数取值方法,Index代码修改成如下。
运行,地址栏输入/Home/Index/8521
用ViewData[“id”]来对页面传值是比较方便简单的方法。
3)URL匹配
上面已经分析过action和controller是可以换过来的,只要输入的url能够找到对应的控制器和方法是能对应上的。
当然还可以打造一些有个性的url,显得高端大气上档次。不过不能定义成{controller}和{action},只能各有一个。其余可以自己命名占位。{}里的词语就是一个占位符。
字面值即一个常数字符串,这个字符串可以在大括弧与大括弧之间,也可以在最前面和最后面。
1.使用字面量作精确匹配。
现在我们在url前方加入”ftah/”。url: "ftah/{controller}/{action}/{id}",让url 看起来就像必然要写这个ftah/的样子。运行程序。
在地址栏输入/Home/Index,出现了无法访问的错误,因为我们url规则必须以ftah/开头。
输入/ftah/Home/Index,成功匹配到/Home/Index。
但是两个url参数之间必须用字面量分隔。
加上-,url输入ch-home/index。完美解决。
2.使用*匹配url剩余部分。
我们把url改成这样,url: "{controller}/{action}/{*plus}"。使用*来匹配URL剩余的部分,最后尾部的URL部分会保存为plus为键名的字典值。
如图修改index方法,获取路由字典信息,同时修改视图中 <p>@ViewData["message"]</p>
运行时没有plus默认参数,视图会显示这样。
地址栏修改成/home/index/pq/da/ca。无论{controller}/{action}/之后有什么东西,一律分配到键名为“plus”对应的值。
2.贪婪匹配
把url改成 url:"{controller}/{action}/{plus}ftah{plus1}"。运行。
在地址栏输入/home/index/ftahftahftahmvc。可以看到plus的值是“ftahftah”,证明匹配是从右往左匹配,只要得到了固定的字符”ftah”,之后的全部交给plus来存值。
4)url默认参数
1.去掉默认值
默认defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }是否重要?先把这段代码去掉。
运行。发现没有默认值后无法访问页面。
输入能正确匹配的地址/home/index/1页面才能访问
如果没有使用默认值只能使用完整形式的URL
2.提供部分默认值
现在我们只给controller的默认值,添加代码 defaults: new { controller = "Home" }。
直接运行程序,无法访问页面。
尝试在地址栏输入/index/1。还是显示错误。这是因为mvc不知道你提供的index到底是一个controller还是action。
试试提供后两个参数?修改一下代码。
在地址栏输入/home 成功访问。(这里才显得有意义)
3.url包含字面量
在action后面把”/”去掉。跟一个”-”。
直接运行也是无法访问页面
在地址栏输入 /home/index-1。访问成功。
把”-”换成”+”。出现双重转义序列错误。
除”-”之外的任意字符的组合,那么字面量相邻的URL参数的默认值是不起作用的。
5)url约束
我们可以用正则表达式来对输入的地址进行约束。
url参数加入/{year}/{month}/{day}。
新增一个参数 constraints: new { year = @"\d{4}", month = @"\d{2}", day = @"\d{2}" }
里面的year ,month ,day 对应url的参数名称。@””里面就是写正则表达式。
这里\d{4}是只能输入4个数字,\d{2}只能输入两个数字。
运行,地址栏输入/home/index/1/2222/55/88。成功访问页面。
输入其中一个 不符合正则表达式的数值,页面就无法访问。
6)由路由生成URL
MVC中的路路由是双向的。可用路由生成URL。
定义一条普通的url。
修改HomeController的Index方法。
RouteTable.Routes.GetVirtualPath根据提供的参数生成url。
return Redirect(vp.VirtualPath);返回/执行一个控制器的action方法。这里vp.VirtualPath=/Home/About。
运行程序,通过默认路由转到/Home/Index在转到由我们写的代码生成的url/Home/About。
在定义一条路由,名称Default1,默认值不提供action。
Index方法修改如下,指定修改name为Default1的路由,为期添加action的默认值。
注释默认路由,运行。地址栏输入/Home/Index。
同样跳转到About
规则:默认路由不提供默认值,RouteValueDictionary(new { controller = "Home", action = "About" })必须提供所有url参数值。默认路由提供部分默认值,new RouteValueDictionary(new { action = "Index1" }),可以提供所有url参数值,但必须提供缺少默认值的那个参数值。但是由RouteTable.Routes.GetVirtualPath提供的默认值后方的默认路由值将失去作用,这里about是提供的,所以后面默认路由的参数值id无效。
如下图。id改成888001。
运行调试,最后只能生成/Home/About。
特殊情况:
路由url:"ftah/{action}/{id}",
默认参数defaults: new { controller = "Home", action = "Index", id = 100 }
在默认值中定义了 controller,但是在 URL 表达式中却没有这个参数。 在这个时候如果使用RouteTable.Routes.GetVirtualPath 获取 URL,如果设置的外界值提供了这个参数的值, 那么这个参数的值必须和默认值一样,否则就得不到 URL。new RouteValueDictionary(new { controller = "Home"})。
默认路由没有参数,也没有默认值,但在GetVirtualPath中添加上了
路由url:"{controller }/{action}/{id}",
默认参数defaults: new { controller = "Home", action = "Index", id = 100 }
RouteTable.Routes.GetVirtualPath(null, "Default1", new RouteValueDictionary(new { a = “a”,b=”b”}));
这样生成的url:/Home/Index/100?a=a&b=b 字符串传参的方式。