Могу ли я использовать несколько методов POST в Web API / MVC на одном и том же маршруте? [Дубликат]

Нет вреда для его использования. Вы не получите никакой ошибки. но лучше всего использовать свойство модели.

116
задан abatishchev 25 January 2014 в 08:05
поделиться

9 ответов

Вы можете иметь несколько действий в одном контроллере.

Для этого вам нужно выполнить следующие две вещи.

  • Сначала выполните декорирование с помощью атрибута ActionName, например
     [ActionName("route")]`
     public class VTRoutingController : ApiController
     {
       [ActionName("route")]
       public MyResult PostRoute(MyRequestTemplate routingRequestTemplate)
       {
         return null;
       }
    
      [ActionName("tspRoute")]
      public MyResult PostTSPRoute(MyRequestTemplate routingRequestTemplate)
      {
         return null;
      }
    }
    
  • Вторые определяют следующие маршруты в файле WebApiConfig.
    // Controller Only
    // To handle routes like `/api/VTRouting`
    config.Routes.MapHttpRoute(
        name: "ControllerOnly",
        routeTemplate: "api/{controller}"               
    );
    
    
    // Controller with ID
    // To handle routes like `/api/VTRouting/1`
    config.Routes.MapHttpRoute(
        name: "ControllerAndId",
        routeTemplate: "api/{controller}/{id}",
        defaults: null,
        constraints: new { id = @"^\d+$" } // Only integers 
    );
    
    // Controllers with Actions
    // To handle routes like `/api/VTRouting/route`
    config.Routes.MapHttpRoute(
        name: "ControllerAndAction",
        routeTemplate: "api/{controller}/{action}"
    );
    
132
ответ дан Ehsan Sajjad 22 August 2018 в 17:22
поделиться
  • 1
    работает отлично..... – yogee 3 October 2012 в 21:32
  • 2
    Что делать, если я не хочу устанавливать какие-либо ограничения на тип идентификатора? Значение: как я могу принимать идентификаторы строк? – frapontillo 12 September 2013 в 08:54
  • 3
    @frapontillo: Идентификатор должен быть целым числом, так что он отличается от имени маршрута, иначе маршрутизатор enghine будет рассматривать его как имя действия, а не идентификатор. Если вам нужен идентификатор как строка, вы можете создать действие. – Asif Mushtaq 13 September 2013 в 12:42
  • 4
    Он работает, спасибо человеку .... :) – Tejas Vaishnav 6 February 2015 в 08:21
  • 5
    что-нибудь еще, что нужно проверить, его не работает – Arijit Mukherjee 24 September 2015 в 08:03
  • 6
  • 7
public class Journal : ApiController
{
    public MyResult Get(journal id)
    {
        return null;
    }
}

public class Journal : ApiController
{

    public MyResult Get(journal id, publication id)
    {
        return null;
    }
}

Я не уверен, что перегрузка метода get / post нарушает концепцию restfull api, но это работает. Если бы кто-нибудь мог просветить этот вопрос. Что делать, если у меня есть uri как

uri:/api/journal/journalid
uri:/api/journal/journalid/publicationid

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

0
ответ дан abatishchev 22 August 2018 в 17:22
поделиться

Конечная точка web-api (контроллер) - это единственный ресурс, который принимает команды get / post / put / delete. Это не обычный контроллер MVC.

Обязательно в /api/VTRouting может быть только один метод HttpPost, который принимает параметры, которые вы отправляете. Имя функции не имеет значения , если вы украшаете материал [http]. Я никогда не пробовал.

Изменить: это не работает. При разрешении он, кажется, зависит от количества параметров, а не от попыток привязки модели к типу.

Вы можете перегружать функции для приема разных параметров. Я уверен, что вы были бы в порядке, если бы объявили это так, как вы, но использовали разные (несовместимые) параметры для методов. Если параметры совпадают, вам не повезло, поскольку привязка к модели не будет знать, какой из них вы имели в виду.

[HttpPost]
public MyResult Route(MyRequestTemplate routingRequestTemplate) {...}

[HttpPost]
public MyResult TSPRoute(MyOtherTemplate routingRequestTemplate) {...}

Эта часть работает

Значение по умолчанию шаблон, который они дают при создании нового, делает это довольно явным, и я бы сказал, что вы должны придерживаться этого соглашения:

public class ValuesController : ApiController
{
    // GET is overloaded here.  one method takes a param, the other not.
    // GET api/values  
    public IEnumerable<string> Get() { .. return new string[] ... }
    // GET api/values/5
    public string Get(int id) { return "hi there"; }

    // POST api/values (OVERLOADED)
    public void Post(string value) { ... }
    public void Post(string value, string anotherValue) { ... }
    // PUT api/values/5
    public void Put(int id, string value) {}
    // DELETE api/values/5
    public void Delete(int id) {}
}

Если вы хотите сделать один класс, который делает много вещей, для использования ajax , нет большой причины не использовать стандартный контроллер / шаблон действия. Единственное реальное отличие заключается в том, что ваши сигнатуры методов не такие красивые, и вы должны обернуть вещи в Json( returnValue), прежде чем вы их вернете.

Редактировать:

Перегрузка работает отлично, когда используя стандартный шаблон (отредактированный для включения) при использовании простых типов. Я пошел и протестировал другой путь, с двумя пользовательскими объектами с разными сигнатурами. Никогда не мог заставить его работать.

  • Связывание со сложными объектами не выглядит «глубоким», поэтому no-go
  • Вы можете обойти это, передав extra param, в строке запроса
  • Лучшая запись, чем я могу дать для доступных опций

Это сработало для меня в этом случае, см., где он вас доставит. Исключение только для тестирования.

public class NerdyController : ApiController
{
    public void Post(string type, Obj o) { 
        throw new Exception("Type=" + type + ", o.Name=" + o.Name ); 
    }
}

public class Obj {
    public string Name { get; set; }
    public string Age { get; set; }
}

И вызывается как эта форма консоли:

$.post("/api/Nerdy?type=white", { 'Name':'Slim', 'Age':'21' } )
12
ответ дан Andrew Backer 22 August 2018 в 17:22
поделиться
  • 1
    Я попытался изменить типы параметров, но, похоже, он допускает только один метод Post в контроллере. Спасибо за ваш ответ – Habib 10 July 2012 в 08:35
  • 2
    Я предположил, что он попробует привязку к модели, чтобы найти ее, поскольку вы можете перегружать. Тем не менее, он работает с разными параметрами. Возможно, не так уж сложно переписать его для этого, но они еще не выпустили исходный код, поэтому я просто застрял, глядя на уродливую разборку – Andrew Backer 11 July 2012 в 02:34
  • 3
    +1 для фактического объяснения причины, по которой он не работает, и философии, лежащей в основе web api. – MEMark 4 June 2014 в 21:36

Можно добавить несколько методов Get и Post в один и тот же контроллер веб-API. Здесь default Route вызывает причину. Web API проверяет соответствие маршрута сверху вниз и, следовательно, ваш маршрут по умолчанию для всех запросов. По умолчанию в одном контроллере возможен только один метод Get и Post. Либо поставьте следующий код сверху, либо выведите комментарий / удалить маршрут по умолчанию

    config.Routes.MapHttpRoute("API Default", 
                               "api/{controller}/{action}/{id}",
                               new { id = RouteParameter.Optional });
5
ответ дан Falcon 22 August 2018 в 17:22
поделиться

use:

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

он больше не относится к RESTful, но теперь вы можете вызывать свои действия по имени (вместо того, чтобы веб-API автоматически определял его для вас на основе глагола), как это :

[POST] /api/VTRouting/TSPRoute

[POST] /api/VTRouting/Route

Вопреки распространенному мнению, нет ничего плохого в этом подходе, и он не злоупотребляет веб-API. Вы все еще можете использовать все потрясающие функции Web API (делегирование обработчиков, согласование контента, mediatypeformatters и т. Д.) - вы просто останавливаете подход RESTful.

26
ответ дан Filip W 22 August 2018 в 17:22
поделиться
  • 1
    Спасибо за ответ, но он все равно дает мне ту же ошибку. – Habib 10 July 2012 в 08:11
  • 2
    Это невозможно, тогда что-то еще должно быть неправильно сконфигурировано в вашем приложении. Можете ли вы показать всю настройку маршрута? Также как точно вы вызываете действия контроллеров? – Filip W 10 July 2012 в 08:22
  • 3
    Вся настройка маршрута находится в global.asax, у меня есть эта часть в моем вопросе. Для получения запроса я использую Fiddler- & gt; Compose- & gt; и выбрав «Почта» в качестве операции – Habib 10 July 2012 в 08:30
  • 4
    сделал это, не работает – Habib 10 July 2012 в 08:39
  • 5
    Филипп, я использую .Net framework 4.5, с mvc4 или Visual studio 2012 RC, какой шаблон вы используете для создания своего проекта, ваш работает отлично – Habib 10 July 2012 в 10:38

Лучшим решением вашей проблемы было бы использовать Route, который позволяет указать маршрут по методу путем аннотации:

[RoutePrefix("api/VTRouting")]
public class VTRoutingController : ApiController
{
    [HttpPost]
    [Route("Route")]
    public MyResult Route(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }

    [HttpPost]
    [Route("TSPRoute")]
    public MyResult TSPRoute(MyRequestTemplate routingRequestTemplate)
    {
        return null;
    }
}
21
ответ дан Marcos Dimitrio 22 August 2018 в 17:22
поделиться

Я просто добавил «action = action_name» в url, и таким образом движок маршрутизации знает, какое действие я хочу. Я также добавил атрибут ActionName к действиям, но я не уверен, что это необходимо.

0
ответ дан Rony Tesler 22 August 2018 в 17:22
поделиться

Поместите префикс маршрута [RoutePrefix («api / Profiles»)] на уровне контроллера и поместите маршрут в метод действия [Route («LikeProfile»)]. Не нужно ничего менять в файле global.asax

namespace KhandalVipra.Controllers
{
    [RoutePrefix("api/Profiles")]
    public class ProfilesController : ApiController
    {
        // POST: api/Profiles/LikeProfile
        [Authorize]
        [HttpPost]
        [Route("LikeProfile")]
        [ResponseType(typeof(List<Like>))]
        public async Task<IHttpActionResult> LikeProfile()
        {
        }
    }
}
1
ответ дан Sushil Kumar 22 August 2018 в 17:22
поделиться

Я думаю, на этот вопрос уже был дан ответ. Я также искал что-то для контроллера webApi, у которого есть те же сигнатурные mehtods, но с разными именами. Я пытался реализовать Калькулятор как WebApi. Калькулятор имеет 4 метода с одной и той же подписью, но с разными именами.

public class CalculatorController : ApiController
{
    [HttpGet]
    [ActionName("Add")]
    public string Add(int num1 = 1, int num2 = 1, int timeDelay = 1)
    {
        Thread.Sleep(1000 * timeDelay);
        return string.Format("Add = {0}", num1 + num2);
    }

    [HttpGet]
    [ActionName("Sub")]
    public string Sub(int num1 = 1, int num2 = 1, int timeDelay = 1)
    {
        Thread.Sleep(1000 * timeDelay);
        return string.Format("Subtract result = {0}", num1 - num2);
    }

    [HttpGet]
    [ActionName("Mul")]
    public string Mul(int num1 = 1, int num2 = 1, int timeDelay = 1)
    {
        Thread.Sleep(1000 * timeDelay);
        return string.Format("Multiplication result = {0}", num1 * num2);
    }

    [HttpGet]
    [ActionName("Div")]
    public string Div(int num1 = 1, int num2 = 1, int timeDelay = 1)
    {
        Thread.Sleep(1000 * timeDelay);
        return string.Format("Division result = {0}", num1 / num2);
    }
}

и в файле WebApiConfig у вас уже есть

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

Просто установите аутентификацию / авторизацию на IIS, и все готово!

Надеюсь, что это помогает!

0
ответ дан Yawar Murtaza 22 August 2018 в 17:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: