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.
I am creating an ASP.NET Web API and have 2 dummy controllers.
I am able to use HTTP Delete method for one controller and not the other controller.
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
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" />
I have enabled CORS,disabled WebDAV.also added HTTPDelete attribute to my delete methods.
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.
I am able to do a GET and POST Method.Am facing the same issue with PUT too.
Added error message screenshots from fiddler. Fiddler URL Fiddler Error Message
It works for ValuesController
because the convention-based route template...
"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. Change those parameter arguments to int id
in order for it to match route template set by the convention.
[HttpDelete]
public HttpResponseMessage Delete(int id) {
//...
}
Otherwise you could instead use attribute routing as it is also enabled with config.MapHttpAttributeRoutes()
Reference: 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) {
//...
}
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With