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

Posted

技术标签:

【中文标题】405 方法不允许 - ASP.NET Web API【英文标题】:405 method not allowed - ASP.NET Web API 【发布时间】:2018-02-04 11:53:53 【问题描述】:

我已在 Google 和 *** 上检查了 ASP.NET Web API 中不允许的 405 方法的所有答案,但没有一个解决方案有效。

    已检查 CORS 已检查 WebDAV 已检查 HTTPDelete 属性

我正在创建一个 ASP.NET Web API 并有 2 个虚拟控制器。

我可以对一个控制器而不是另一个控制器使用 HTTP Delete 方法。

价值控制者

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);
    
  

工作细节控制器

 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

 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

 <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" />

我启用了 CORS,禁用了 WebDAV。还在我的删除方法中添加了 HTTPDelete 属性。

我面临的问题是值控制器删除方法在 Fiddler 中工作正常,但对于 JobDetails 控制器,我得到了一个不允许的 405 方法。

我能够执行 GET 和 POST 方法。我也面临与 PUT 相同的问题。

添加了来自 fiddler 的错误消息截图。 Fiddler URL Fiddler Error Message

【问题讨论】:

约定路由模板有id 占位符,而JobDetailController.Delete(int jobId) 与路由模板不匹配,因为jobId。将这些参数参数更改为 int id 以使其匹配路由模板 【参考方案1】:

它适用于ValuesController,因为基于约定的路由模板...

"api/controller/id" 

id占位符,控制器符合,而JobDetailController.Delete(int jobId)不匹配路由模板,因为jobId参数名称。将这些参数参数更改为int id,以使其与约定设置的路由模板匹配。

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

否则您可以改用属性路由,因为它也通过config.MapHttpAttributeRoutes() 启用

参考:Attribute Routing in 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) 
        //...
    

请注意,当路由到控制器时,要么按照约定要么按照属性,而不是两者兼而有之。如果通过属性路由到一个动作,那么控制器上的所有其他动作也需要属性路由。

【讨论】:

以上是关于405 方法不允许 - ASP.NET Web API的主要内容,如果未能解决你的问题,请参考以下文章

ASP.NET Core 2.2 WebAPI 405 方法不允许

“405 方法不允许” - 使用 ASP.NET jQuery ajax POST 时

如何将对象数组发送到服务器。 Asp.Net Core 3.1 405 方法不允许

删除返回错误 405(不允许方法) 我正在使用 React 和 ASP.net。我没有大多数人说要编辑的网络配置文件,所以我迷路了

使用 IIS 时方法不允许 405

ASP.NET Web API - 尝试传递参数时不支持 GET HTTP Verb (405)