在上一篇文章中,有约定路由的介绍。MVC 5中增加了对属性路由这一新技术的支持。在属性路由中,路由是由直接运用于控制器的C#属性定义的。
启动和运用属性路由
默认情况下属性路由是禁止的,通过MapMvcAttributeRoutes扩展方法可以启用它。该方法由RouteCollection对象调用,如下图所示:
public static void RegisterRoutes(RouteCollection routes){routes.IgnoreRoute("{resource}.axd/{*pathInfo}");routes.MapMvcAttributeRoutes();//启动属性路由routes.MapRoute(name: "Default",url: "{controller}/{action}/{id}",defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional });}
调用 MapMvcAttributeRoutes 方法导致路由系统检查应用系统中的控制器类,并寻找匹配路由属性。最重要的属性是Route。如下图所示:
public class CustomerController : Controller{[Route("Test")]// GET: Customerpublic ActionResult Index(){ViewBag.Controller = "Customer";ViewBag.Action = "Index";return View("ActionName");}public ActionResult List(){ViewBag.Controller = "Customer";ViewBag.Action = "List";return View("ActionName");}}
当一个动作方法用Route属性修饰时,它不需要通过约定路由来访问,这意味着Customer控制器中的Index方法不再需要/Customer/Index,也不能用/Customer/Index来访问。 执行效果如下图所示:
使用片段变量创建路由
虽然通过属性表示,但是属性路由支持和基于约定路由一样的特性。这些特性包括创建包含片段变量的路由。如下图所示:
public class CustomerController : Controller{[Route("Test")]// GET: Customerpublic ActionResult Index(){ViewBag.Controller = "Customer";ViewBag.Action = "Index";return View("ActionName");}[Route("Users/Add/{user}/{id}")]public string Create(string user, int id){return string.Format("User:{0},ID:{1}",user,id);}public ActionResult List(){ViewBag.Controller = "Customer";ViewBag.Action = "List";return View("ActionName");}}
上述代码中添加了一个带有string 和 int 类型参数的动作方法Create。为了简单起见,返回一个string类型的结果,这样就不用创建一个视图了。 用Route属性定义的路由混合了静态前缀(Users/Add)以及方法参数对应的user 和 id 片段。为了调用Create方法,MVC框架使用模型绑定特性将片段变量转化成正确的类型。运行效果如下图所示:
运用路由约束
属性路由中的约束更加直接,如下图所示:
public class CustomerController : Controller{[Route("Test")]// GET: Customerpublic ActionResult Index(){ViewBag.Controller = "Customer";ViewBag.Action = "Index";return View("ActionName");}[Route("Users/Add/{user}/{id:int}")]public string Create(string user, int id){return string.Format("User:{0},ID:{1}",user,id);}[Route("Users/Add/{user}/{password}")]public string ChangePass(string user, string password){return string.Format("changePass Method - User:{0}, Pass:{1}",user,password);}public ActionResult List(){ViewBag.Controller = "Customer";ViewBag.Action = "List";return View("ActionName");}}
新的动作方法名称为ChangePass,有两个string类型的参数。但是为了区分Create方法,对Create方法中的Route属性运用了约束,[Route("Users/Add/{user}/{id:int}")],指定 id 接收int类型的请求。 运行效果如下图所示:
组合约束
可以将多个约束运用于一个片段,以便进一步限制路由将要匹配的值的范围,如下图所示:
[Route("Users/Add/{user}/{password:alpha:length(6)}")]public string ChangePass(string user, string password){return string.Format("changePass Method - User:{0}, Pass:{1}",user,password);}
使用Route Prefix
可以使用Route Prefix属性定义一个将被运用到控制器所有路由中的普通前缀,当很多动作都使用同样的根URL为目标是,这点特别有用。如下图所示:
[RoutePrefix("Users")]public class CustomerController : Controller{[Route("~/Test")]// GET: Customerpublic ActionResult Index(){ViewBag.Controller = "Customer";ViewBag.Action = "Index";return View("ActionName");}[Route("Add/{user}/{id:int}")]public string Create(string user, int id){return string.Format("User:{0},ID:{1}",user,id);}[Route("Add/{user}/{password:alpha:length(6)}")]public string ChangePass(string user, string password){return string.Format("changePass Method - User:{0}, Pass:{1}",user,password);}public ActionResult List(){ViewBag.Controller = "Customer";ViewBag.Action = "List";return View("ActionName");}}
运行效果如下图所示:
以~/为前缀告诉MVC框架,不要运用到Index动作方法的RoutePrefix属性,这意味着它仍然可以通过/Test来访问。