it-swarm.com.de

Web-API-Routing - API / {Controller} / {Aktion} / {ID} "Funktionsstörungen" API / {Controller} / {ID}

Ich habe die Standardroute in Global.asax:

 RouteTable.Routes.MapHttpRoute(
         name: "DefaultApi",
         routeTemplate: "api/{controller}/{id}",
         defaults: new { id = System.Web.Http.RouteParameter.Optional }
         );

Ich wollte in der Lage sein, auf eine bestimmte Funktion abzuzielen, deshalb habe ich eine andere Route erstellt:

RouteTable.Routes.MapHttpRoute(
         name: "WithActionApi",
         routeTemplate: "api/{controller}/{action}/{id}",
         defaults: new { id = System.Web.Http.RouteParameter.Optional }
         );

Also habe ich in meinem Controller:

    public string Get(int id)
    {
        return "object of id id";
    }        

    [HttpGet]
    public IEnumerable<string> ByCategoryId(int id)
    {
        return new string[] { "byCategory1", "byCategory2" };
    }

Wenn ich .../api/records/bycategoryid/5 Anrufe, bekomme ich, was ich will. Wenn ich jedoch .../api/records/1 Aufrufe, erhalte ich den Fehler

Es wurden mehrere Aktionen gefunden, die der Anfrage entsprechen: ...

Ich verstehe, warum das so ist - die Routen definieren nur, welche URLs gültig sind, aber wenn es um die Funktionsübereinstimmung geht, stimmen sowohl Get(int id) als auch ByCategoryId(int id) mit api/{controller}/{id} Überein verwirrt den Rahmen.

Was muss ich tun, damit die Standard-API-Route wieder funktioniert und die mit {action} Beibehalten wird? Ich dachte daran, einen anderen Controller mit dem Namen RecordByCategoryIdController zu erstellen, der der Standard-API-Route entspricht, für die ich .../api/recordbycategoryid/5 Anfordern würde. Ich finde jedoch, dass dies eine "schmutzige" (also unbefriedigende) Lösung ist. Ich habe nach Antworten zu diesem Thema gesucht und kein Tutorial zur Verwendung einer Route mit {action} Erwähnt dieses Problem.

92
Mickael Caruso

Das Routenmodul verwendet die gleiche Reihenfolge, in der Sie Regeln hinzufügen. Sobald es die erste übereinstimmende Regel erhält, hört es auf, andere Regeln zu überprüfen und sucht nach Controller und Aktion.

Deshalb solltest du:

  1. Stellen Sie Ihre spezifischen Regeln vor Ihre allgemeinen Regeln (wie die Standardregeln), was bedeutet, dass Sie RouteTable.Routes.MapHttpRoute zuerst "WithActionApi", dann "DefaultApi" zuordnen.

  2. Entferne das defaults: new { id = System.Web.Http.RouteParameter.Optional } -Parameter Ihrer "WithActionApi" -Regel, da eine einmal optionale ID die URL "/ api/{part1}/{part2}" niemals in "DefaultApi" einfügt.

  3. Fügen Sie Ihrem "DefaultApi" eine benannte Aktion hinzu, um dem Routenmodul mitzuteilen, welche Aktion eingegeben werden soll. Wenn Sie mehr als eine Aktion in Ihrem Controller haben, weiß die Engine nicht, welche verwendet werden soll, und gibt den Befehl "Es wurden mehrere Aktionen gefunden, die der Anforderung entsprechen: ..." aus. Verwenden Sie anschließend ein ActionNameAttribute , damit es mit Ihrer Get-Methode übereinstimmt.

Ihre Route sollte also so aussehen:

// Map this rule first
RouteTable.Routes.MapRoute(
     "WithActionApi",
     "api/{controller}/{action}/{id}"
 );

RouteTable.Routes.MapRoute(
    "DefaultApi",
    "api/{controller}/{id}",
    new { action="DefaultAction", id = System.Web.Http.RouteParameter.Optional }
);

Und dein Controller:

[ActionName("DefaultAction")] //Map Action and you can name your method with any text
public string Get(int id)
{
    return "object of id id";
}        

[HttpGet]
public IEnumerable<string> ByCategoryId(int id)
{
    return new string[] { "byCategory1", "byCategory2" };
}
101
Chris Li

Sie können Ihr Problem mit Hilfe des Attribut-Routings lösen

Controller

[Route("api/category/{categoryId}")]
public IEnumerable<Order> GetCategoryId(int categoryId) { ... }

URI in Abfrage

api/category/1

Routenkonfiguration

using System.Web.Http;

namespace WebApplication
{
    public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            // Web API routes
            config.MapHttpAttributeRoutes();

            // Other Web API configuration not shown.
        }
    }
}

und Ihr Standardrouting funktioniert als standardmäßiges konventionelles Routing

Controller

public string Get(int id)
    {
        return "object of id id";
    }   

URI in Jquery

/api/records/1 

Routenkonfiguration

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Attribute routing.
        config.MapHttpAttributeRoutes();

        // Convention-based routing.
        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional }
        );
    }
}

Weitere Informationen finden Sie im Artikel Attribut-Routing und erfindungsbezogenes Routing hier & this

36
MSTdev

Der mögliche Grund kann auch sein, dass Sie Controller nicht von ApiController geerbt haben. Es hat eine Weile gedauert, bis ich dasselbe verstanden habe.

0
Paritosh Tiwari

Versuche dies.

public class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services

        var json = config.Formatters.JsonFormatter;
        json.SupportedMediaTypes.Add(new System.Net.Http.Headers.MediaTypeHeaderValue("application/json"));
        config.Formatters.Remove(config.Formatters.XmlFormatter);

        // Web API routes
        config.MapHttpAttributeRoutes();

        config.Routes.MapHttpRoute(
            name: "DefaultApi",
            routeTemplate: "api/{controller}/{action}/{id}",
            defaults: new { id = RouteParameter.Optional , Action =RouteParameter.Optional }

        );
    }
}
0
Amit

Um die Routen zu unterscheiden, fügen Sie eine Einschränkung hinzu, dass die ID numerisch sein muss:

RouteTable.Routes.MapHttpRoute(
         name: "DefaultApi",
         routeTemplate: "api/{controller}/{id}",
         constraints: new { id = @"\d+" }, // Only matches if "id" is one or more digits.
         defaults: new { id = System.Web.Http.RouteParameter.Optional }
         );  
0
Derek Wade