wake-up-neo.com

Weiterleitung und Vererbung von Attributen

Ich spiele mit der Idee, einen Basis-Controller zu haben, der ein generisches Repository verwendet, um die grundlegenden CRUD-Methoden für meine API-Controller bereitzustellen, damit ich nicht in jedem neuen Controller denselben Basis-Code duplizieren muss. Es treten jedoch Probleme mit dem Routing-Attribut auf, das im Basis-Controller erkannt wird. Um genau zu zeigen, was für ein Problem ich habe, habe ich einen wirklich einfachen WebAPI-Controller erstellt.

Wenn ich eine Get -Methode im Haupt-Controller habe und diese direkt von ApiController erbt, habe ich keine Probleme und das funktioniert wie erwartet.

[RoutePrefix("admin/test")]
public class TestController : ApiController
{
    [Route("{id:int:min(1)}")]
    public string Get(int id)
    {
        return "Success";
    }
}

Wenn ich die Get -Methode in einen Basiscontroller verschiebe, gibt sie den Inhalt der 404-Seite zurück.

[RoutePrefix("admin/test")]
public class TestController : TestBaseController
{

}

public class TestBaseController : ApiController
{
    [Route("{id:int:min(1)}")]
    public string Get(int id)
    {
        return "Success";
    }
}

Einige weitere interessante Hinweise:

  • Ich kann die Aktion unter GET/Test/1 Aufrufen. Es wird also immer noch basierend auf der Standardroute gefunden.

  • Wenn ich versuche, auf POST/admin/test Zuzugreifen, wird der folgende JSON zurückgegeben

    {"Message": "Es wurde keine HTTP-Ressource gefunden, die mit dem Anforderungs-URI ' http://test.com/admin/test ' übereinstimmt.", "MessageDetail": "Es wurde kein Typ gefunden, der übereinstimmt der Controller mit dem Namen "admin". " }

Kennt jemand eine Möglichkeit, um das Routing mit Attributen von einem Basiscontroller arbeiten zu lassen?

63
Jeff Treuting

Attributrouten können nicht vererbt werden. Dies war eine bewusste Designentscheidung. Wir fühlten uns nicht richtig und sahen keine gültigen Szenarien, in denen es sinnvoll wäre, sie zu erben.

Könnten Sie ein realistischeres Szenario angeben, in dem Sie dies verwenden möchten?

[ Update(24.03.2014)]
In der kommenden Version 5.2 von MVC Web API wird es einen Erweiterungspunkt mit dem Namen System.Web.Http.Routing.IDirectRouteProvider, über das Sie das hier gesuchte Vererbungsszenario aktivieren können. Sie können dies selbst mit den neuesten Nacht-Builds versuchen (die Dokumentation zur Verwendung von Nacht-Builds finden Sie hier )

[ Update(31.07.2014)]
Beispiel dafür, wie dies in der Web-API 2.2 Freisetzung:

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());

//---------

public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> 
    GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        // inherit route attributes decorated on base class controller's actions
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
        (inherit: true);
    }
}
77
Kiran Challa

Mit der Web-API 2.2 können Sie:

public class BaseController : ApiController
{
    [Route("{id:int}")]
    public string Get(int id)
    {
        return "Success:" + id;
    }
}
[RoutePrefix("api/values")]
public class ValuesController : BaseController
{
}

config.MapHttpAttributeRoutes(new CustomDirectRouteProvider());
public class CustomDirectRouteProvider : DefaultDirectRouteProvider
{
    protected override IReadOnlyList<IDirectRouteFactory> 
    GetActionRouteFactories(HttpActionDescriptor actionDescriptor)
    {
        return actionDescriptor.GetCustomAttributes<IDirectRouteFactory>
        (inherit: true);
    }
}

wie hier beschrieben: http://www.asp.net/web-api/overview/releases/whats-new-in-aspnet-web-api-22

25
Dejan

Ich habs.

[Route("api/baseuploader/{action}")]
public abstract class BaseUploaderController : ApiController
{
    [HttpGet] 
    public string UploadFile() 
    {
        return "UploadFile";
    }
}


[Route("api/values/{action}")]
public class ValuesController : BaseUploaderController
{
    [HttpGet]
    public string Get(int id)
    {
        return "value";
    }
}

Eine Einschränkung hierbei ist, dass der Routenaktionsparameter mit dem Aktionsnamen identisch sein muss. Ich konnte keinen Weg finden, das zu umgehen. (Sie können die Route nicht mit einem RouteAttribute umbenennen.)

3
parliament