C# Web API Put 请求生成 Http 405 Method Not Allowed 错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19162825/
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
Web API Put Request generates an Http 405 Method Not Allowed error
提问by Mike Marks
Here's the call to the PUT
method on my Web API - the third line in the method (I am calling the Web API from an ASP.NET MVC front end):
这是PUT
对我的 Web API 上方法的调用- 方法中的第三行(我从 ASP.NET MVC 前端调用 Web API):
client.BaseAddress
is http://localhost/CallCOPAPI/
.
client.BaseAddress
是http://localhost/CallCOPAPI/
。
Here's contactUri
:
这是contactUri
:
Here's contactUri.PathAndQuery
:
这是contactUri.PathAndQuery
:
And finally, here's my 405 response:
最后,这是我的 405 响应:
Here's the WebApi.config in my Web API project:
这是我的 Web API 项目中的 WebApi.config:
public static void Register(HttpConfiguration config)
{
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApiGet",
routeTemplate: "api/{controller}/{action}/{regionId}",
defaults: new { action = "Get" },
constraints: new { httpMethod = new HttpMethodConstraint("GET") });
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
I've tried stripping down the path that gets passed into PutAsJsonAsync
to string.Format("/api/department/{0}", department.Id)
and string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id)
with no luck.
我试着剥离下来获取传递到路径PutAsJsonAsync
,以string.Format("/api/department/{0}", department.Id)
和string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id)
没有运气。
Does anyone have any ideas why I'm getting the 405 error?
有没有人知道为什么我会收到 405 错误?
UPDATE
更新
As per request, here's my Department controller code (I will post both the Department controller code for my front end project, as well as the Department ApiController code for the WebAPI):
根据请求,这是我的部门控制器代码(我将发布前端项目的部门控制器代码以及 WebAPI 的部门 ApiController 代码):
Front End Department Controller
前端部门主管
namespace CallCOP.Controllers
{
public class DepartmentController : Controller
{
HttpClient client = new HttpClient();
HttpResponseMessage response = new HttpResponseMessage();
Uri contactUri = null;
public DepartmentController()
{
// set base address of WebAPI depending on your current environment
client.BaseAddress = new Uri(ConfigurationManager.AppSettings[string.Format("APIEnvBaseAddress-{0}", CallCOP.Helpers.ConfigHelper.COPApplEnv)]);
// Add an Accept header for JSON format.
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
// need to only get departments that correspond to a Contact ID.
// GET: /Department/?regionId={0}
public ActionResult Index(int regionId)
{
response = client.GetAsync(string.Format("api/department/GetDeptsByRegionId/{0}", regionId)).Result;
if (response.IsSuccessStatusCode)
{
var departments = response.Content.ReadAsAsync<IEnumerable<Department>>().Result;
return View(departments);
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot retrieve the list of department records due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Index");
}
}
//
// GET: /Department/Create
public ActionResult Create(int regionId)
{
return View();
}
//
// POST: /Department/Create
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Create(int regionId, Department department)
{
department.RegionId = regionId;
response = client.PostAsJsonAsync("api/department", department).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Edit", "Region", new { id = regionId });
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot create a new department due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Edit", "Region", new { id = regionId });
}
}
//
// GET: /Department/Edit/5
public ActionResult Edit(int id = 0)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
Department department = response.Content.ReadAsAsync<Department>().Result;
if (department == null)
{
return HttpNotFound();
}
return View(department);
}
//
// POST: /Department/Edit/5
[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Edit(int regionId, Department department)
{
response = client.GetAsync(string.Format("api/department/{0}", department.Id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.PutAsJsonAsync(string.Format(contactUri.PathAndQuery), department).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("Index", new { regionId = regionId });
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot edit the department record due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return RedirectToAction("Index", new { regionId = regionId });
}
}
//
// GET: /Department/Delete/5
public ActionResult Delete(int id = 0)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
Department department = response.Content.ReadAsAsync<Department>().Result;
if (department == null)
{
return HttpNotFound();
}
return View(department);
}
//
// POST: /Department/Delete/5
[HttpPost, ActionName("Delete")]
[ValidateAntiForgeryToken]
public ActionResult DeleteConfirmed(int regionId, int id)
{
response = client.GetAsync(string.Format("api/department/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;
return RedirectToAction("Index", new { regionId = regionId });
}
}
}
Web API Department ApiController
Web API 部门 ApiController
namespace CallCOPAPI.Controllers
{
public class DepartmentController : ApiController
{
private CallCOPEntities db = new CallCOPEntities(HelperClasses.DBHelper.GetConnectionString());
// GET api/department
public IEnumerable<Department> Get()
{
return db.Departments.AsEnumerable();
}
// GET api/department/5
public Department Get(int id)
{
Department dept = db.Departments.Find(id);
if (dept == null)
{
throw new HttpResponseException(Request.CreateResponse(HttpStatusCode.NotFound));
}
return dept;
}
// this should accept a contact id and return departments related to the particular contact record
// GET api/department/5
public IEnumerable<Department> GetDeptsByRegionId(int regionId)
{
IEnumerable<Department> depts = (from i in db.Departments
where i.RegionId == regionId
select i);
return depts;
}
// POST api/department
public HttpResponseMessage Post(Department department)
{
if (ModelState.IsValid)
{
db.Departments.Add(department);
db.SaveChanges();
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, department);
return response;
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
// PUT api/department/5
public HttpResponseMessage Put(int id, Department department)
{
if (!ModelState.IsValid)
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
if (id != department.Id)
{
return Request.CreateResponse(HttpStatusCode.BadRequest);
}
db.Entry(department).State = EntityState.Modified;
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK);
}
// DELETE api/department/5
public HttpResponseMessage Delete(int id)
{
Department department = db.Departments.Find(id);
if (department == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
db.Departments.Remove(department);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK, department);
}
}
}
采纳答案by Mike Marks
So, I checked Windows Features to make sure I didn't have this thing called WebDAV installed, and it said I didn't. Anyways, I went ahead and placed the following in my web.config (both front end and WebAPI, just to be sure), and it works now. I placed this inside <system.webServer>
.
所以,我检查了 Windows 功能以确保我没有安装这个叫做 WebDAV 的东西,它说我没有。无论如何,我继续将以下内容放入我的 web.config(前端和 WebAPI,只是为了确定),现在它可以工作了。我把这个放在里面<system.webServer>
。
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/> <!-- add this -->
</modules>
Additionally, it is often required to add the following to web.config
in the handlers. Thanks to Babak
此外,通常需要web.config
在处理程序中添加以下内容。感谢巴巴克
<handlers>
<remove name="WebDAV" />
...
</handlers>
回答by Aron
Add this to your web.config
. You need to tell IIS what PUT
PATCH
DELETE
and OPTIONS
means. And which IHttpHandler
to invoke.
将此添加到您的web.config
. 您需要告诉 IIS 是什么PUT
PATCH
DELETE
和OPTIONS
意味着什么。以及IHttpHandler
调用哪个。
<configuation>
<system.webServer>
<handlers>
<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" />
<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" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
</configuration>
Also check you don't have WebDAV enabled.
还要检查您没有启用 WebDAV。
回答by Molibar
WebDav-SchmebDav.. ..make sure you create the url with the ID correctly. Don't send it like http://www.fluff.com/api/Fluff?id=MyID, send it like http://www.fluff.com/api/Fluff/MyID.
WebDav-SchmebDav .. ..确保您使用正确的 ID 创建了 url。不要把它像http://www.fluff.com/api/Fluff?id=MyID,把它像http://www.fluff.com/api/Fluff/MyID。
Eg.
例如。
PUT http://www.fluff.com/api/Fluff/123 HTTP/1.1
Host: www.fluff.com
Content-Length: 11
{"Data":"1"}
This was busting my balls for a small eternity, total embarrassment.
这让我的球在短暂的永恒中彻底崩溃,完全尴尬。
回答by Lev K.
Your client application and server application must be under same domain, for example :
您的客户端应用程序和服务器应用程序必须在同一个域下,例如:
client - localhost
客户端 - 本地主机
server - localhost
服务器 - 本地主机
and not :
并不是 :
client - localhost:21234
客户端 - 本地主机:21234
server - localhost
服务器 - 本地主机
回答by jpgrassi
I'm running an ASP.NET MVC 5 application on IIS 8.5. I tried all the variations posted here, and this is what my web.config
looks like:
我正在 IIS 8.5 上运行 ASP.NET MVC 5 应用程序。我尝试了这里发布的所有变体,这就是我的web.config
样子:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/> <!-- add this -->
</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-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" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
I couldn't uninstall WebDav from my Server because I didn't have admin privileges. Also, sometimes I was getting the method not allowed
on .css and .js files. In the end, with the configuration above set up everything started working again.
我无法从我的服务器上卸载 WebDav,因为我没有管理员权限。此外,有时我会收到method not allowed
.css 和 .js 文件。最后,有了上面的配置,一切又开始工作了。
回答by Владимiръ
Decorating one of the action params with [FromBody] solved the issue for me:
用 [FromBody] 装饰其中一个动作参数为我解决了这个问题:
public async Task<IHttpActionResult> SetAmountOnEntry(string id, [FromBody]int amount)
However ASP.NET would infer it correctly if complex object was used in the method parameter:
但是,如果在方法参数中使用了复杂对象,ASP.NET 将正确推断它:
public async Task<IHttpActionResult> UpdateEntry(string id, MyEntry entry)
回答by Adam Levitt
Another cause of this could be if you don't use the default variable name for the "id" which is actually: id.
另一个原因可能是如果您不使用“id”的默认变量名称,实际上是:id。
回答by Petr ?ugar
In my case the error 405 was invoked by static handler due to route ("api/images") conflicting with the folder of the same name ("~/images").
在我的情况下,由于路由(“api/images”)与同名文件夹(“~/images”)冲突,静态处理程序调用了错误 405。
回答by Naveen Kumar G C
You can remove webdav module manually from GUI for the particular in IIS.
1) Goto the IIs.
2) Goto the respective site.
3) Open "Handler Mappings"
4) Scroll downn and select WebDav module. Right click on it and delete it.
您可以从 GUI 中手动删除 webdav 模块,以便在 IIS 中进行特定操作。
1) 转到 IIs。
2) 转到相应的站点。
3) 打开“处理程序映射”
4) 向下滚动并选择 WebDav 模块。右键单击它并删除它。
Note: this will also update your web.config of the web app.
注意:这也将更新您的 web 应用程序的 web.config。