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

问题描述 投票:0回答:1

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

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

提供的示例显示了如何使用类级别属性,但我想在操作级别实现它。有人在操作级别成功实现了属性继承吗? 我看到另一个答案属性路由和继承声称这在 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<IDirectRouteFactory>  
         GetControllerRouteFactories(ControllerDescriptor controllerDescriptor)
    {
        return controllerDescriptor
            .GetCustomAttributes(typeof(InheritedRouteAttribute), inherit: true)
            .Cast<IDirectRouteFactory>()
            .ToArray();
    }
} 
asp.net-mvc attributerouting
1个回答
11
投票

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

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[] { ... };
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.