简体   繁体   中英

ASP.NET Web Api “The requested resource does not support http method PUT/DELETE”

I am working on building an API with ASP.NET/C#. However, when attempting to make either a PUT or DELETE request, I receive the following error:

"The requested resource does not support http method PUT (or DELETE)"

I realize this issue has been discussed before; however, I have looked over the responses (including this one ) to related questions but have yet to find the solution. I have disabled WebDAV and ensured that the verbs are allowed in the ExtensionlessUrlHanlder. The "webserver" portion of my web.config is as follows:

  <system.webServer>
    <modules>
      <remove name="FormsAuthentication" />
      <remove name="WebDAVModule"/>
      <add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
      <add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
    </modules>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
      </customHeaders>
    </httpProtocol>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
      <remove name="OPTIONSVerbHandler" />
      <remove name="WebDAV" />
      <remove name="TRACEVerbHandler" />
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
    </handlers>
  <validation validateIntegratedModeConfiguration="false" />
</system.webServer>

The controller is as follows:

namespace MidamAPI.Controllers
{
    [RoutePrefix("SupplyItems")] 
    public class SupplyItemsController : ApiController
    {
        UnitOfWork worker = new UnitOfWork();

        [Route("")]
        [HttpGet]
        public string Get()
        {
            IEnumerable<SupplyItemsDTO> dtoList =  Mapper.Map<List<SupplyItem>, List<SupplyItemsDTO>>(worker.SupplyItemRepo.Get().ToList());
            return JsonConvert.SerializeObject(dtoList);
        }

        [Route("{propertyType}")]
        public string Get(String propertyType = "BK")
        {
                 IEnumerable<SupplyItemsDTO> dtoList = null;
            if (propertyType.Equals("POPEYES", StringComparison.CurrentCultureIgnoreCase))
            {dtoList  = Mapper.Map<List<PopeyesSupplyItem>, List<SupplyItemsDTO>>(worker.PopeyesItemRepo.Get().ToList());

            }
            dtoList = Mapper.Map<List<BKSupplyItem>, List<SupplyItemsDTO>>(worker.BKItemRepo.Get().ToList());


            return JsonConvert.SerializeObject(dtoList);
        }

        [Route("{id:int}")]
        public string Get(int id)
        {
            SupplyItemsDTO dto = Mapper.Map<SupplyItem, SupplyItemsDTO>(worker.SupplyItemRepo.GetByID(id)); 

            return JsonConvert.SerializeObject(dto);
        }

           [Route("")]
           [HttpPost]
        public HttpResponseMessage Post([FromBody]SupplyItem itm)
        {
            try
            {
                worker.SupplyItemRepo.Insert(itm);
                worker.Save();
                return Request.CreateResponse(HttpStatusCode.OK, itm);
            }
            catch (Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest, ex);
            }

        }

                 [Route("")]
           [HttpDelete]
           public HttpResponseMessage Delete(int id)
           {
               try
               {
                   SupplyItem itm = worker.SupplyItemRepo.GetByID(id);
                   worker.SupplyItemRepo.Delete(itm);
                   worker.Save();
                   return Request.CreateResponse(HttpStatusCode.OK, itm);
               }
               catch(Exception ex)
               {
                   return Request.CreateResponse(HttpStatusCode.BadRequest, ex);
               }
           }

        [Route("")]
        [HttpPut]
        public HttpResponseMessage Put(int id, SupplyItem item) {
            try
            {
                item.ID = id;
                worker.SupplyItemRepo.Update(item);
                return Request.CreateResponse(HttpStatusCode.OK, item);
            }
            catch(Exception ex)
            {
                return Request.CreateResponse(HttpStatusCode.BadRequest, ex);
            }
        }
    }
}

The GET and POST calls work as expected. I do not want to alter the applicationhost.config file, really modify the web server in any way (since this is my development machine), or use headers that might represent a security vulnerability.

The response headers:

    Access-Control-Allow-Credentials →true
Access-Control-Allow-Headers →Origin, X-Requested-With, Content-Type, Accept, X-Token,Authorization
Access-Control-Allow-Methods →GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Methods →GET, POST, PUT, DELETE, OPTIONS
Access-Control-Allow-Origin →*
Allow →GET
Cache-Control →no-cache
Content-Length →72
Content-Type →application/json; charset=utf-8
Date →Tue, 10 Oct 2017 13:39:03 GMT
Expires →-1
Pragma →no-cache
Server →Microsoft-IIS/8.0
X-AspNet-Version →4.0.30319
X-Powered-By →ASP.NET
X-SourceFiles →=?UTF-8?B?QzpcVmlzdWFsIFN0dWRpbyBQcm9qZWN0c1xNaWRhbWVyaWNhQVBJXE1pZGFtQVBJXHN1cHBseWl0ZW1zXDQ1NA==?=

The request in the IIS logs:

2017-10-10 13:27:35 ::1 PUT /supplyitems/454 - 57263 - ::1 PostmanRuntime/6.3.2 - 405 0 0 0

My routing:

  config.Routes.MapHttpRoute(
              name: "DefaultAPI",
              routeTemplate: "{controller}/{id}",
              defaults: new { id = RouteParameter.Optional }
          );

Any advice is appreciated. I am using IIS Express. Thanks.

You might still have some extra modules installed. Even if you get those fixed, your request and routes won't match.

Your route config is being ignored as you have explicitly set the routes using your route attributes. You should update your DELETE method route attribute to [Route("{id:int}")] . For the PUT method, it is a little more unclear as to what you are doing, but I would assume you would want to do something like this: [Route("{id:int}")] [HttpPut] public HttpResponseMessage Put([FromUrl]int id, [FromBody]SupplyItem item) { ...

The adventure with that error for me was:

You are getting that probably because you have some extra IIS modules installed: WebDAV If you don't need it I would just remove it from your IIS.

This module is part of IIS Roles. To get rid of that go to: Windows Features -> Turn Windows Features On/Off -> Internet Information Services -> World Wide Web Services -> Common HTTP Features -> WebDAV Publishing.

If you want to keep it on, you need to add PUT/DELETE to ISAPI filters I think.

More explanation about here: https://stackoverflow.com/a/33552821/4869329

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM