Ответ 1
Вы отправляете сообщение от клиента:
await client.PostAsJsonAsync("api/products", product);
not PUTing.
Ваш метод Web API принимает только запросы PUT.
Итак:
await client.PutAsJsonAsync("api/products", product);
Эта ошибка очень распространена, и я пробовал все решения и не работал. Я отключил публикацию 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
Любые предложения?
Вы отправляете сообщение от клиента:
await client.PostAsJsonAsync("api/products", product);
not PUTing.
Ваш метод Web API принимает только запросы PUT.
Итак:
await client.PutAsJsonAsync("api/products", product);
У меня было то же исключение. Моя проблема заключалась в том, что я использовал:
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";
}
Я пробовал много вещей, чтобы получить метод DELETE (я получал 405 метод, не разрешенный web 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);
}
Моя проблема оказалась маршрутизируемой атрибутом в WebAPI. Я создал настраиваемый маршрут, и он рассматривал его как GET вместо WebAPI, обнаружив, что это POST
[Route("")]
[HttpPost] //I added this attribute explicitly, and it worked
public void Post(ProductModel data)
{
...
}
Я знал, что это должно быть что-то глупое (это поглощает весь ваш день)
Chrome часто пытается выполнить вызов OPTIONS
перед выполнением сообщения. Он делает это, чтобы убедиться, что заголовки CORS в порядке. Это может быть проблематично, если вы не обрабатываете вызов OPTIONS
в вашем контроллере API.
public void Options() { }
Эта ошибка также может возникнуть при попытке подключиться к http, когда сервер находится на https.
Это немного сбивало с толку, потому что мои get-запросы были в порядке, проблема присутствовала только с post-запросами.
Я получал 405 на моем вызове GET, и проблема оказалась в том, что я назвал параметр в методе GET на стороне сервера Get(int formId)
, и мне нужно было изменить маршрут или переименовать его Get(int id)
.
Вы также можете получить ошибку 405, если заявите, что ваш метод ожидает параметра, и вы его не передаете.
Это НЕ работает (ошибка 405)
HTML-представление/Javascript
$.ajax({
url: '/api/News',
//.....
Web Api:
public HttpResponseMessage GetNews(int id)
Таким образом, если сигнатура метода похожа на приведенную выше, вы должны сделать:
HTML-представление/Javascript
$.ajax({
url: '/api/News/5',
//.....
Если у вас есть маршрут, например
[Route("nuclearreactors/{reactorId}")]
Вам нужно использовать точное имя параметра в методе, например.
public ReactorModel GetReactor(reactorId)
{
...
}
Если вы не передадите тот же самый параметр, вы можете получить ошибку "405 метод не разрешен", потому что маршрут не будет соответствовать запросу, а WebApi ударит по другому методу контроллера с другим допустимым HTTP-методом.
Вот одно решение
<handlers accessPolicy="Read, Script"> <remove name="WebDAV"/> </handlers>
docs.microsoft.com статья о решении
и удалите WebDAV из модулей
<remove name="WebDAVModule"/>
Я опаздываю на эту вечеринку, но поскольку ничто выше не было жизнеспособным или не работало в большинстве случаев, вот как это было окончательно разрешено для меня.
На сервере, на котором размещался сайт/служба, была необходима функция! HTTP ACTIVATION!!!
Диспетчер серверов > Управление > Добавить роли и функции > следующий следующий следующий, пока вы не перейдете к функциям > В .NET(каждая версия) отметьте HTTP-активацию. Также обратите внимание, что есть один скрытый под > net > WCF Services.
Теперь это сработало! Это таял мой мозг.
Это не отвечает на ваш конкретный вопрос, но когда у меня была та же проблема, я оказался здесь, и я подумал, что больше людей могут сделать то же самое.
Проблема, которая у меня была, заключалась в том, что я неизменно объявлял мой метод Get как статический. Я пропустил это на весь передний план, и это не вызвало никаких предупреждений об атрибутах или подобных.
Неправильно:
public class EchoController : ApiController
{
public static string Get()
{
return string.Empty;
}
}
Правильно:
public class EchoController : ApiController
{
public string Get()
{
return string.Empty;
}
}
[HttpPost] не требуется!
[Route("")]
public void Post(ProductModel data)
{
...
}
Я не мог решить этого. Я включил CORS и работал до тех пор, пока POST вернул void (ASP.NET 4.0 - WEBAPI 1). Когда я попытался вернуть HttpResponseMessage, я начал получать ответ HTTP 405.
Основываясь на вышеприведенном Llad-ответе, я взглянул на свои собственные ссылки.
У меня был атрибут [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>
У нас была похожая проблема. Мы пытались получить от:
[RoutePrefix("api/car")]
public class CarController: ApiController{
[HTTPGet]
[Route("")]
public virtual async Task<ActionResult> GetAll(){
}
}
Таким образом, мы бы .GET("/api/car")
и это выдало бы 405 error
.
Файл CarController.cs
находился в каталоге /api/car
поэтому, когда мы запрашивали эту конечную точку api, IIS отправляла обратно ошибку, потому что выглядело так, как будто мы пытались получить доступ к виртуальному каталогу, к которому нам не разрешали.
Вариант 1: изменить/переименовать каталог, в котором находится контроллер
Вариант 2: измените префикс маршрута, чтобы он не совпадал с виртуальным каталогом.
проверьте файл проекта .csproj и измените
<IISUrl>http://localhost:PORT/</IISUrl>
на ваш сайт url like this
<IISUrl>http://example.com:applicationName/</IISUrl>
Другая возможная проблема, вызывающая такое же поведение, - это параметры по умолчанию в маршрутизации. В моем случае контроллер был локализован и инстанцирован правильно, но POST был заблокирован из-за установленного значения по умолчанию Get
:
config.Routes.MapHttpRoute(
name: "GetAllRoute",
routeTemplate: "api/{controller}.{ext}"/*,
defaults: new { action = "Get" }*/ // this was causing the issue
);
У меня была точно такая же проблема. Два часа я смотрел, что было не так, без удачи, пока не понял, что мой метод POST
был private
а не public
.
Забавно теперь, когда я вижу это сообщение об ошибке. Надеюсь, поможет!
В моем случае в проекте была физическая папка с тем же именем, что и маршрут WebAPI (например, песочница), и обработчик статических файлов в IIS перехватил только запрос POST (очевидно).
Появление вводящей в заблуждение ошибки 405 вместо более ожидаемой 404 было причиной, по которой мне потребовалось много времени для устранения неполадок.
Не легко впасть в это, но возможно. Надеюсь, это кому-нибудь поможет.
Убедитесь, что ваш контроллер наследуется от класса Controller
.
Это может быть даже более безумно, что вещи будут работать локально, даже без этого.