Маршрутизация с использованием нескольких методов Get в веб-API ASP.NET

Я использую Web Api с ASP.NET MVC, и я очень новичок в этом. Я просмотрел демонстрацию на сайте asp.net и пытаюсь сделать следующее.

У меня есть 4 метода получения со следующими подписями

public List<Customer> Get()
{
    // gets all customer
}

public List<Customer> GetCustomerByCurrentMonth()
{
    // gets some customer on some logic
}

public Customer GetCustomerById(string id)
{
    // gets a single customer using id
}

public Customer GetCustomerByUsername(string username)
{
    // gets a single customer using username
}

Для всех вышеперечисленных методов я хотел бы, чтобы мой веб-API был примерно таким, как показано ниже.

  • Список Get () = api/customers/
  • Клиент GetCustomerById (строка Id) = api/customers/13
  • Список GetCustomerByCurrentMonth () = /customers/currentMonth
  • Клиент GetCustomerByUsername (строка имени пользователя) = /customers/customerByUsername/yasser

Я пробовал вносить изменения в маршрутизацию, но, поскольку я новичок в этом, многого не понял.

Итак, пожалуйста, не могли бы кто-нибудь помочь мне понять и подсказать мне, как это должно быть сделано. Спасибо


person Yasser Shaikh    schedule 08.10.2012    source источник
comment
Изучите маршруты и фильтры действий   -  person Daniel Little    schedule 08.10.2012
comment
возможный дубликат контроллера API, объявляющего более одного оператора Get   -  person tpeczek    schedule 08.10.2012


Ответы (8)


Отсюда Маршрутизация в Asp.net Mvc 4 и Web Api

Дарин Димитров опубликовал очень хороший ответ, который работает для меня.

В нем говорится ...

У вас может быть несколько маршрутов:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        config.Routes.MapHttpRoute(
            name: "ApiById",
            routeTemplate: "api/{controller}/{id}",
            defaults: new { id = RouteParameter.Optional },
            constraints: new { id = @"^[0-9]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiByName",
            routeTemplate: "api/{controller}/{action}/{name}",
            defaults: null,
            constraints: new { name = @"^[a-z]+$" }
        );

        config.Routes.MapHttpRoute(
            name: "ApiByAction",
            routeTemplate: "api/{controller}/{action}",
            defaults: new { action = "Get" }
        );
    }
}
person Yasser Shaikh    schedule 08.10.2012
comment
пожалуйста, ознакомьтесь с моим вопросом - person Moeez; 11.10.2017
comment
Очень полезно. Я создал несколько методов Get и не зарегистрировал их в файле WebApiConfig. Получил доступ после регистрации. - person Adi; 30.10.2017

Сначала добавьте новый маршрут с действием вверху:

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

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

Затем используйте атрибут ActionName для сопоставления:

[HttpGet]
public List<Customer> Get()
{
    //gets all customer
}

[ActionName("CurrentMonth")]
public List<Customer> GetCustomerByCurrentMonth()
{
    //gets some customer on some logic
}

[ActionName("customerById")]
public Customer GetCustomerById(string id)
{
    //gets a single customer using id
}

[ActionName("customerByUsername")]
public Customer GetCustomerByUsername(string username)
{
    //gets a single customer using username
}
person cuongle    schedule 08.10.2012
comment
ааа! это выглядит многообещающе, попробую сейчас. - person Yasser Shaikh; 08.10.2012
comment
Пробовал, все работает, кроме api/customers/ и /customers/customerByUsername/yasser какие изменения мне делать - person Yasser Shaikh; 08.10.2012
comment
Я допустил ошибку, о которой идет речь, и исправил ее. пожалуйста, помогите - person Yasser Shaikh; 08.10.2012
comment
также теперь у меня есть два правила маршрутизации в моем методе Register WebApiConfig, первое - это то, которое вы мне дали, а второе - встроенное. Нужно ли мне удалить второе? - person Yasser Shaikh; 08.10.2012
comment
Я все еще получаю 500 Internal Server Error для http://localhost:61821/api/customers/, я очень ценю, что вы помогли мне в этом, пожалуйста, помогите мне снова :) - person Yasser Shaikh; 08.10.2012
comment
@Yasser: этот код я тестировал на VS, какое исключение вы получите? - person cuongle; 08.10.2012
comment
так ли это, позвольте мне создать новый проект и попробовать это, здесь может быть какая-то настройка, которая может повлиять на это. Спасибо - person Yasser Shaikh; 08.10.2012
comment
эти маршруты я должен добавить к WebApiConfig's Register method, верно? - person Yasser Shaikh; 08.10.2012
comment
Это хорошо выглядит на бумаге, но на самом деле не работает. Вам нужно сделать что-то вроде второго ответа на этот пост: stackoverflow.com/questions/9569270/ Хитрость заключается в добавлении ограничения int к параметру id в первом маршруте и установке действия по умолчанию на« Совместно с ограничением HttpGet на второй маршрут - person Levitikon; 01.04.2013
comment
пожалуйста, ознакомьтесь с моим вопросом - person Moeez; 11.10.2017

Также вы укажете маршрут по действию для заданного маршрута

[HttpGet]
[Route("api/customers/")]
public List<Customer> Get()
{
   //gets all customer logic
}

[HttpGet]
[Route("api/customers/currentMonth")]
public List<Customer> GetCustomerByCurrentMonth()
{
     //gets some customer 
}

[HttpGet]
[Route("api/customers/{id}")]
public Customer GetCustomerById(string id)
{
  //gets a single customer by specified id
}
[HttpGet]
[Route("api/customers/customerByUsername/{username}")]
public Customer GetCustomerByUsername(string username)
{
    //gets customer by its username
}
person Lalji Dhameliya    schedule 03.11.2016
comment
Я думаю, что этот ответ прост и понятен, даже если он совместим с .NET Core. Однако повторных префиксов маршрутов можно избежать. См .: stackoverflow.com/questions/12775590/ - person Major; 02.03.2018

На этот вопрос уже есть много хороших ответов. Однако в настоящее время конфигурация маршрутов как бы «устарела». Более новая версия MVC (.NET Core) не поддерживает его. Так что лучше привыкнуть :)

Поэтому я согласен со всеми ответами, в которых используется маршрутизация в стиле атрибутов. Но постоянно замечаю, что все повторяли базовую часть маршрута (api / ...). Лучше применить атрибут [RoutePrefix] поверх класса Controller и не повторять одну и ту же строку снова и снова.

[RoutePrefix("api/customers")]
public class MyController : Controller
{
 [HttpGet]
 public List<Customer> Get()
 {
   //gets all customer logic
 }

 [HttpGet]
 [Route("currentMonth")]
 public List<Customer> GetCustomerByCurrentMonth()
 {
     //gets some customer 
 }

 [HttpGet]
 [Route("{id}")]
 public Customer GetCustomerById(string id)
 {
  //gets a single customer by specified id
 }
 [HttpGet]
 [Route("customerByUsername/{username}")]
 public Customer GetCustomerByUsername(string username)
 {
    //gets customer by its username
 }
}
person Major    schedule 02.03.2018

Для этого достаточно всего одного маршрута

config.Routes.MapHttpRoute("DefaultApiWithAction", "{controller}/{action}");

И нужно указывать атрибут HttpGet или HttpPost во всех действиях.

[HttpGet]
public IEnumerable<object> TestGet1()
{
    return new string[] { "value1", "value2" };
}

[HttpGet]
public IEnumerable<object> TestGet2()
{
    return new string[] { "value3", "value4" };
}
person Palanikumar    schedule 06.11.2013

Возможно, вам не потребуется вносить какие-либо изменения в маршрутизацию. Просто добавьте следующие четыре метода в свой файл customersController.cs:

public ActionResult Index()
{
}

public ActionResult currentMonth()
{
}

public ActionResult customerById(int id)
{
}


public ActionResult customerByUsername(string userName)
{
}

Поместите соответствующий код в метод. С предоставленной маршрутизацией по умолчанию вы должны получить соответствующий результат действия от контроллера на основе действия и параметров для ваших заданных URL-адресов.

Измените маршрут по умолчанию как:

routes.MapRoute(
    "Default", // Route name
    "{controller}/{action}/{id}", // URL with parameters
    new { controller = "Api", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
person Murtuza Kabul    schedule 08.10.2012
comment
Правильно. Именно контроллер отвечает за отображение результатов данного действия. Чтобы методы работали таким образом, вам придется либо переименовать его в customerController, либо изменить маршрут. Если вы хотите сохранить имя контроллера как apicontroller, измените маршрут и установите значение по умолчанию для контроллера Api вместо Home. - person Murtuza Kabul; 08.10.2012
comment
да, я бы хотел оставить имя как есть, подскажите, как написать для этого роутинг? - person Yasser Shaikh; 08.10.2012
comment
Я отредактировал маршрут, посмотрите, как я заменил контроллер по умолчанию с Home на Api - person Murtuza Kabul; 08.10.2012
comment
Мне не нужен индекс в качестве действия в моем контроллере - person Yasser Shaikh; 08.10.2012
comment
Индекс предназначен для вашего url-адреса по умолчанию api / customers /. Вам не нужно указывать индекс в URL-адресе, он автоматически выполнит действие Index, если действие не указано. Смотрите в маршруте, у нас есть действие по умолчанию. - person Murtuza Kabul; 08.10.2012
comment
Я видел измененный вопрос, и для достижения цели потребуется несколько маршрутов. Далее маршруты станут конкретными для действий. - person Murtuza Kabul; 08.10.2012
comment
Примечание: если это ApiController, вам нужно будет использовать routes.MapHttpRoute, а не routes.MapRoute. - person Scotty.NET; 19.12.2013

У меня есть два метода получения с одинаковыми параметрами или без них

[Route("api/ControllerName/FirstList")]
[HttpGet]
public IHttpActionResult FirstList()
{
}

[Route("api/ControllerName/SecondList")]
[HttpGet]
public IHttpActionResult SecondList()
{
}

Просто определите пользовательские маршруты в AppStart=>WebApiConfig.cs => в методе регистрации

config.Routes.MapHttpRoute(
       name: "GetFirstList",
       routeTemplate: "api/Controllername/FirstList"          
       );
config.Routes.MapHttpRoute(
       name: "GetSecondList",
       routeTemplate: "api/Controllername/SecondList"          
       );
person Gaurav Dubey    schedule 06.06.2017

Прочитав множество ответов, я наконец понял.

Сначала я добавил 3 разных маршрута в WebApiConfig.cs

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

    // Web API routes
    config.MapHttpAttributeRoutes();

    config.Routes.MapHttpRoute(
        name: "ApiById",
        routeTemplate: "api/{controller}/{id}",
        defaults: new { id = RouteParameter.Optional },
        constraints: new { id = @"^[0-9]+$" }
    );

    config.Routes.MapHttpRoute(
        name: "ApiByName",
        routeTemplate: "api/{controller}/{action}/{name}",
        defaults: null,
        constraints: new { name = @"^[a-z]+$" }
    );

    config.Routes.MapHttpRoute(
        name: "ApiByAction",
        routeTemplate: "api/{controller}/{action}",
        defaults: new { action = "Get" }
    );
}

Затем удалил ActionName, Route и т. Д. Из функций контроллера. Так что в основном это мой контроллер;

// GET: api/Countries/5
[ResponseType(typeof(Countries))]
//[ActionName("CountryById")]
public async Task<IHttpActionResult> GetCountries(int id)
{
    Countries countries = await db.Countries.FindAsync(id);
    if (countries == null)
    {
        return NotFound();
    }

    return Ok(countries);
}

// GET: api/Countries/tur
//[ResponseType(typeof(Countries))]
////[Route("api/CountriesByName/{anyString}")]
////[ActionName("CountriesByName")]
//[HttpGet]
[ResponseType(typeof(Countries))]
//[ActionName("CountryByName")]
public async Task<IHttpActionResult> GetCountriesByName(string name)
{
    var countries = await db.Countries
            .Where(s=>s.Country.ToString().StartsWith(name))
            .ToListAsync();

    if (countries == null)
    {
        return NotFound();
    }

    return Ok(countries);
}

Теперь я могу работать со следующими образцами URL (с именем и с идентификатором);

http://localhost:49787/api/Countries/GetCountriesByName/France

http://localhost:49787/api/Countries/1

person Salim    schedule 07.07.2017