2014-10-02 83 views
2

我有一個基礎控制器,它包含幾個我想使用屬性路由的動作,而不必在從基礎繼承的控制器中重寫這些方法。.NET MVC 5.2繼承基本控制器的屬性路由

由於.NET MVC 5.2本應根據此可能:http://www.asp.net/mvc/overview/releases/whats-new-in-aspnet-mvc-52

提供的示例展示瞭如何使用一個類級別的屬性,但我想在行動層面Implment它。有沒有人成功實現了動作級別的屬性繼承? 我看到另一個答案.NET WebAPI Attribute Routing and inheritance聲稱這是可能的與Web API控制器,但它可以完成使用標準的MVC控制器?

[InheritedRoute("attributerouting/{controller}/{action=Index}/{id?}")] 
public abstract class BaseController : Controller 
{ 
} 
public class BlogController : BaseController 
{ 
    public string Index() 
    { 
     return "Hello from blog!"; 
    } 
} 
public class StoreController : BaseController 
{ 
    public string Index() 
    { 
     return "Hello from store!"; 
    } 
} 
[AttributeUsage(AttributeTargets.Class, Inherited=true, AllowMultiple=true)] 
public class InheritedRouteAttribute : Attribute, IDirectRouteFactory 
{ 
    public InheritedRouteAttribute(string template) 
    { 
     Template=template; 
    } 
    public string Name { get; set; } 
    public int Order { get; set; } 
    public string Template { get; private set; } 
    public new RouteEntry CreateRoute(DirectRouteFactoryContext context) 
    { 
     // context.Actions will always contain at least one action - and all of the 
     // actions will always belong to the same controller. 
     var controllerDescriptor=context.Actions.First().ControllerDescriptor; 
     var template=Template.Replace("{controller}", 
      controllerDescriptor.ControllerName); 
     IDirectRouteBuilder builder=context.CreateBuilder(template); 
     builder.Name=Name; 
     builder.Order=Order; 
     return builder.Build(); 
    } 
} 
// Custom direct route provider which looks for route attributes of type 
// InheritedRouteAttribute and also supports attribute route inheritance. 
public class InheritedDirectRouteProvider : DefaultDirectRouteProvider 
{ 
    protected override IReadOnlyList 
     GetControllerRouteFactories(ControllerDescriptor controllerDescriptor) 
    { 
     return controllerDescriptor 
      .GetCustomAttributes(typeof(InheritedRouteAttribute), inherit: true) 
      .Cast() 
      .ToArray(); 
    } 
} 

回答

8

我覺得我有行動水平與下面的代碼工作:

public class InheritedDirectRouteProvider : DefaultDirectRouteProvider 
{ 
    protected override IReadOnlyList<IDirectRouteFactory> 
     GetActionRouteFactories(ActionDescriptor actionDescriptor) 
    { 
     return actionDescriptor.GetCustomAttributes(typeof(IDirectRouteFactory), inherit: true).Cast<IDirectRouteFactory>().ToArray(); 
    } 
} 

,並呼籲:

routes.MapMvcAttributeRoutes(new InheritedDirectRouteProvider()); 

這讓我從一個抽象的控制器繼承控制器及其程序,簡化示例:

// Inherited class needs to define [RoutePrefix("childPrefix")] 
public abstract class ChildBaseController<TChildEntity> : BaseController where TChildEntity : ChildEntity 
{ 
    public ChildBaseController(IUnitOfWork DAL) : base(DAL) { } 

    protected abstract GenericChildRepository<TChildEntity> ChildRepository { get; } 
    protected abstract string[] GetCreateBindFields(); 
    protected abstract string[] GetEditBindFields(); 

    [Route("{valueId}")] 
    public ActionResult Index(int valueId) 
    { 
     ViewBag.ValueId = valueId; 
     return View(ChildRepository.Get().Where(cr => cr.ValueId == valueId)); 
    } 

    ... bunch more CRUD actions with [Route(...)] ... 
} 

繼承人分類:

namespace Web.Frontend.Controllers 
{ 
    [RoutePrefix("Fields")] 
    public class FieldsController : ChildBaseController<Field> 
    { 
     public FieldsController(IUnitOfWork DAL) : base(DAL) { } 

     protected override GenericChildRepository<Field> ChildRepository 
     { 
      get 
      { 
       return DAL.Fields; 
      } 
     } 
     protected override string[] GetCreateBindFields() 
     { 
      return new string[] { ... }; 
     } 
     protected override string[] GetEditBindFields() 
     { 
      return new string[] { ... }; 
     } 
    } 
}