25

在我的 Web API 项目中,我无法HTTP PUT对我的资源执行操作。我已经阅读了有关问题的一些 类似 问题 ,并且遵循了推荐的建议。

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

其次,WebDAV 处理程序在 my 中被指定为删除,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 无扩展 URL 处理程序(32 位和 64 位)并将我的应用程序从集成管道应用程序池更改为经典应用程序池。

<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();

属性路由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 处理程序并确保正确配置无扩展 URL 处理程序。我已经完成了所有这些,但它仍然不起作用。

在提琴手中,我得到以下信息:

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

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

我究竟做错了什么?

4

7 回答 7

20

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

当前接受的解决方法是将适当的动词添加到路线上,直到出现适当的修复:

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() {}
于 2013-01-14T16:50:49.480 回答
14

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

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

这为我们带来了 405。

于 2013-04-19T04:16:23.653 回答
4

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

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

这里的问题是action = "Get"阻止了PUT相同 URI 的操作来响应。删除默认操作解决了该问题。

于 2013-01-29T16:35:26.483 回答
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);
    }
于 2014-01-13T22:13:07.747 回答
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);
    }
}

(更改发送请求的 url) 当我们单击提交按钮时,它会将 HttpPut 请求发送到声明了 PutDataResponse 操作方法的“/api/default”(DefaultController)。该方法将被调用并且用户得到它的响应。

这个解决方案最初写在这里

于 2015-07-07T10:16:23.790 回答
0

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

新的 StringContent(json, Encoding.UTF32, "application/json" );

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

于 2016-06-28T09:33:49.630 回答
-1

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

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

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

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

这对我行得通!!!

于 2021-07-13T16:30:58.410 回答