简体   繁体   English

405方法不允许 - ASP.NET Web API

[英]405 method not allowed - ASP.NET Web API

I have checked all the answers on Google and StackOverflow for 405 method not allowed in ASP.NET Web API and none of the solutions is working. 我已经检查了Google上的所有答案,并且在ASP.NET Web API中不允许使用StackOverflow for 405方法,并且没有一个解决方案正常工作。

  1. Checked CORS 检查CORS
  2. Checked WebDAV 检查了WebDAV
  3. Checked for HTTPDelete Attribute 检查HTTPDelete属性

I am creating an ASP.NET Web API and have 2 dummy controllers. 我正在创建一个ASP.NET Web API并有2个虚拟控制器。

I am able to use HTTP Delete method for one controller and not the other controller. 我能够为一个控制器而不是另一个控制器使用HTTP Delete方法。

Value Controller 价值控制者

using System.Collections.Generic;
using System.Web.Http;

namespace JobSite_WebAPI.Controllers
{
  public class ValuesController : ApiController
  {
    List<string> strings = new List<string>()
    {
        "value1", "value2","value3"
    };
    // GET api/values
    public IEnumerable<string> Get()
    {
        return  strings;
    }

    // GET api/values/5
    public string Get(int id)
    {
        return strings[id];
    }

    // DELETE api/values/5
    public void Delete(int id)
    {
        strings.RemoveAt(id);
    }
  }
}

Job Details Controller 工作细节控制器

 using System;
 using System.Collections.Generic;
 using System.Linq;
 using System.Net;
 using System.Net.Http;
 using System.Web.Http;
 using DataAccess;

 namespace JobSite_WebAPI.Controllers
 {
  public class JobDetailController : ApiController
  {
    public JobDetailController()
    {
        JobSiteEntities entities = new JobSiteEntities();
        entities.Configuration.ProxyCreationEnabled = false;
    }
    public IEnumerable<JobDetail>Get()
    {
        using (JobSiteEntities entities = new JobSiteEntities())
        {
            return entities.JobDetails.ToList();
        }
    }

[HttpGet]
    public HttpResponseMessage Get(int id)
    {
        using (JobSiteEntities entities = new JobSiteEntities())
        {
            var entity = entities.JobDetails.FirstOrDefault(e => e.JOBID == id);
            if (entity != null)
            {
                return Request.CreateResponse(HttpStatusCode.OK, entity);
            }
            else
            {
                return Request.CreateErrorResponse(HttpStatusCode.NotFound, "Job With Id = " + id.ToString() + " not found");
            }
        }
    }


 [HttpGet]
    public HttpResponseMessage RetrieveJobByLocation(string locationName)
    {
        try
        {
            using (JobSiteEntities entities = new JobSiteEntities())
            {
                IEnumerable<JobDetail> jobDetails = entities.JobDetails.Where(e => e.Location.LocationName.ToLower() == locationName).ToList();

                if (jobDetails != null)
                    return Request.CreateResponse(HttpStatusCode.OK, jobDetails);
                else
                    return Request.CreateResponse(HttpStatusCode.NotFound);

            }
        }
        catch(Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest, ex);
        }
    }

    [HttpDelete]
    public HttpResponseMessage Delete(int jobId)
    {
        try
        {
            using (JobSiteEntities entities = new JobSiteEntities())
            {
                var entity = entities.JobDetails.FirstOrDefault(e => e.JOBID == jobId);

                if (entity == null)
                {
                    return Request.CreateResponse(HttpStatusCode.NotFound, "Job Id with id " + jobId + "is not found");
                }
                else
                {
                    entities.JobDetails.Remove(entity);
                    entities.SaveChanges();
                    return Request.CreateResponse(HttpStatusCode.OK);
                }
            }
        }
        catch (Exception ex)
        {
            return Request.CreateResponse(HttpStatusCode.BadRequest, ex);
        }
    }
}

}

WebAPIConfig.cs WebAPIConfig.cs

 var cors = new EnableCorsAttribute("*", "*", "*");
 config.EnableCors(cors);


 // Web API routes
 config.MapHttpAttributeRoutes();

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

        );
        config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/octet-stream"));

Web.Config Web.Config中

 <remove name="WebDAV" />
  <remove name="ExtensionlessUrlHandler-Integrated-4.0" />
  <remove name="OPTIONSVerbHandler" />
  <remove name="TRACEVerbHandler" />
  <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />

I have enabled CORS,disabled WebDAV.also added HTTPDelete attribute to my delete methods. 我启用了CORS,禁用了WebDAV.also将HTTPDelete属性添加到我的删除方法中。

The issue am facing is for Value Controller Delete method works fine from Fiddler but for JobDetails Controller i get a 405 method not allowed. 面临的问题是价值控制器删除方法从Fiddler工作正常,但对于JobDetails控制器,我得到405方法不允许。

I am able to do a GET and POST Method.Am facing the same issue with PUT too. 我能够做一个GET和POST方法。我也面临与PUT相同的问题。

Added error message screenshots from fiddler. 添加了来自fiddler的错误消息截图。 Fiddler URL Fiddler Error Message Fiddler URL Fiddler错误消息

It works for ValuesController because the convention-based route template... 它适用于ValuesController因为基于约定的路由模板...

"api/{controller}/{id}" 

has {id} placeholder, which the controller conforms to, while JobDetailController.Delete(int jobId) does not match the route template because of jobId parameter name. 具有{id}占位符,控制器符合该占位符,而JobDetailController.Delete(int jobId)由于jobId参数名称而与路径模板不匹配。 Change those parameter arguments to int id in order for it to match route template set by the convention. 将这些参数参数更改为int id ,以使其匹配约定设置的路由模板。

[HttpDelete]
public HttpResponseMessage Delete(int id) {
    //...
}

Otherwise you could instead use attribute routing as it is also enabled with config.MapHttpAttributeRoutes() 否则你可以使用属性路由,因为它也使用config.MapHttpAttributeRoutes()启用

Reference: Attribute Routing in ASP.NET Web API 2 参考: ASP.NET Web API 2中的属性路由

[RoutePrefix("api/JobDetail")] 
public class JobDetailController : ApiController {

    [HttpGet]
    [Route("")] //Matches GET api/jobdetail
    public IEnumerable<JobDetail> Get() {
        //...
    }

    [HttpGet]
    [Route("{id:int}")] //Matches GET api/jobdetail/1
    public HttpResponseMessage Get(int id) {
       //...
    }

    [HttpGet]
    [Route("{locationName}")] //Matches GET api/jobdetail/somewhere
    public HttpResponseMessage RetrieveJobByLocation(string locationName) {
        //...
    }

    [HttpDelete]
    [Route("{jobId:int}")] //Matches DELETE api/jobdetail/1
    public HttpResponseMessage Delete(int jobId) {
        //...
    }
}

Note that when routing to a controller it is either by convention or by attribute, not both. 请注意,在路由到控制器时,它是按惯例或按属性,而不是两者。 If routing by attribute to an action, then all the other actions on the controller need attribute routing as well. 如果按属性路由到操作,则控制器上的所有其他操作也需要属性路由。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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