ASP.NET Web API中不允许HTTP PUT

时间:2013-01-14 16:00:05

标签: c# asp.net-web-api iis-7.5

在我的Web API项目中,我无法对我的资源执行HTTP PUT。我通读了some similar questions on this problem并且我遵循了建议的建议。

首先,我在我的机器上完全卸载了WebDAV(Windows 7 64位),然后重新启动了我的机器。

其次,WebDAV处理程序在我的web.config中被指定为已删除,并且HTTP PUT动词被指定为允许无扩展URL处理程序。

<modules runAllManagedModulesForAllRequests="false">
  <remove name="WebDAVModule"/>
</modules>

<handlers>
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
  <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="WebDAV"/>
  <add name="ExtensionlessUrlHandler-Integrated-4.0"
       path="*."
       verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
       type="System.Web.Handlers.TransferRequestHandler"
       resourceType="Unspecified"
       requireAccess="Script"
       preCondition="integratedMode,runtimeVersionv4.0" />
  <add name="AttributeRouting" path="routes.axd" verb="*" type="AttributeRouting.Web.Logging.LogRoutesHandler, AttributeRouting.Web" />
</handlers>

我甚至尝试添加ISAPI Extensionless URL Handler(32位和64位)并将我的应用程序从集成管道App Pool更改为经典App Pool。

<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" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit"
      path="*."
      verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS"
      modules="IsapiModule"
      scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll"
      preCondition="classicMode,runtimeVersionv4.0,bitness64"
      responseBufferLimit="0" />

我目前正在使用Thinktecture IdentityModel来启用跨源资源共享(CORS)支持。为了我的理智,我选择了启用所有内容的核选项,以确保实际允许HTTP PUT

config.RegisterGlobal(httpConfig);

config.ForAllResources()
      .ForAllOrigins()
      .AllowAllMethods()
      .AllowAllRequestHeaders();

Attribute Routing NuGet包配置为从当前程序集和ApiController的任何子类型中选取所有路由。

config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
config.AddRoutesFromControllersOfType<ApiController>();

我的资源也正确指定了PUT属性。

[PUT("/API/Authenticate/Link/{key}/{identifier}")]
public Boolean LinkUser(Guid key, String identifier) { ... }

我在这个问题上查看的每个资源都推荐了同样的东西:卸载WebDAV,禁用WebDAV处理程序并确保正确配置了Extensionless URL处理程序。我已经完成了所有这些并且仍然不起作用。

在小提琴手中,我得到以下内容:

PUT https://localhost/Test/API/Authenticate/Link/Foo/Bar

{"Message":"The requested resource does not support http method 'PUT'."}

我做错了什么?

7 个答案:

答案 0 :(得分:19)

显然,AttributeRouting中存在一个已知问题,其中HttpPut方法目前在ASP.NET Web API中不起作用。

currently accepted workaround是将适当的动词添加到路线上,直到出现正确的修复:

  

Web API RC密封了一个重要的接口,用于路由检测   基础框架。虽然界面现在是公开的,但改变了   直到vNext才会发布。所以这里有一些解决方法:

     
      
  • 将AR属性与System.Web.Http中的HttpGet,HttpPost,HttpPut或HttpDelete属性结合使用:
  •   
[GET("some/url"), HttpGet]
public string Method1() {}

[PUT("some/url"), HttpPut]
public string Method2() {}

[POST("some/url"), HttpPost]
public string Method3() {}

[DELETE("some/url"), HttpDelete]
public string Method4() {}

答案 1 :(得分:12)

仔细检查您使用的是 [HttpPut] System.Web.Http

在某些情况下,您最终可以使用System.Web.Mvc。

中的属性

这导致了我们的405s。

答案 2 :(得分:4)

我遇到了同样的错误,并将其追溯到我定义的自定义路线:

config.Routes.MapHttpRoute(
    name: "SomeCall",
    routeTemplate: "api/somecall/{id}",
    defaults: new { controller = "SomeCall", action = "Get" }
);

此处的问题是 action = "Get" ,它阻止同一URI的PUT操作作出响应。删除默认操作可解决问题。

答案 3 :(得分:3)

对我来说有用的是添加一个路由属性,因为我已经为一个GET请求定义了一个,如下所示:

    // GET api/Transactions/5
    [Route("api/Transactions/{id:int}")]
    public Transaction Get(int id)
    {
        return _transactionRepository.GetById(id);
    }

    [Route("api/Transactions/{code}")]
    public Transaction Get(string code)
    {
        try
        {
            return _transactionRepository.Search(p => p.Code == code).Single();
        }
        catch (Exception Ex)
        {
            System.IO.File.WriteAllText(@"C:\Users\Public\ErrorLog\Log.txt",
                Ex.Message + Ex.StackTrace + Ex.Source + Ex.InnerException.InnerException.Message);
        }

        return null;
    }

所以我为PUT添加了:

    // PUT api/Transactions/5
    [Route("api/Transactions/{id:int}")]
    public HttpResponseMessage Put(int id, Transaction transaction)
    {
        try
        {
            if (_transactionRepository.Save(transaction))
            {
                return Request.CreateResponse<Transaction>(HttpStatusCode.Created, transaction);
            }
        }
        catch (Exception Ex)
        {
            System.IO.File.WriteAllText(@"C:\Users\Public\ErrorLog\Log.txt",
                Ex.Message + Ex.StackTrace + Ex.Source + Ex.InnerException.InnerException.Message);
        }

        return Request.CreateResponse<Transaction>(HttpStatusCode.InternalServerError, transaction);
    }

答案 4 :(得分:0)

我认为情况已经不是这样了,也许这个问题现在已经解决了。 ASP.NET MVC Web API现在允许$ http.put,这里是要测试的代码。

AngularJS脚本代码

$scope.UpdateData = function () {
        var data = $.param({
            firstName: $scope.firstName,
            lastName: $scope.lastName,
            age: $scope.age
        });

        $http.put('/api/Default?'+ data)
        .success(function (data, status, headers) {
            $scope.ServerResponse = data;
        })
        .error(function (data, status, header, config) {
            $scope.ServerResponse =  htmlDecode("Data: " + data +
                "\n\n\n\nstatus: " + status +
                "\n\n\n\nheaders: " + header +
                "\n\n\n\nconfig: " + config);
        });
    };

Html代码

<div ng-app="myApp" ng-controller="HttpPutController">
<h2>AngularJS Put request </h2>
<form ng-submit="UpdateData()">
    <p>First Name: <input type="text" name="firstName" ng-model="firstName" required /></p>
    <p>Last Name: <input type="text" name="lastName" ng-model="lastName" required /></p>
    <p>Age : <input type="number" name="age" ng-model="age" required /></p>
    <input type="submit" value="Submit" />
    <hr />
    {{ ServerResponse }}
</form></div>

ASP.NET MVC Web API控制器操作方法

 public class DefaultController : ApiController
{

    public HttpResponseMessage PutDataResponse(string firstName, string lastName, int age)
    {
        string msg =  "Updated: First name: " + firstName +
            " | Last name: " + lastName +
            " | Age: " + age;

        return Request.CreateResponse(HttpStatusCode.OK, msg);
    }
}

(更改要发送请求的网址) 当我们点击“提交”按钮时,它会将HttpPut请求发送到&#39; / api / default&#39; (DefaultController)声明了PutDataResponse操作方法。将调用此方法,用户将获得其响应。

此解决方案最初编写为here

答案 5 :(得分:0)

对我来说,这是因为我没有在我的http客户端请求的json内容字符串中设置媒体类型:

new StringContent(json,Encoding.UTF32,&#34; application / json&#34; );

如果没有设置,会出现各种奇怪的行为。

答案 6 :(得分:-1)

就我而言,我在邮递员中放入了一个参数 ID:

http://localhost:55038/api/documento/pruebadetallecatalogo?id=100

但是,我将 url 请求更改为:

http://localhost:55038/api/documento/pruebadetallecatalogo/100

这对我有用!!!