ASP.NET MVC的URL Routing的基本应用
参考:https://github.com/MVCAppDesignAndDevelop/MVC5Book
1.默认的URL Routing
新建一个MVC项目,在App_Start文件夹中找到RouteConfig.cs,内容如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
//忽略特定网址样式匹配,避免ASP.NET MVC的调用被MvcHandler执行
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
//定义URL Routing网址样式
routes.MapRoute(
name: "Default",//Route名称必须唯一
/*URL Routing样式,其中被“{}”包住的变量除了controller和action
都可以根据自己的需要自定义*/
url: "{controller}/{action}/{id}",
/*当传入的网址比对不到的时候就会根据defaults定义的值代替
其中id的设置UrlParameter.Optional(选择性参数)
这个意思是即使网址中没有id也会默认通过*/
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
2.加入自定义的URL Routing
比对顺序是由上往下的,所以当一个请求过来时,首先比对名为Test的MapRoute,如果网址不匹配,则比对Default的MapRoute,如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Test",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
}
}
}
3.为URL Routing加上限制条件
为了避免网址被预期外的URL Routing对比成功,编写MapRoute()时可加上一些限制条件,ASP.NET MVC提供了Constraints条件约束和Namespaces命名空间限制的两种方式
/* constraints方式 */
routes.MapRoute(
name: "Test",//名称必须唯一
url: "{action}/{id}",//删除了{controller}
defaults: new
{
controller = "Home",//网址样式删除了{controller}就必须使用默认值
action = "Index",
id = UrlParameter.Optional
},
constraints:new
{
//利用Regex语法,同时限制只有About和contact这两个Action会被比对到
//由于对比时会变成^(About|contact)$,所以不必加^和$
action = "(About|contact)"
}
);
/* namespces方式,多与Area关系紧密*/
routes.MapRoute(
name: "Test",//名称必须唯一
url: "{action}/{id}",//删除了{controller}
defaults: new
{
controller = "Home",//网址样式删除了{controller}就必须使用默认值
action = "Index",
id = UrlParameter.Optional
},
constraints:new
{
//利用Regex语法,同时限制只有About和contact这两个Action会被比对到
//由于对比时会变成^(About|contact)$,所以不必加^和$
action = "(About|contact)",
//限制只有命名空间相同的才会比对成功,多与Area关系紧密
namespaces: new[]{"WebApplication1.Controllers"}
}
);
4.直接获取Route Data内的值
Route Value存放于RouteValueDictionary的RouteData对象中,开发人员 可以从RouteData.Values内获取目前所有的Route Value如下:
//在View中获取Route Value
@(ViewContext.RouteData.Values["action"]);
@(ViewContext.RouteData.Values["controller"]);
//在Controller中获取Route Value
var currentAction = RouteData.Values["action"];
var currentController = RouteData.Values["controller"];
//在类内获取Route Value(这里用的HtmlHelper)
public static string GetCurrentControllerName(this HtmlHelper helper)
{
return (string)helper.ViewContext.RouteData.Values["controller"];
}
5.调试映射路由工具
Route Debugger属于项目等级的程序包,可使用NuGet获取安装,如:
使用Cobisi Routing Assitant,它属于Visual Studio的扩展功能,下载地址:https://marketplace.visualstudio.com/items?itemName=Cobisi.CobisiRoutingAssistant
6.Area以及相关问题
Area就是在原本MVC的结构中新增加的一个区域(这个区域包含专用的Model、View、Controller,也有独立的Route和View Engine等),使用Area更容易实现系统模块化。创建一个Area,名称为Admin,如下:
使用Area会遇到以下几个问题:
- Route相冲突的问题
Area内的Controller不能与主层重复,解决这一问题的办法是:尽量不要改Area内的Route,应从主Route入手,利用namespace限制条件让Route正确找到对应的Controller,如下:
using System.Web.Mvc;
using System.Web.Routing;
namespace WebApplication1
{
public class RouteConfig
{
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional },
namespaces: new[] { "WebApplication1.Controllers" }//
);
}
}
}
- 主层与Area互相调用问题
当项目中创建了Area后,对网址的调用方式就有了变化,为了避免混淆,必须提供Area位置,如下:
@{
ViewBag.Title = "Index";
}
<h2>Index</h2>
@Html.ActionLink("前往AD页面",//链接名称
"Index", //Action名称
new {
controller ="AD", //Controller名称
area ="Admin" //Area名称
})
<a href="@Url.Action("Index", "AD", new { area = "Admin"})">前往AD页面</a>
虽然主层的网址不需要加上Area="“的参数,只有在Area区域内的网址要回到主层才需要加上Area=”",但是建议项目中只要使用了Area,就加上Area定义,养成习惯