Веб-API Put запрос генерирует Http 405 метод не допускается ошибка
вот звонок в PUT метод на моем веб-API-третья строка в методе (я вызываю веб-API из ASP.NET MVC front end):

client.BaseAddress и http://localhost/CallCOPAPI/.
здесь contactUri:

здесь contactUri.PathAndQuery:

и, наконец, вот мой 405 ответ:

вот WebApi.config в моем веб-API проект:
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);
Я пробовал зачистки вниз по пути, который проходит в PutAsJsonAsync до string.Format("/api/department/{0}", department.Id) и string.Format("http://localhost/CallCOPAPI/api/department/{0}", department.Id) не повезло.
есть ли у кого-нибудь идеи, почему я получаю ошибку 405?
обновление
согласно запросу, вот мой код контроллера отдела (я опубликую как код контроллера отдела для моего проекта переднего плана, так и код ApiController отдела для Веб-API):
Контроллер Переднего Отдела
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 отдел 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);
}
}
}
8 ответов:
Итак, я проверил функции Windows, чтобы убедиться, что у меня не установлена эта вещь под названием WebDAV, и она сказала, что я этого не сделал. в любом случае, я пошел вперед и разместил следующее в своем интернете.config (как передний конец, так и WebAPI, просто чтобы быть уверенным), и он работает сейчас. Я поместил это внутрь
<system.webServer>.<modules runAllManagedModulesForAllRequests="true"> <remove name="WebDAVModule"/> <!-- add this --> </modules>кроме того, часто требуется добавить следующее
web.configв обработчиках. Спасибо Бабак<handlers> <remove name="WebDAV" /> ... </handlers>
WebDav-SchmebDav.. ..убедитесь, что вы правильно создали url-адрес с идентификатором. Не отправляйте его как http://www.fluff.com/api/Fluff?id=MyID, отправить его как http://www.fluff.com/api/Fluff/MyID.
например.
PUT http://www.fluff.com/api/Fluff/123 HTTP/1.1 Host: www.fluff.com Content-Length: 11 {"Data":"1"}это ломало мои яйца в течение небольшой вечности, полное смущение.
добавьте это в ваш
web.config. Вы должны сказать IIS, чтоPUTPATCHDELETEи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>также проверьте, что у вас нет WebDAV включен.
я запускаю ASP.NET приложение MVC 5 на IIS 8.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>Я не мог удалить WebDav с моего сервера, потому что у меня не было прав администратора. Кроме того, иногда я получал
method not allowedдалее .css и .JS файлы. В конце концов, с настройкой выше все снова начало работать.
украшение одного из парамов действия с помощью [FromBody] решило проблему для меня:
public async Task<IHttpActionResult> SetAmountOnEntry(string id, [FromBody]int amount)однако ASP.NET было бы правильно сделать вывод, если сложный объект был использован в параметре метода:
public async Task<IHttpActionResult> UpdateEntry(string id, MyEntry entry)
другая причина этого может быть, если вы не используете имя переменной по умолчанию для "id", который на самом деле: id.
клиентское и серверное приложения должны находиться в одном домене, например:
клиент-localhost
сервер - localhost в
и
клиент-localhost: 21234
сервер - localhost в
в моем случае ошибка 405 была вызвана статическим обработчиком из - за маршрута ("api/images"), конфликтующего с папкой с тем же именем ("~/images").
Comments