Web API - 405 - 请求的资源不支持HTTP方法'PUT'

23

我有一个Web API项目,但无法启用其"PUT/Patch"请求。

Fiddler返回的响应是:


HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET,POST,DELETE
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcUHJvamVjdHNcZG90TmV0XFdlYkFQSVxBZFNlcnZpY2VcQWRTZXJ2aWNlXGFwaVxpbXByZXNzaW9uXDE1?=
X-Powered-By: ASP.NET
Date: Tue, 06 May 2014 14:10:35 GMT
Content-Length: 72

{"message":"The requested resource does not support http method 'PUT'."}
根据上述回复,“PUT”动词不被接受。但是我无法找出相关的处理程序在哪里配置。
该类的“Put”方法声明如下:
[HttpPatch]
[HttpPut]
public HttpResponseMessage Put(Int32 aID, [FromBody] ImpressionModel impressionModel)
{
     bla, bla, bla, bla
}

我已阅读并实施了以下线程中解释的更改:

尽管我已经注释掉了ApplicationsHost.config文件中的所有 “Handlers”,但仍然无法使用“PUT”命令对我的Web API项目进行操作,仍然收到405响应。

我使用VS2012 Premium和IIS Express(我假设它是版本8)。我还尝试了VS Dev Server,但也得到了相同的结果。

我已经没有任何想法了。感谢您的帮助。

谢谢Lee

10个回答

24

你是否在使用属性路由?

这个神秘的错误是一个路由属性(route attributes)问题。在你的WebAPIConfig中启用了它:

 config.MapHttpAttributeRoutes(); 

事实证明,Web API控制器“不能同时托管基于动词的操作方法和传统的操作名称路由。”;https://aspnetwebstack.codeplex.com/workitem/184

简而言之:我需要给我的API控制器中的所有操作都打上[Route]属性,否则在尝试通过传统路由查找操作时,该操作将被“隐藏”(405)。

API控制器:

[RoutePrefix("api/quotes")]
public class QuotesController : ApiController
{
    ...

    // POST api/Quote
    [ResponseType(typeof(Quote))]
    [Route]
    public IHttpActionResult PostQuote(Quote quote)
    {
        if (!ModelState.IsValid)
        {
            return BadRequest(ModelState);
        }

        db.Quotes.Add(quote);
        db.SaveChanges();

        return CreatedAtRoute("", new { id = quote.QuoteId }, quote);
    }

注意:我的路由没有名称,所以CreatedAtRoute()的名称只是一个空字符串。

WebApiConfig.cs:

public static class WebApiConfig
{
    public static void Register(HttpConfiguration config)
    {
        // Web API configuration and services
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html"));

        // Web API routes
        config.MapHttpAttributeRoutes();

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

    }
}

希望这可以帮到你


很不幸,对我来说也是同样的问题。 - Idrees Khan
请提供在CodePlex上报告问题的链接,如果提供了链接将会得到+1分。同时,您可能会发现两个不同的链接来解决这个问题。由于该问题没有修复而被关闭,我更倾向于不使用任何解决方法来管理它,以避免过度设计我的Web API ;) - Guillaume Raymond
谢谢! 在PUT和POST上添加 [Route](之前缺失了)解决了我的问题。终于,关于Web API路由的重要信息! - ticky

11

我和你一样遇到了完全相同的问题,我试过了你试过的所有方法,但有时解决方案是如此微不足道且显而易见,以至于你根本没想到并继续寻找更复杂的原因。确保在调用测试Web方法的URL中,参数名称与控制器方法声明中的名称匹配。通过做到这一点 (我正在使用查询参数),我的405问题得到了解决:

我的clientsController:

...

[HttpPut]
public string PutClient(string username = "", string phone= ""){...}

在我的WebApiConfig文件中:

// Web API routes
config.MapHttpAttributeRoutes();

config.Routes.MapHttpRoute(
     name: "DefaultApi",
     routeTemplate: "api/{controller}"
);

测试该方法的路径必须如下所示:(使用Postman或类似工具,应用正确的网络方法)

http://localhost:49216/api/clients?username=Kurt&phone=443332211
否则,在该控制器使用该HTTP方法将会收到405错误。我根本不需要更改web.config文件(无需删除WebDAV等内容)。请参阅文档中的源以获取更多信息:
例如,考虑以下操作: public void Get(int id)
id参数绑定到URI。因此,此操作仅能匹配包含“id”值的URI, 无论是在路由字典中还是在查询字符串中。
可选参数是一个例外,因为它们是可选的。对于可选参数,如果绑定无法从URI获取值,则可以。

一样的情况。我传递了错误的参数名称,纠结了一个小时!! - Milind Thakkar

5
当我更改PUT方法的第一个参数名称时,发生了这种情况。
public void Put(int code, [FromBody]Lead lead)

应该是:

public void Put(int id, [FromBody]Lead lead)

这是它被调用的方式:

$.ajax({
    type: "PUT",
    data: json,
    url: "../api/leadsapi/123",
    contentType: "application/json; charset=utf-8"
});

3

我觉得和其他帖子的情况类似。也许你在webapiconfig中已经正确设置了一切,但是你可能只是遗漏掉了一些小东西。

在我的情况下,我的路由定义如下:

[HttpPut]
    [Route("api/MilestonePut/{Milestone_ID}")]
    public void Put(int id, [FromBody]Milestone milestone)
    {
        db.Entry(milestone).State = System.Data.Entity.EntityState.Modified;
        db.SaveChanges();
    }

看出问题了吗?路由中参数被定义为Milestone_ID,但在函数本身中却被定义为id。你可能认为.NET会足够聪明地意识到这一点,但实际上它并不会,因此无法正常工作。

一旦我将其更改为与参数匹配,就像这样:

[HttpPut]
    [Route("api/MilestonePut/{id}")]
    public void Put(int id, [FromBody]Milestone milestone)
    {
        db.Entry(milestone).State = System.Data.Entity.EntityState.Modified;
        db.SaveChanges();
    }

一切都像魔法般顺利运行。


1

这个答案解决了我的问题。我需要添加Route属性,问题就解决了。

    [HttpPut]
    [Route("")]
    public HttpResponseMessage MyMethod()

我尝试了你的解决方案,但结果相同。 - C.Fasolin

1

如果您忘记将API控制器上的Put()方法设置为public,则也会返回此错误消息。事后看来这是显而易见的,但却让我费了好几分钟才想明白。


1

我遇到了相同的问题,需要做三件事才能解决:

  1. <modules><handlers>中禁用Webdav
  2. 确保在使用WebAPI时,HttpPut来自于System.Web.Http而不是System.Web.Mvc
  3. 像这样启用ExtensionlessUrlHandler

<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />

<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />

<remove name="ExtensionlessUrlHandler-Integrated-4.0" />

<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" />

希望这可以帮助你解决这个麻烦的问题...

0
也许现在有些晚了,但有人可以用这个。
我想使用PUT请求,所以我只是将字符串化的对象发送到Web API中,在put方法中只接受该对象。
JQUERY
let musterija = {
            Name: name,
            Email: email,
            Password: password,
            Username: logUser.Username,
            Lastname: lastname,
            GenderString: gender,
            Jmbg: identification,
            PhoneNumber: phone,
        };

        $.ajax({
            method: "PUT",
            url: "/api/Musterija",
            data: JSON.stringify(musterija),
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            success: function () {
                alert("Entity updated");
                EmptyAllInputs();
                $('#divprofile').show();
                $('#divupdate').hide();
            },
            error: function (msg) {
                alert("Fail - " + msg.responseText);
            }
        });

WEB API

    [HttpPut]
    public HttpResponseMessage PutMusterija(Musterija m)

0
请在web.config的Handler部分下添加以下内容:
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,POST,PUT,PATCH,MERGE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

例如:
<handlers>
    <remove name="WebDAV" />
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
    <remove name="OPTIONSVerbHandler" />
    <remove name="TRACEVerbHandler" />
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,POST,PUT,PATCH,MERGE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>

0

您应该在您的Web服务器配置中进行配置。这取决于Web服务器的类型,您可以在哪里进行配置。例如,在IIS中,您可以使用web.config文件在文档根目录中进行配置。对于跨域请求,您必须向响应添加CORS标头,以允许来源、方法等...

注意:可能您也可以使用ASP.NET框架来处理此问题,但我认为这不太可能。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接