Web API Yönlendirmesi - api / {controller} / {action} / {id} "dysfunctions" api / {controller} / {id}


94

Global.asax'ta varsayılan Rotam var:

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

Belirli bir işlevi hedefleyebilmek istedim, bu yüzden başka bir rota oluşturdum:

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

Yani, denetleyicimde:

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

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

Aramak .../api/records/bycategoryid/5bana istediğimi verecektir. Ancak, aramak .../api/records/1bana hatayı verecek

İstekle eşleşen birden çok işlem bulundu: ...

Bunun nedenini anlıyorum - rotalar sadece hangi URL'lerin geçerli olduğunu tanımlar, ancak iş eşleştirme Get(int id)ve ByCategoryId(int id)eşleştirme api/{controller}/{id}söz konusu olduğunda çerçeveyi karıştıran şey budur .

Varsayılan API yolunun tekrar çalışması için ne yapmalıyım ve birini devam ettirmeliyim {action}? İstediğim RecordByCategoryIdControllervarsayılan API yoluyla eşleşecek şekilde adlandırılmış farklı bir denetleyici oluşturmayı düşündüm .../api/recordbycategoryid/5. Bununla birlikte, bunu "kirli" (dolayısıyla yetersiz) bir çözüm olarak görüyorum. Bununla ilgili cevapları aradım ve {action}bu sorundan bahseden bir rota kullanma konusunda hiçbir öğretici yok .

Yanıtlar:


105

Rota motoru, içine kurallar eklediğinizle aynı sırayı kullanır. İlk eşleşen kuralı aldığında, diğer kuralları kontrol etmeyi bırakacak ve bunu denetleyici ve eylemi aramak için kullanacaktır.

Yani, şunları yapmalısınız:

  1. Belirli kurallarınızı genel kurallarınızın önüne koyun (varsayılan gibi); bu, RouteTable.Routes.MapHttpRouteönce "WithActionApi", ardından "DefaultApi" eşlemesini kullanmak anlamına gelir .

  2. defaults: new { id = System.Web.Http.RouteParameter.Optional }"WithActionApi" kuralınızın parametresini kaldırın, çünkü kimlik isteğe bağlı olduğunda, "/ api / {part1} / {part2}" gibi url hiçbir zaman "DefaultApi" ye gitmez.

  3. Rota motoruna hangi eylemin girileceğini söylemek için "DefaultApi" nize adlandırılmış bir eylem ekleyin. Aksi takdirde, denetleyicinizde birden fazla eyleminiz olduğunda, motor hangisinin kullanılacağını bilemez ve "istekle eşleşen birden çok eylem bulundu: ..." seçeneğini atar. Daha sonra Get yönteminizle eşleşmesini sağlamak için bir ActionNameAttribute kullanın .

Yani rotanız şöyle olmalı:

// 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 }
);

Ve denetleyiciniz:

[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" };
}

1
Yukarıdaki tavsiyeyi denedim ve her şey beklendiği gibi çalışıyor. Bu "sır" için çok teşekkür ederim.
Mickael Caruso

Cevabınızın 2. noktasında id, isteğe bağlıysa , rota için eşleşen bir eylem bulunmazsa, URL benzeri /api/{part1}/{part2}yol yine de DefaultApirotaya girebilir WithActionApi. Yanılıyorsam lütfen beni düzeltin.
orad

sadece api / {controller} / {action} sahibi olmak istersem ne olur. kimliği olmadan. Başka biri aynı sorunla karşı karşıyaysa. WebApiConfig'i unutun. Attribute Routing hakkında bilgi edinin.
ahsant

40

Sorununuzu Öznitelik yönlendirme yardımıyla çözebilirsiniz

Kontrolör

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

Jquery'de URI

api/category/1

Rota Yapılandırması

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.
        }
    }
}

ve varsayılan yönlendirmeniz varsayılan kural tabanlı yönlendirme olarak çalışıyor

Kontrolör

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

Jquery'de URI

/api/records/1 

Rota Yapılandırması

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

Daha fazla bilgi için Gözden makale Özellik yönlendirme ve burada yönlendirme Sözleflme tabanlı & bu


tanrı cevap. ancak api / {controller} / {id} ile birlikte api / {controller} / {action} / {id} ekleyemez miyiz?
karim

Öznitelik yönlendirme sorunu kesinlikle çözer. Önemli bir nokta: Web API 2'den önce, Web API proje şablonları şu şekilde kod üretti: korumalı void Application_Start () {WebApiConfig.Register (GlobalConfiguration.Configuration); } Öznitelik yönlendirmesi etkinleştirilirse, bu kod bir istisna atar. Öznitelik yönlendirmeyi kullanmak için var olan bir Web API projesini yükseltirseniz, bu yapılandırma kodunu aşağıdakilere güncellediğinizden emin olun: korumalı void Application_Start () {GlobalConfiguration.Configure (WebApiConfig.Register); }
Deeb

0

Bunu dene.

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

Olası neden, Denetleyiciyi ApiController'den devralmamış olmanız da olabilir. Benimle aynı şeyi anlamak biraz zaman aldı.


0

Rotaları farklılaştırmak için kimliğin sayısal olması gereken bir kısıtlama eklemeyi deneyin:

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 }
         );  
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.