.NET MVC 5.2 Inheriting Attribute Routes from Base Controller

I have a base controller that contains several actions that I would like to use attribute routing on, and should not override these methods in controllers that inherit from the base.

As of .NET MVC 5.2 it should be possible according to this: http://www.asp.net/mvc/overview/releases/whats-new-in-aspnet-mvc-52

The example provided shows how to use a class level attribute, but I would like to Imitate it at the action level. Has anyone successfully implemented action level attribute inheritance? I see another answer. .NET WebAPI Attribute Routing and Inheritance claims that this is possible with Web API controllers, but can it be done with a standard MVC controller?

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

      

+3


source to share


1 answer


I think I have an action layer working with the following code:

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

      

and call:

routes.MapMvcAttributeRoutes(new InheritedDirectRouteProvider());

      



this allows me to inherit a controller and its procedures from an abstract controller, a simplified example:

// 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(...)] ...
}

      

inherited class:

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

      

+9


source







All Articles