【问题标题】:.NET MVC 5.2 Inheriting attribute Routes from Base Controller.NET MVC 5.2 从基本控制器继承属性路由
【发布时间】:2014-11-27 21:18:00
【问题描述】:

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

从 .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();
    }
} 

【问题讨论】:

    标签: asp.net-mvc attributerouting


    【解决方案1】:

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

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

    【讨论】:

    • 这适用于 RouteAttribute 定义的操作。如果没有 RouteAttributes 继承动作呢?
    猜你喜欢
    • 2013-12-19
    • 2014-06-14
    • 2014-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多