解读ASP.NET 5 & MVC6系列教程(11):Routing路由(3)

所以,在创建MVC Controller和Web API Controller的时候,如果你不需要相关的上下文(如HTTPContext、ActionContext等)的话,则可以不必继承于Controller基类;但推荐都继承于Controller,因为可以多多利用基类的方法和属性,因为不管继承不继承,你定义的所有Controller类都要走MVC的各个生命周期,我们通过ActionFilter来验证一下:

第一步:在project.json文件的dependencies节点中引用程序集"Microsoft.AspNet.Server.WebListener": "1.0.0-beta3"。
第二步:创建一个Aciton Filter,分别在Action执行前和执行后输出一行文字,代码如下:

public class ActionFilterTest : IActionFilter { public void OnActionExecuting(ActionExecutingContext context) { var typeName = context.Controller.GetType().FullName; Console.WriteLine(typeName + "." + context.ActionDescriptor.Name + ":Start"); } public void OnActionExecuted(ActionExecutedContext context) { var typeName = context.Controller.GetType().FullName; Console.WriteLine(typeName + "." + context.ActionDescriptor.Name + ":END"); } }

第三步:在ConfigureServices方法里注册该Action Filter。

services.Configure<MvcOptions>(options => { options.Filters.Add(typeof(ActionFilterTest)); });

运行程序,并访问响应的路径,三种类型的代码均会按计划输出内容,输出内容如下:

RouterTest.ProductsController.Index:Start RouterTest.ProductsController.Index:End RouterTest.DemoController.Index:Start RouterTest.DemoController.Index:End RouterTest.APIController.Index:Start RouterTest.APIController.Index:End

普通的ASP.NET5程序和MVC程序是可以在一起混合使用Routing功能的。

自定义Route

ASP.NET 5和MVC6都提供了丰富的Route自定义功能,关于普通Route的自定义,可以参考前面小节的DebuggerRouteHandler,这种方式需要实现自己的HTTP输出,相当于原来轻量级的IHttpHandler一样。本节,我们将这种在基于MVC的Route自定义功能,即定义的Route的Handler处理程序都是MvcRouteHandler。

在之前版本的MVC中,要自定义Route,一般都是继承于RouteBase基类或Route类;而在新版的MVC6中,要实现自定义Route,有三种方式,分别如下:

继承于TemplateRoute实现IRouter实现INamedRouter(注:INamedRouter和IRouter的唯一区别是多了一个名称)

本例中,我们以继承继承于TemplateRoute为例,首先创建一个继承于该类的子类PromoTemplateRoute,该类只匹配/promo目录下的路径。

public class PromoTemplateRoute : TemplateRoute { public PromoTemplateRoute(IRouter target, string routeTemplate, IInlineConstraintResolver inlineConstraintResolver) : base(target, routeTemplate, inlineConstraintResolver: inlineConstraintResolver) { } public PromoTemplateRoute(IRouter target, string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, IInlineConstraintResolver inlineConstraintResolver) : base(target, routeTemplate, defaults, constraints, dataTokens, inlineConstraintResolver) { } public PromoTemplateRoute(IRouter target, string routeName, string routeTemplate, IDictionary<string, object> defaults, IDictionary<string, object> constraints, IDictionary<string, object> dataTokens, IInlineConstraintResolver inlineConstraintResolver) : base(target, routeName, routeTemplate, defaults, constraints, dataTokens, inlineConstraintResolver) { } public async override Task RouteAsync(RouteContext context) { var requestPath = context.HttpContext.Request.Path.Value ?? string.Empty; if (!requestPath.StartsWith("/promo", StringComparison.OrdinalIgnoreCase)) { return; } await base.RouteAsync(context); } }

为了方便使用,我们也比葫芦画瓢,创建一些扩展方法,示例如下:

public static class RouteBuilderExtensions { public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template) { MapPromoRoute(routeCollectionBuilder, name, template, defaults: null); return routeCollectionBuilder; } public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template, object defaults) { return MapPromoRoute(routeCollectionBuilder, name, template, defaults, constraints: null, dataTokens: null); } public static IRouteBuilder MapPromoRoute(this IRouteBuilder routeCollectionBuilder, string name, string template, object defaults, object constraints, object dataTokens) { var inlineConstraintResolver = routeCollectionBuilder.ServiceProvider.GetService<IInlineConstraintResolver>(); routeCollectionBuilder.Routes.Add( new PromoTemplateRoute( routeCollectionBuilder.DefaultHandler, name, template, ObjectToDictionary(defaults), ObjectToDictionary(constraints), ObjectToDictionary(dataTokens), inlineConstraintResolver)); return routeCollectionBuilder; } private static IDictionary<string, object> ObjectToDictionary(object value) { var dictionary = value as IDictionary<string, object>; if (dictionary != null) { return dictionary; } return new RouteValueDictionary(value); } }

使用的时候,则很简单,和之前的方式非常类似,示例如下:

routes.MapPromoRoute( name: "default2", template: "promo/{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" });

通过这种方式,我们可以在符合路由匹配条件的时候,使用PromoTemplateRoute类来处理一些自定义逻辑,比如添加一些额外的文件头信息等等。

基于Attribute的Routing

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wjysgd.html