405 метод запрещен Веб-API

89

Эта ошибка очень распространена, я попробовал все решения, и ни одно из них не сработало. Я отключил публикацию WebDAV в панели управления и добавил это в свой файл веб-конфигурации:

  <handlers>
  <remove name="WebDAV"/>
  </handlers>
  <modules runAllManagedModulesForAllRequests="true">
  <remove name="WebDAVModule"/>
  </modules>

Ошибка по-прежнему сохраняется. Это контроллер:

   static readonly IProductRepository repository = new ProductRepository();

    public Product Put(Product p)
    {
        return repository.Add(p);
    }

Реализация метода:

 public Product Add(Product item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }
        item.Id = _nextId++;
        products.Add(item);
        return item;
    }

И здесь возникает исключение:

client.BaseAddress = new Uri("http://localhost:5106/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));      
var response = await client.PostAsJsonAsync("api/products", product);//405 exception

Какие-либо предложения?

Xardas
источник

Ответы:

61

Вы отправляете сообщение от клиента:

await client.PostAsJsonAsync("api/products", product);

не ставить.

Ваш метод веб-API принимает только запросы PUT.

Так:

await client.PutAsJsonAsync("api/products", product);
Дарин Димитров
источник
Ошибка «HttpClient» не содержит определения для «PostAsJsonAsync», выдается при попытке вашего кода.
agileDev
61

У меня было такое же исключение. Моя проблема заключалась в том, что я использовал:

using System.Web.Mvc; // Wrong namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}

ДОЛЖНО БЫТЬ

using System.Web.Http; // Correct namespace for HttpGet attribute !!!!!!!!!
[HttpGet]
public string Blah()
{
    return "blah";
}
Llad
источник
18

Я пробовал много всего, чтобы заставить работать метод DELETE (я получал 405 метод, не разрешенный веб-API), и, наконец, я добавил [Route ("api / scan / {id}")] в свой контроллер, и все заработало. надеюсь, что этот пост кому-то поможет.

     // DELETE api/Scan/5
    [Route("api/scan/{id}")]
    [ResponseType(typeof(Scan))]
    public IHttpActionResult DeleteScan(int id)
    {
        Scan scan = db.Scans.Find(id);
        if (scan == null)
        {
            return NotFound();
        }

        db.Scans.Remove(scan);
        db.SaveChanges();

        return Ok(scan);
    }
user2662006
источник
По какой-то причине у меня это не работало только для удаления, для создания и обновления все работало нормально. Я только что добавил [HttpPost], и это сработало. Но спасибо, вы привели меня на правильный путь и стоили мне всего 5 минут :)
Rubenisme
1
Почему вы просто не добавляете атрибут [HttpDelete]?
Джонни 5
14

Моя проблема оказалась в маршрутизации атрибутов в WebAPI. Я создал собственный маршрут, и он обработал его как GET, а не WebAPI, обнаружив, что это POST

    [Route("")]
    [HttpPost] //I added this attribute explicitly, and it worked
    public void Post(ProductModel data)
    {
        ...
    }

Я знал, что это должно быть что-то глупое (это занимает весь ваш день)

Nexxas
источник
Это спасло мне день!
Phate01,
6

Chrome часто пытается OPTIONSпозвонить перед публикацией. Это делается для того, чтобы заголовки CORS были в порядке. Это может быть проблематично, если вы не обрабатываете OPTIONSвызов в своем контроллере API.

public void Options() { }
Нейт Заугг
источник
6

Эта ошибка также может возникнуть, когда вы пытаетесь подключиться к http, когда сервер находится на https.

Это немного сбивало с толку, потому что мои запросы на получение были в порядке, проблема была только с пост-запросами.

ФрэнкиГолливуд
источник
4

Я получал 405 при вызове GET, и проблема оказалась в том, что я назвал параметр в методе GET на стороне сервера Get(int formId), и мне нужно было изменить маршрут или переименовать его Get(int id).

Sako73
источник
4

Вы также можете получить ошибку 405, если скажете, что ваш метод ожидает параметр, а вы его не передаете.

Это НЕ работает (ошибка 405)

Просмотр HTML / Javascript

$.ajax({
         url: '/api/News',
         //.....

Веб-API:

public HttpResponseMessage GetNews(int id)

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

Просмотр HTML / Javascript

$.ajax({
         url: '/api/News/5',
         //.....
Том Стикель
источник
Кажется, у меня возникают ошибки 405 по разным причинам, все они сводятся к тому факту, что он пытается УДАЛИТЬ сигнатуру метода и проблему с параметром, или проблему с именованием соглашения, или проблему с атрибутами и т. Д.
Том Стикель,
4

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

На сервере, на котором размещался сайт / сервис, требовалась функция! АКТИВАЦИЯ HTTP !!!

Диспетчер серверов> Управление> Добавить роли и компоненты> далее, затем, пока вы не дойдете до Функции> Под .NET (для каждой версии), отметьте HTTP-активация. Также обратите внимание, что есть один скрытый в> net> WCF Services.

Это сработало мгновенно! Это плавило мой мозг

Монолитный код
источник
4

Если у вас есть маршрут вроде

[Route("nuclearreactors/{reactorId}")]

Вам нужно использовать то же самое имя параметра в методе, например

public ReactorModel GetReactor(reactorId)
{
 ...
}

Если вы не передадите тот же самый параметр, вы можете получить ошибку «405 метод не разрешен», потому что маршрут не будет соответствовать запросу, и WebApi будет использовать другой метод контроллера с другим разрешенным методом HTTP.

Roylac
источник
Это тоже не ответ!
Divyang Desai 01
@Div «Метод 405 не разрешен» может быть показан в случае, который я поделился, потому что метод не будет ловить api-call, поскольку настройка маршрута недействительна. Затем вызов api может поразить другой непредусмотренный метод, для которого может быть разрешено другое действие HTTP. Да, я согласен с тем, что этот ответ может быть не на 100% релевантным для фактического вопроса, однако название вопроса Ксардасом не очень конкретное, и я считаю, что многие люди, попадающие сюда в поисках ответов на вопрос, как указано в заголовке, могут считаю этот ответ полезным.
roylac 01
3

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

Проблема заключалась в том, что я намеренно объявил свой метод Get статическим . Я пропустил это всю полдень, и никаких предупреждений от атрибутов и т.п. не было.

Неправильно:

public class EchoController : ApiController
{
    public static string Get()
    {
        return string.Empty;
    }
}

Верный:

public class EchoController : ApiController
{
    public string Get()
    {
        return string.Empty;
    }
}
Пер Штольпе
источник
2

[HttpPost] не нужен!

[Route("")]
public void Post(ProductModel data)
{
    ...
}
user3963793
источник
1
Да, способ, которым вы это делаете, является правильным в том смысле, что вам не нужен явный [HttpPost], однако есть некоторые люди, не соблюдающие соглашение (yikes) и, следовательно, что-то вроде [Route ("MyMethodSaver"] публичная строка MyMethodtoSave (int? id) -> для этого потребуется [HttpPost], и тогда он будет работать
Том Стикель
2

Я НЕ мог решить эту проблему. У меня был включен CORS, и он работал, пока POST не возвращал void (ASP.NET 4.0 - WEBAPI 1). Когда я попытался вернуть HttpResponseMessage, я начал получать ответ HTTP 405.

Основываясь на ответе Ллада выше, я взглянул на свои собственные ссылки.

У меня был атрибут [System.Web.Mvc.HttpPost], указанный выше моего метода POST.

Я изменил это на использование:

[System.Web.Http.HttpPostAttribute]
[HttpOptions]
public HttpResponseMessage Post(object json)        
{
    ...
    return new HttpResponseMessage { StatusCode = HttpStatusCode.OK };
}

Это устранило мои беды. Надеюсь, это поможет кому-то другому.

Для полноты картины в моем web.config было следующее:

<httpProtocol>
    <customHeaders>
        <clear />
        <add name="Access-Control-Expose-Headers " value="WWW-Authenticate"/>
        <add name="Access-Control-Allow-Origin" value="*" />
        <add name="Access-Control-Allow-Methods" value="GET, POST, OPTIONS, PUT, PATCH, DELETE" />
        <add name="Access-Control-Allow-Headers" value="accept, authorization, Content-Type" />
        <remove name="X-Powered-By" />
    </customHeaders>
</httpProtocol>
Спенсер Салливан
источник
Это будет иметь метод, вызываемый в предполетном запросе OPTIONS (а также при POST), что jsonвполне вероятно, nullпоскольку предполетные запросы обычно не имеют полезных данных, или вы дважды запустите действие публикации.
glennsl 03
1

У нас была аналогичная проблема. Мы пытались ПОЛУЧИТЬ из:

[RoutePrefix("api/car")]
public class CarController: ApiController{

    [HTTPGet]
    [Route("")]
    public virtual async Task<ActionResult> GetAll(){

    }

}

Так мы бы .GET("/api/car")и это бросили 405 error.


Исправление:

CarController.csФайл находился в каталоге /api/carпоэтому , когда мы были запросив апи конечной точку, IIS будет возвращать ошибку , потому что казалось, что мы пытались получить доступ к виртуальному каталогу , который мы не разрешались.

Вариант 1: изменить / переименовать каталог, в котором находится контроллер.
Вариант 2: изменить префикс маршрута на то, что не соответствует виртуальному каталогу.

Zze
источник
1

В моем случае у меня была физическая папка в проекте с тем же именем, что и у маршрута WebAPI (например, песочница), и только запрос POST был перехвачен обработчиком статических файлов в IIS (очевидно).

Получение вводящей в заблуждение ошибки 405 вместо более ожидаемой 404 было причиной, по которой мне потребовалось много времени, чтобы устранить неполадки.

Попасть в это непросто, но возможно. Надеюсь, это кому-то поможет.

Панос Родитакис
источник
1

Со своей стороны мой обработчик POST имел такую ​​форму:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromRoute] int routeParam, [FromBody] PostData data)

Я понял, что мне пришлось поменять местами аргументы , то есть сначала данные тела, а затем параметр маршрута, как это:

[HttpPost("{routeParam}")]
public async Task<ActionResult> PostActuality ([FromBody] PostData data, [FromRoute] int routeParam)
Александр Добрикур
источник
0

проверьте файл .csproj вашего проекта и измените

<IISUrl>http://localhost:PORT/</IISUrl>

на URL-адрес вашего веб-сайта

<IISUrl>http://example.com:applicationName/</IISUrl>
Анкит
источник
0

Другая возможная проблема, которая вызывает такое же поведение, - это параметры маршрутизации по умолчанию. В моем случае контроллер был обнаружен и создан правильно, но POST был заблокирован из-за Getуказанного действия по умолчанию :

config.Routes.MapHttpRoute(
    name: "GetAllRoute",
    routeTemplate: "api/{controller}.{ext}"/*,
    defaults: new { action = "Get" }*/ // this was causing the issue
);
Эдель
источник
0

У меня была точно такая же проблема. Я два часа искал, что было не так, но безуспешно, пока не понял, что мой POSTметод был privateвместо этого public.

Забавно, что теперь это сообщение об ошибке носит общий характер. Надеюсь, это поможет!

Гонзо345
источник
0

Убедитесь, что ваш контроллер наследуется от Controllerкласса.

Было бы даже более безумно, что все работало бы локально даже без этого.

ОЗУ
источник