On my Web API I have a few [HttpGet] functions that work perfectly, but the one that is [HttpDelete] (on the same Controller) doesn't work, it returns 404 error.
[Authorize]
[RoutePrefix("Users")]
public class UsersController : ApiController
{
[HttpDelete]
[Route("DeleteUser/{ID}")]
public void Delete(int id)
{
_UserRepository.Delete(id);
}
}
On the web.config I have the verb set to *:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="FormsAuthentication" />
</modules>
<handlers>
<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" />
</handlers>
</system.webServer>
The AJAX call:
deleteUser = function (id, callback) {
$.ajax({
url: "../../API/Users/DeleteUser/" + id,
type: "DELETE",
success: function () {
callback;
}
});
}
The error:
HTTP Error 404.0 - Not Found
Detailed Error Information
Module IIS Web Core Notification MapRequestHandler Handler StaticFile
Error Code 0x80070002
Requested
URL https://www.example.com:443/Rejected-By-UrlScan?~/API/Users/DeleteUser/155
Physical Path d:\wr\mySite\example.com\Rejected-By-UrlScan
Logon Method Anonymous Logon User Anonymous
All the calls are authenticated with OWIN Authentication and a bearer token.
An example of a working call on the same page:
getUsers = function (callback) {
$.get("../../API/Users/GetUsers/", callback);
}
What can causes it?
As stated in another post, there may be an extension (UrlScan) configured in IIS to block DELETE requests. You can check your IIS for this extension.
Try setting the verbs manually
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
<remove name="FormsAuthentication" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add name="ExtensionlessUrlHandler-Integrated-4.0"
path="*."
verb="GET,HEAD,POST,DEBUG,DELETE,PUT"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Also check to make sure
That you are calling the correct path.
you do not have a folder that matches the intended route
Also, your route template place holder needs to match the action parameter name
[Authorize]
[RoutePrefix("Users")]
public class UsersController : ApiController {
[HttpDelete]
[Route("DeleteUser/{id:int}")] //Matches DELETE {root}/Users/DeleteUser/5
[AcceptVerbs("DELETE")]
public IHttpActionResult Delete(int id) {
//TODO: check if {id} exists and if not, then return NotFound()
_UserRepository.Delete(id);
return Ok();
}
//...other members
}
Related
I have SPA using angular(routing too is with angular).I have written http handler which will intercept old url and redirect to new url.
When I give path as * its hitting but with *.html not hitting my handler.
Please find code snip.
My Handler code-
public class PageHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
HttpRequest request = context.Request;
HttpResponse response = context.Response;
string newUrl=string.Empty;
if (Convert.ToString(request.Path) != null)
newUrl = GetNewURL(Convert.ToString(request.Path));
if (newUrl != string.Empty)
response.Redirect(newUrl);
else
response.Redirect("/404");
}
}
Webconfig setting-
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add verb="*" path="*.html,*.aspx" name="myHandler" type="LucidFox.Helpers.PageHandler"/>
</handlers>
Not sure why its not intercepting .aspx and .html
IIS 7's handler mapping is different than IIS 6's handler mapping. In IIS 6, you can map your handlers like this in web.config.It allows you to use multiple paths, comma-delimited.
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add verb="*" path="*.html,*.aspx" name="myHandler" type="LucidFox.Helpers.PageHandler"/>
</handlers>
In IIS 7, it's in a different section.It doesn't support multiple paths, so you need to map your handler for each path.
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<add verb="*" path="*.html" name="myHandler" type="LucidFox.Helpers.PageHandler"/>
<add verb="*" path="*.aspx" name="myHandler" type="LucidFox.Helpers.PageHandler"/>
</handlers>
In the asp.net mvc 5 + web api 2 am working on, some of the webapi routes that I defined are not working, while some are working perfectly. I can't seem to identify what the problem is. And before you ask I have read the whole SO questions and applied all the solutions I can find, but none of it seems to work in my current situation. I also checked, double checked and yet I can't figure out why. Here are some of the configurations and route registrations that I think affects web api.
Route definition
[HttpPost]
[Route("FollowApi/{profileId:int}/FollowClient" Name = "FollowClient")]
Application_start configuration
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RegisterRoutes(RouteTable.Routes);
Webconfig configuration
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
<add name="ImageResizingModule" type="ImageResizer.InterceptModule" />
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
<handlers>
<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" />
</handlers>
</system.webServer>
Please, any help or pointers as to why this problem is occurring will be seriously appreciated as I am in a time constrained situation.
Edit
Working api
public class CommonApiController : BaseApiController
{
[Authorize]
[HttpGet]
[Route("Client/GetInfoCounts")]
public IHttpActionResult GetInfoCounts()
{
//Method body
}
}
Not working api
public class FollowApiController : BaseApiController
{
[HttpPost]
[Route("FollowApi/{profileId:int}/FollowClient")]
public IHttpActionResult Follow(int profileId)
{
//Method body
}
}
It looks like the RoutePrefix on the controller was not included in the client call. My take away from this is that it makes sense to have a certain pattern for troubleshooting these kind of problems.
Something like:
Is the url correct?
Is the httpMethod correct?
Are the parameters named correctly?
I'm working on a ASP.NET WebAPI project with basic CRUD operations. The project runs locally and has a sample database living inside Windows Azure.
So far, the Http GET and POST works fine, giving me a 200 and 201. But I'm struggling with DELETE and POST. I changed the handlers in the Web.config, removed WebDav, but none of this worked. Also enabling CORS and all sorts of Attributes like [AcceptVerbs] didn't work.
Any idea what I am doing wrong?
Fiddler Raw Output:
HTTP/1.1 405 Method Not Allowed
Cache-Control: no-cache
Pragma: no-cache
Allow: GET
Content-Type: application/json; charset=utf-8
Expires: -1
Server: Microsoft-IIS/8.0
X-AspNet-Version: 4.0.30319
X-SourceFiles: =?UTF-8?B?QzpcVXNlcnNcTWFyY1xPbmVEcml2ZVxEb2t1bWVudGVcRmlcVnNQcm9qZWt0ZVxONTIwMTQwODI1XE41XE41XGFwaVxwcm9kdWN0XDEwODM=?=
X-Powered-By: ASP.NET
Date: Sun, 14 Sep 2014 15:00:43 GMT
Content-Length: 75
{"Message":"The requested resource does not support http method 'DELETE'."}
Web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Controller:
public class ProductController : BaseApiController
{
public ProductController(IRepository<Product> repo)
: base(repo)
{
}
[HttpGet]
public IEnumerable<Product> Get()
{
//...
}
[HttpGet]
public Product Get(int id)
{
//...
}
[HttpPost]
public HttpResponseMessage Post([FromBody] Product product)
{
//...
}
[HttpPut]
public HttpResponseMessage Put(int productId, [FromBody] Product product)
{
//..
}
[HttpDelete]
public HttpResponseMessage Delete(int productId)
{
//..
}
}
Routing & Formatters:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Configure Web API to use only bearer token authentication.
config.SuppressDefaultHostAuthentication();
config.Filters.Add(new HostAuthenticationFilter(OAuthDefaults.AuthenticationType));
config.Routes.MapHttpRoute(
name: "Product",
routeTemplate: "api/product/{id}",
defaults: new {controller = "product", id = RouteParameter.Optional }
);
// Custom Formatters:
config.Formatters.XmlFormatter.SupportedMediaTypes.Remove(
config.Formatters.XmlFormatter.SupportedMediaTypes.FirstOrDefault(t => t.MediaType == "application/xml"));
var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver();
}
}
Finally I found what I messed up. The naming of the Id (productId) in both controller methods (Post and Put) must be the same as in the customized routing (id). When I changed it from productId to id both POST and PUT worked in fiddler. After that I switched back my Web.config settings to the default one. This is what I changed:
Controller:
[HttpPut]
public HttpResponseMessage Put(int id, [FromBody] Product product)
{
//..
}
[HttpDelete]
public HttpResponseMessage Delete(int id)
{
//..
}
Web.config:
<system.webServer>
<modules>
<remove name="FormsAuthentication" />
</modules>
<handlers>
<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" />
</handlers>
The "Attribute Routing in ASP.NET Web API 2" (20-Jan-2014) article tells us the following;
Routing is how Web API matches a URI to an action. Web API 2 supports
a new type of routing, called attribute routing.
( See: "Attribute Routing in ASP.NET Web API 2" )
So, as of Web API 2, you can also fix it by adding the route attribute [to the method in question] with the placeholder named as you wish.
[HttpDelete]
[Route("api/product/{productId}")]
public HttpResponseMessage Delete(int productId)
{
if (values.Count > productId) {
values.RemoveAt(productId);
}
}
Tested this in my own code, because I got hit with the same problem, and it worked like a charm!
Try adding this below code in your WebConfig file:
<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>
I also got the same issue, by doing this it got resolved!
I know this is a commonly addressed issue, and I've done everything that many posts here on SO suggest. When I try to delete a record using WebAPI (version 2) from my MVC5 front end running under local IIS, I get a 404 Not Found response. Here are the things I've tried:
I've added the following under <system.webServer /> in my WebAPI web.config:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<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" />
</handlers>
</system.webServer>
I've followed the instructions at: http://geekswithblogs.net/michelotti/archive/2011/05/28/resolve-404-in-iis-express-for-put-and-delete-verbs.aspx, which basically say to modify the ExtensionlessUrlHandler-Integrated-4.0 in IIS "Handler Mappings". It says to double click on the handler, click "Request Restrictions", and "Allow PUT and DELETE verbs". I've done this, and I still get the 404 error.
I've done an IIS reset.
Here's my MVC5 front end code that calls the WebAPI delete method - please note that when I manually navigate to api/bulletinboard/get/{0} where {0} is an integer, I get a valid JSON response. Below, contactUri is http://localhost/SiteName/api/bulletinboard/get/53 which returns valid JSON:
[HttpPost, ActionName("Delete")]
public ActionResult Delete(string appId, int id)
{
response = client.GetAsync(string.Format("api/bulletinboard/get/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;
if (response.IsSuccessStatusCode)
{
return RedirectToAction("MessageList", new { appId = appId });
}
else
{
LoggerHelper.GetLogger().InsertError(new Exception(string.Format(
"Cannot delete message due to HTTP Response Status Code not being successful: {0}", response.StatusCode)));
return View("Problem");
}
}
Here's my WebAPI delete method:
[HttpDelete]
public HttpResponseMessage Delete(int id)
{
BulletinBoard bulletinBoard = db.BulletinBoards.Find(id);
if (bulletinBoard == null)
{
return Request.CreateResponse(HttpStatusCode.NotFound);
}
db.BulletinBoards.Remove(bulletinBoard);
try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException ex)
{
return Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
return Request.CreateResponse(HttpStatusCode.OK, bulletinBoard);
}
Here's my WebApiConfig.cs in my WebAPI project:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors();
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "ApiWithActionName",
routeTemplate: "api/{controller}/{action}/{id}",
defaults: new { id = RouteParameter.Optional }
);
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
var json = config.Formatters.JsonFormatter;
json.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.Objects;
config.Formatters.Remove(config.Formatters.XmlFormatter);
config.Formatters.Add(new PlainTextFormatter());
}
QUESTION: What else can I try to resolve this error? This works fine when deployed from my local environment to my company's development servers.
for those who still looking for enable DELETE & PUT The below code solve my problem
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />
<remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<!--This will enable all Web API verbose-->
<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>
I've followed the instructions at: https://forums.asp.net/t/1961593.aspx?DELETE+PUT+verbs+result+in+404+Not+Found+in+WebAPI+only+when+running+locally
That says to only change this piece of code in your Web.config, and works fine for me!
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<validation validateIntegratedModeConfiguration="false" />
<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>
If you are using IIS, make sure you have the HTTP Verb set to allowed in Request Filtering. If its not there, you can set it to allow it on the side.
We were struggling with DELETE/PUT returning 404 errors on IIS 8. We did all of the above answers changing web.config to accept all Verbs, enabling put/delete in the request filtering. We had also disabled webDAV multiple ways. We found that the application pool was set to classic verses integrated (what it should have been). Now DELETE/PUT verbs work fine.
Mark Jensen solution worked for me.
Just changed my Application Pool from "Classic" to "Integrated" and my requests worked.
This issue can be fixed by IIS level configuration-
Open IIS->select your website->IIS (section) ->Request Filtering ->HHTP Verbs
Remove DELETE verb/ OR allow DELETE verb
Issue will get resolved.
What I did was just switch from using local IIS to IIS Express via the project properties on my WebAPI project, as a workaround. Doing this and deleting a record then resulted in a 405 Method Not Allowed error. I then changed the lines of code:
response = client.GetAsync(string.Format("api/bulletinboard/get/{0}", id)).Result;
contactUri = response.RequestMessage.RequestUri;
response = client.DeleteAsync(contactUri).Result;
To:
response = client.DeleteAsync(string.Format("api/bulletinboard/delete/{0}", id)).Result;
This is very strange because I have another project that runs the first block of code and it deletes records just fine. Anyways, this resolved my local problem. I understand this doesn't really resolve my main issue which was using local IIS, but this workaround worked for me.
If your project is working under IIS and not under IISExpress, try to set IISExpress Managed Pipeline Mode to Integrated.
PUT and DELETE verbs seems to have problem under Classic Managed Pipeline mode.
Good luck..
Roberto.
For me it was an ISAPI module called UrlScan which I had to completely remove from the application.
I have been trying to get DELETE working now for over an hour and I am a little frustrated. I have tried every recommendation I can find. I have removed EVERY reference to ANYTHING WEBDAV from my applicationconfig as well as copying my whole webserver section over. I did it in steps and tried different variations and I still cannot get it to work. Yes my method is called DELETE and I added the [HttpDelete] to further make sure it knew I wanted delete support. Any other suggestions? :/
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
<remove name="FormsAuthenticationModule" />
<remove name="WebDAVModule" />
</modules>
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
<add name="Access-Control-Allow-Methods" value="GET, POST, PUT, DELETE, OPTIONS" />
</customHeaders>
</httpProtocol>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="OPTIONSVerbHandler" />
<remove name="TRACEVerbHandler" />
<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>
Tried these and more:
Asp.NET Web API - 405 - HTTP verb used to access this page is not allowed - how to set handler mappings
Web API Put Request generates an Http 405 Method Not Allowed error
http://www.britishdeveloper.co.uk/2010/06/dont-use-modules-runallmanagedmodulesfo.html
Kinda ridiculous, if M$ is going to release a product they should make sure its configured to work as expected out of the box.
Here is the controller code, it doesn't even break in it though as the application "doesnt understand the DELETE verb". The HttpDelete I slapped on there is from System.Web.Http not the mvc one. The name is by convention but I was hoping if I stuck the attribute on it would understand anyways.
// DELETE api/product/5
[HttpDelete]
public HttpResponseMessage Delete(int id)
{
HttpResponseMessage response = null;
var product = _uow.Repository<Product>().ById(id);
if (product == null)
response = Request.CreateResponse(HttpStatusCode.NotFound);
_uow.Repository<Product>().Delete(id);
try
{
_uow.Save();
}
catch (DbUpdateConcurrencyException ex)
{
response = Request.CreateErrorResponse(HttpStatusCode.NotFound, ex);
}
var model = Mapper.Map<ProductModel>(product);
return response ?? Request.CreateResponse(HttpStatusCode.OK, model);
}
This is in my angularJs controller
$scope.deleteProduct = function (product) {
product.$delete();
dismiss();
//$scope.products = _.without($scope.products, product);
};
This is in my angular service using $resource. (The rest of my crud is working)
minopApp.services.factory("ProductSvc", ['$resource',
function ($resource) {
return $resource('/api/product/:id',
{ productId: '#id' },
{
update: { method: 'PUT' }
});
}]).value('version', '0.1');
This is my routing inside the app.js
minopApp.config(
['$routeProvider',
function ($routeProvider) {
$routeProvider.
when('/products', {
templateUrl: 'areas/product/product-list.html',
controller: 'ProductCtrl'
}).
when('/products/new', {
templateUrl: 'areas/product/product-create.html',
controller: 'ProductCtrl'
}).
when('/products/:id', {
templateUrl: 'areas/product/product-detail.html',
controller: 'ProductCtrl'
}).
when('/products/:id/edit', {
templateUrl: 'areas/product/product-edit.html',
controller: 'ProductCtrl'
}).
otherwise({
redirectTo: '/products'
});
}],
['$compileProvider',
function ($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|ftp|mailto|file|tel):/);
}]
);
It looks a lot in your Web.config. Can you trim it to...
<system.webServer>
<modules runAllManagedModulesForAllRequests="true" runManagedModulesForWebDavRequests="true">
<remove name="WebDAVModule" />
</modules>
<handlers>
<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" />
</handlers>
</system.webServer>
I have tested it in IIS with WebDAV component installed and both PUT and DELETE verbs work with it.
I was stuck in a position similar to this but with a with PUT verb when I suddenly realize, after requesting my Api via Fiddler Composer, that my restClient was performing an unvalid request like using
"api/resource?id=1234"
instead of
"api/resource/1234"