ASP.NET Web Api: запрашиваемый ресурс не поддерживает метод http 'GET'

У меня есть следующее действие на ApiController:

public string Something()
{
    return "value";
}

И я настроил свои маршруты следующим образом:

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

В бета-версии это сработало отлично, но я только что обновился до последнего кандидата, и теперь я вижу ошибки в таких вызовах:

Запрошенный ресурс не поддерживает метод http 'GET'.

Почему эта работа больше не работает?

(я полагаю, я мог бы избавиться от {action} и просто сделать тонну контроллеров, но это кажется грязным.)

Ответ 1

Если вы не настроили HttpMethod в своем действии в контроллере, предполагается, что это только HttpPost в RC. В Beta предполагается, что он поддерживает все методы - GET, PUT, POST и Delete. Это небольшое изменение от бета-версии до RC. Вы можете легко декорировать более одного метода http вашего действия с помощью [AcceptVerbs ( "GET", "POST" )].

Ответ 2

Вся приведенная выше информация верна, я также хотел бы отметить, что аннотация [AcceptVerbs()] существует как в пространствах имен System.Web.Mvc, так и в System.Web.Http.

Вы хотите использовать System.Web.Http, если это контроллер веб-API.

Ответ 3

Хотя это не ответ на ОП, у меня была такая же ошибка из совершенно другой основной причины; поэтому в случае, если это поможет кому-то еще...

Проблема для меня была некорректно названным параметром метода, который заставил WebAPI направить запрос неожиданно. У меня есть следующие методы в моем ProgrammesController:

[HttpGet]
public Programme GetProgrammeById(int id)
{
    ...
}

[HttpDelete]
public bool DeleteProgramme(int programmeId)
{
    ...
}

Запросы DELETE для... /api/programs/ 3 не были перенаправлены на DeleteProgramme, как я ожидал, но в GetProgrammeById, потому что у DeleteProgramme не было имени параметра id. GetProgrammeById тогда, конечно, отклонял DELETE, поскольку он помечен как только прием GET.

Итак, исправление было простым:

[HttpDelete]
public bool DeleteProgramme(int id)
{
    ...
}

И все хорошо. Глубокая ошибка действительно, но трудно отлаживать.

Ответ 4

Это, безусловно, изменение от Beta до RC. В примере, представленном в вопросе, теперь вам нужно украсить свое действие с помощью [HttpGet] или [AcceptVerbs ( "GET" )].

Это вызывает проблему, если вы хотите смешивать действия на основе глагола (т.е. "GetSomething", "PostSomething" ) с действиями на основе не глагола. Если вы попытаетесь использовать приведенные выше атрибуты, это вызовет конфликт с любым действием на основе глагола в вашем контроллере. Один из способов получить arount, который будет определять отдельные маршруты для каждого глагола, и установить действие по умолчанию на имя глагола. Этот подход может использоваться для определения дочерних ресурсов в вашем API. Например, следующий код поддерживает: "/resource/id/children", где id и children являются необязательными.

        context.Routes.MapHttpRoute(
           name: "Api_Get",
           routeTemplate: "{controller}/{id}/{action}",
           defaults: new { id = RouteParameter.Optional, action = "Get" },
           constraints: new { httpMethod = new HttpMethodConstraint("GET") }
        );

        context.Routes.MapHttpRoute(
           name: "Api_Post",
           routeTemplate: "{controller}/{id}/{action}",
           defaults: new { id = RouteParameter.Optional, action = "Post" },
           constraints: new { httpMethod = new HttpMethodConstraint("POST") }
        );

Надеемся, что будущие версии Web API будут лучше поддерживать этот сценарий. В настоящее время проблема запускается в проекте aspnetwebstack codeplex, http://aspnetwebstack.codeplex.com/workitem/184. Если это то, что вы хотели бы видеть, пожалуйста, проголосуйте по этому вопросу.

Ответ 5

Если вы украшаете свой метод с помощью HttpGet, добавьте следующий using в верхней части контроллера:

using System.Web.Http;

Если вы используете System.Web.Mvc, эта проблема может возникнуть.

Ответ 6

Та же проблема, что и выше, но сильно отличающийся корень. Для меня это было то, что я попал в конечную точку с правилом перезаписи https. Нажатие на http вызвало ошибку, работало, как ожидалось, с помощью https.

Ответ 7

Иметь ту же настройку, что и OP. Один контроллер со многими действиями... менее "грязный": -)

В моем случае я забыл "[HttpGet]" при добавлении нового действия.

[HttpGet]
public IEnumerable<string> TestApiCall()
{
    return new string[] { "aa", "bb" };
}