.NET MVC 5.2从基本控制器继承属性路由

时间:2014-10-02 19:41:00

标签: asp.net-mvc attributerouting

我有一个基本控制器,其中包含几个我想要使用属性路由的操作,而不必在从基础继承的控制器中覆盖这些方法。

从.NET MVC 5.2开始,这应该是可行的:http://www.asp.net/mvc/overview/releases/whats-new-in-aspnet-mvc-52

提供的示例显示了如何使用类级别属性,但我想在操作级别实现它。有没有人成功实现了动作级别的属性继承? 我看到另一个答案.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();
    }
} 

1 个答案:

答案 0 :(得分:9)

我认为我的操作级别使用以下代码:

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[] { ... };
        }
    }
}