Маршрутизации веб - АПИ-АПИ/{контроллера}/{действие}/{ИД} "дисфункции" по API/{контроллера}/{ИД}


у меня есть маршрут по умолчанию в Global.асакс:

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

я хотел иметь возможность ориентироваться на определенную функцию, поэтому я создал другой маршрут:

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

Итак, в моем контроллере, у меня есть:

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

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

вызов .../api/records/bycategoryid/5 даст мне то, чего я хочу. Однако, вызов .../api/records/1 даст мне ошибку

найдено несколько действий, которые соответствуют запросу: ...

я понимаю, почему это - маршруты просто определите, какие URL-адреса действительны, но когда дело доходит до сопоставления функций, оба Get(int id) и ByCategoryId(int id) матч api/{controller}/{id}, что смущает рамках.

что мне нужно сделать, чтобы снова запустить маршрут API по умолчанию и сохранить его с {action}? Я думал о создании другого контроллера с именем RecordByCategoryIdController чтобы соответствовать маршруту API по умолчанию, для которого я бы запросил .../api/recordbycategoryid/5. Однако я считаю, что это" грязное " (таким образом, неудовлетворительное) решение. Я посмотрел для ответов на этот и никакой учебник там по использованию маршрута с {action} даже не упоминает эту проблему.

3 87

3 ответа:

механизм маршрута использует ту же последовательность, что и при добавлении в него правил. Как только он получит первое согласованное правило, он перестанет проверять другие правила и примет это для поиска контроллера и действия.

Итак, вы должны:

  1. поставьте свои конкретные правила перед вашими общими правилами(например, по умолчанию), что означает использование RouteTable.Routes.MapHttpRoute для отображения "WithActionApi" сначала, затем "DefaultApi".

  2. удалить defaults: new { id = System.Web.Http.RouteParameter.Optional } параметр вашего " WithActionApi" правило, потому что после того, как идентификатор является необязательным, url-адрес типа "/api/{part1}/{part2}" никогда не переходит в "DefaultApi".

  3. добавьте именованное действие в свой" DefaultApi", чтобы сообщить движку маршрута, какое действие ввести. В противном случае, если у вас есть более одного действия в контроллере, движок не будет знать, какой из них использовать и бросает "было найдено несколько действий, которые соответствуют запросу: ...". Затем, чтобы он соответствовал вашему методу Get, используйте ActionNameAttribute.

так что ваш маршрут должен выглядеть так:

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

и ваш контроллер:

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

вы можете решить вашу проблему с помощью маршрут

контроллер

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

URI в jquery

api/category/1

Настройки Маршруту

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

и ваш маршрут по умолчанию работает по умолчанию маршрутизация на основе соглашения

контроллер

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

URI в Jquery

/api/records/1 

Настройки Маршруту

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

обзор статьи для получения дополнительной информации маршрутизация атрибутов и маршрутизация на основе onvention здесь & этой

попробуйте это.

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 }

        );
    }
}