C# ASP.NET Web API 中不允许 HTTP PUT
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/14321988/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
HTTP PUT not allowed in ASP.NET Web API
提问by Mike Bailey
On my Web API project, I cannot perform an HTTP PUT
to my resources. I've read through somesimilarquestionsonthisproblemand I've followed the recommended advice.
在我的 Web API 项目中,我无法HTTP PUT
对我的资源执行 an 。我已经阅读了一些关于这个问题的类似问题,并遵循了推荐的建议。
First off, I uninstalled WebDAV completely on my machine (Windows 7 64-bit) and subsequently rebooted my machine.
首先,我在我的机器(Windows 7 64 位)上完全卸载了 WebDAV,然后重新启动了我的机器。
Secondly, the WebDAV handlers were specified as removed in my web.config
and the HTTP PUT
verb was specified as being allowed for the Extensionless URL Handler.
其次,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>
I even tried adding the ISAPI Extensionless URL Handler (32-bit and 64-bit) and changing my application from the integrated pipeline App Pool to the classic App Pool.
我什至尝试添加 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" />
I'm currently using Thinktecture IdentityModelto enable Cross Origin Resource Sharing (CORS) support. For my sanity, I've gone with the nuclear option of enabling everything to make sure the HTTP PUT
is actually allowed.
我目前正在使用Thinktecture IdentityModel来启用跨源资源共享 (CORS) 支持。为了我的理智,我已经选择了启用一切以确保HTTP PUT
实际允许的核选项。
config.RegisterGlobal(httpConfig);
config.ForAllResources()
.ForAllOrigins()
.AllowAllMethods()
.AllowAllRequestHeaders();
The Attribute RoutingNuGet package is configured to pick up all routes from the current assembly and any subtypes of ApiController
.
的属性路由NuGet包被构造成拾取从当前组件的所有路由和的任何亚型ApiController
。
config.AddRoutesFromAssembly(Assembly.GetExecutingAssembly());
config.AddRoutesFromControllersOfType<ApiController>();
My resource has the PUT
attribute properly specified as well.
我的资源也PUT
正确指定了属性。
[PUT("/API/Authenticate/Link/{key}/{identifier}")]
public Boolean LinkUser(Guid key, String identifier) { ... }
Every resource I look up on this matter recommends the same exact thing: Uninstalling WebDAV, disabling the WebDAV handlers and making sure that the Extensionless URL handler is properly configured. I've done all that and it stilldoesn't work.
我在这个问题上查找的每个资源都推荐相同的内容:卸载 WebDAV、禁用 WebDAV 处理程序并确保正确配置 Extensionless URL 处理程序。我已经完成了所有这些,但它仍然不起作用。
In fiddler, I'm getting the following:
在提琴手中,我得到以下信息:
PUT https://localhost/Test/API/Authenticate/Link/Foo/Bar
{"Message":"The requested resource does not support http method 'PUT'."}
What am I doing wrong?
我究竟做错了什么?
采纳答案by Mike Bailey
Apparently, there is a known problem within AttributeRouting
wherein the HttpPut
methods are currently non-functional in ASP.NET Web API.
显然,存在一个已知问题,AttributeRouting
其中HttpPut
方法当前在 ASP.NET Web API 中不起作用。
The currently accepted workaroundis add the appropriate verb onto the route until a proper fix comes along:
在目前公认的解决方法是添加合适的动词到路线直至适当的修复走来:
Web API RC sealed a vital interface for route detection by the underlying framework. Though the interface is now public, the change won't be released until vNext. So here are some workarounds:
- Use AR attributes in combination with HttpGet, HttpPost, HttpPut, or HttpDelete attributes from System.Web.Http:
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() {}
回答by Andrew
I had the same error, and traced it to a custom route that I'd defined like so:
我遇到了同样的错误,并将其跟踪到我定义的自定义路由,如下所示:
config.Routes.MapHttpRoute(
name: "SomeCall",
routeTemplate: "api/somecall/{id}",
defaults: new { controller = "SomeCall", action = "Get" }
);
The problem here is the action = "Get"
which prevented the PUT
action of the same URI to respond. Removing the default action fixed the issue.
这里的问题是action = "Get"
它阻止PUT
了相同 URI的动作进行响应。删除默认操作解决了该问题。
回答by Nick Josevski
Double check that you're using [HttpPut]from System.Web.Http.
仔细检查你使用[HttpPut]从System.Web.Http。
Under some circumstances you can end up using the attribute from System.Web.Mvc.
在某些情况下,您最终可能会使用 System.Web.Mvc 中的属性。
This was resulting in 405s for us.
这给我们带来了 405s。
回答by Oladipo Olasemo
What worked for me was to add a Route Attribute as I already had one defined for a GET request that was overloaded as below:
对我有用的是添加一个路由属性,因为我已经为一个重载的 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;
}
So I added for the PUT:
所以我为 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);
}
回答by Sheo Narayan
I think this is no more the case, perhaps this issue has been fixed now. ASP.NET MVC Web API now allows $http.put and here is the code to test.
我认为情况不再如此,也许这个问题现在已经解决了。ASP.NET MVC Web API 现在允许 $http.put,这里是要测试的代码。
AngularJS Script code
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 code
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 Controller action method
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);
}
}
(Change the url to send request to) When we click on the Submit button, it sends HttpPut request to '/api/default' (DefaultController) where PutDataResponse action method is declared. This method will be called and user gets its response.
(更改将请求发送到的 url)当我们单击提交按钮时,它会将 HttpPut 请求发送到声明了 PutDataResponse 操作方法的“/api/default”(DefaultController)。这个方法将被调用,用户得到它的响应。
This solution was originally written here
这个解决方案最初是写在这里的
回答by ComeIn
For me it was because I had not set the media type in the json content string for my http client request:
对我来说,这是因为我没有在 json 内容字符串中为我的 http 客户端请求设置媒体类型:
new StringContent(json, Encoding.UTF32, "application/json");
new StringContent(json, Encoding.UTF32, "application/json");
All sorts of weird behavior if this is not set.
如果未设置,则会出现各种奇怪的行为。