Custom IHttpHandler mapping in ASP.NET MVC - asp.net

I am trying to configure a custom IHttpHandler in web.config and I don't understand the behavior I'm getting. I'm trying this using IIS express.
This is how my Sytem.WebServer section of web.config looks like:
<system.webServer>
<modules runAllManagedModulesForAllRequests="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" />
<add name="dynamicPngHandler" verb="*" path="*.png" type="ImagServingTest.HttpHandler.PureCustomPngHandler, ImagServingTest"/>
</handlers>
</system.webServer>
http ://localhost:48705/default.png (does not work, I get a 404)
http ://localhost:48705/something/default.png (does not work, I get a 404)
http ://localhost:48705/something/something/default.png (does not work, I get a 404)
http ://localhost:48705/something/something/something/default.png (works)
I don't understand why this is happening. Why does the mapping fail until I have a url with three parts after localhost?
I imagine the fact that this is an MVC4 app is important (although I can't see why).
UPDATE
I've tried this using web forms instead of MVC and it works as expected.
In the MVC project I tried moving the custom handler so it was the first on the handlers' list in web.config and it still did not work.

The reason for the request failing for those urls is that they were being covered by MVC's default routing rule: "{controller}/{action}/{id}" because all those have defaults.
I've added routes.IgnoreRoute("{ignore}.png"); to RouteConfig and I'm now seeing the behavior that I expected

Related

HTTP Patch Verb not working on windows server 2012 r2

I'm working on single page application which consumes WebApi for data manipulation. My site was hosted on Windows Server 2008 R2 (IIS 7.5.7600.16385) and working fine, however after migration to Windows Server 2012 R2 (IIS 8.5.9600.16384) HTTP PATCH VERBS are not working, api call returns with status code 400 "Bad Request". I have tried following code snippet in web.config but got no luck.
<handlers>
<remove name="WebDAV" />
<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" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" type="System.Web.Handlers.TransferRequestHandler" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" />
<add name="Telerik.ReportViewer.axd_*" type="Telerik.ReportViewer.WebForms.HttpHandler, Telerik.ReportViewer.WebForms, Version=9.0.15.225, Culture=neutral, PublicKeyToken=a9d7983dfcc261be" path="Telerik.ReportViewer.axd" verb="*" />
</handlers>
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule" />
</modules>
Googling again and again but got nothing useful, I'm stuck here, Any help would be appreciated.
These are the web.config settings I used when I had a similar problem with PUT requests after moving servers.
<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" />
When I tried to send API call outside from network, everything was working as expected. Further investigations reveals that network firewall policy was problematic. By mistake production server was blacklisted by NOC team.
Thanks all for your efforts :)

Implementing static files cache in asp.net mvc

I am trying to implement static files cache in the ASP.net mvc application.
What i did:
I've added into Content folder a web.config file with the following content:
<?xml version="1.0"?>
<configuration>
<system.webServer>
<staticContent>
<clientCache cacheControlCustom="public" cacheControlMode="UseMaxAge" cacheControlMaxAge="300.0:00:00" />
</staticContent>
</system.webServer>
</configuration>
In the website web.config file, i commented out some lines of code:
<system.webServer>
<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" />
<!-- Commented them out
<add verb="GET" path="*.js" name="Static for js" type="System.Web.StaticFileHandler" />
<add verb="GET" path="*.css" name="Static for css" type="System.Web.StaticFileHandler" />
<add verb="GET" path="*.png" name="Static for png" type="System.Web.StaticFileHandler" />
<add verb="GET" path="*.jpg" name="Static for jpg" type="System.Web.StaticFileHandler" />
-->
</handlers>
Now, publishing the website and inspecting the resources, i get the folowing response:
I see is missing the Expire header ?! (shouldn't it be there in order for cache to work)
Does the response headers tell the browser to cache the resource for the next 25920000 seconds?
I am doing things correctly in order to cache the static files?
This is correct, and you should be fine.
Some might say you should add Expires, too, for clients which do not understand HTTP/1.1, but as already argued in the first linked article, that shouldn't be a real concern, even less now, 7 years later.

ASP.NET Web API - PUT & DELETE Verbs Not Allowed - IIS 8

I recently upgraded from Visual Studio 2010 to the Visual Studio 2012 RC. The installer also installs IIS 8 Express which Visual Studio now uses as the default web server.
IIS 8 is blocking my WEB API requests that use PUT AND DELETE verbs. IIS returns a 405 error, The requested resource does not support http method 'PUT'.
I know people have issues with this in the past and there are several messages about it on Stack Overflow. With IIS 7 Express the solution was to uninstall WebDav. Unfortunately I don't see any way to do that with IIS 8.
I've tried editing out the WebDav sections from applicationhost.config but that hasn't helped. For example I removed <add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" /> from the config file.
I've spent far too long on this. There must be a simple way to enable PUT and DELETE?
Okay. I finally got to the bottom of this. You need to jump through some hoops to get the PUT and DELETE verbs working correctly with IIS8. In fact if you install the release candidate of VS 2012 and create a new WEB API project you'll find that the sample PUT and DELETE methods return 404 errors out of the box.
To use the PUT and DELETE verbs with the Web API you need to edit %userprofile%\documents\iisexpress\config\applicationhost.config and add the verbs to the ExtensionlessUrl handler as follows:
Change this line:
<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
to:
<add name="ExtensionlessUrl-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
In addition to the above you should ensure WebDAV is not interfering with your requests. This can be done by commenting out the following lines from applicationhost.config.
<add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" />
<add name="WebDAVModule" />
<add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" />
Also be aware that the default Web API convention is that your method name should be the same as the invoked HTTP verb. For example if you're sending an HTTP delete request your method, by default, should be named Delete.
Change Your Web.Config file as below. It will act like charm.
In node <system.webServer> add below portion of code
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
After adding, your Web.Config will look like below
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<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="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>
Remove the WebDAV works perfectly for my case:
<modules>
<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,DELETE,PATCH,OPTIONS"
type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
it always better to solve the problem through the web.config instead of going to fix it through the iis or machine.config to grantee it wouldn't happen if the app hosted at another machine
Update your web.config
<system.webServer>
<modules>
<remove name="WebDAVModule"/>
</modules>
<handlers>
<remove name="WebDAV" />
<remove name="ExtensionlessUrl-Integrated-4.0" />
<add name="ExtensionlessUrl-Integrated-4.0"
path="*."
verb="GET,HEAD,POST,DEBUG,DELETE,PUT"
type="System.Web.Handlers.TransferRequestHandler"
preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
http://odetocode.com/blogs/scott/archive/2012/08/07/configuration-tips-for-asp-net-mvc-4-on-a-windows.aspx
Removes the need to modify your host configs.
In Asp.Net Web API - webconfig. This works in all browser.
Add the following code inside the System.web tag
<webServices>
<protocols>
<add name="HttpGet"/>
<add name="HttpPost"/>
</protocols>
</webServices>
Replace your system.webserver tag with this below code
<httpProtocol>
<customHeaders>
<add name="Access-Control-Allow-Origin" value="*" />
<add name="Access-Control-Allow-Methods" value="GET,PUT,POST,DELETE" />
<add name="Access-Control-Allow-Headers" value="Content-Type" />
</customHeaders>
</httpProtocol>
<modules runAllManagedModulesForAllRequests="false">
<remove name="WebDAVModule" />
</modules>
<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" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
this worked for me on iis8 together with some of the other answers. My error was a 404.6 specifically
<system.webServer>
<security>
<requestFiltering>
<verbs applyToWebDAV="false">
<add verb="DELETE" allowed="true" />
</verbs>
</requestFiltering>
</security>
</system.webServer>
Just a quick update for anyone else who might run into this issue. As of today, changing the %userprofile%\documents\iisexpress\config\applicationhost.config does NOT work any longer (this was working fine until now, not sure if this is due to a Windows update). After hours of frustration, I changed the web.config to add these handlers to system.webserver to get it to work:
<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>
Enable CORS (nice and neat)
1.Add CORS nuget package
Install-Package microsoft.aspnet.webapi.cors
2.in the WebApiConfig.cs file to Register method add bellow code :
config.EnableCors();
ex:
using System.Web.Http;
namespace test
{
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
config.EnableCors(); //add this**************************
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
}
}
}
3.Add bellow code into namespace of the controller include get,post,delete,put or any http method
[EnableCors(origins: "The address from which the request comes", headers: "*", methods: "*")]
ex:
using System.Web.Http.Cors;//add this******************************
namespace Test.Controllers
{
[EnableCors(origins: "http://localhost:53681/HTML/Restaurant.html", headers: "*", methods: "*")]
public class RestaurantController : ApiController
{
protected TestBusinessLayer DevTestBLL = new TestBusinessLayer();
public List<Restaurant> GET()
{
return DevTestBLL.GetRestaurant();
}
public List<Restaurant> DELETE(int id)
{
return DevTestBLL.DeleteRestaurant(id);
}
}
}
reference :http://www.asp.net/web-api/overview/security/enabling-cross-origin-requests-in-web-api
For PHP, it was simply:
Open IIS
Go to Handler Mappings
click edit on php5.6.x or php7.0.x
click "request restrictions"
under the verbs tab, select "one of the following verbs" and add "GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS"
I imagine this will work with other handlers too.
After nothing worked, I was able to solve this by below steps:
• Did not select ‘WEB DAV PUBLISHING’ IIS settings, while installing IIS.
• INETMGR - Default Website – Request Filtering – HTTP Verbs – PUT as True
After endless searching and trying the already supplied answers (adding the PUT,DELETE verbs and remove WEBdav) it just didn't work.
I went to IIS logging settings: > View Log Files. In my case W3SVC4 was the folder with the latest date, opened the folder, looked up the latest log file and saw this entry:
GET /Rejected-By-UrlScan ~/MYDOMAIN/API/ApiName/UpdateMETHOD
The Update method was listed with verb GET, weird right? So I Googled for Rejected-By-UrlScan and found this link: UrlScan Broke My Blog.
I went to here: %windir%\system32\inetsrv\urlscan\UrlScan.ini
Basically, the UrlScan blocked PUT and DELETE verbs.
I opened this INI file, added the PUT and DELETE to the AllowVerbs and removed them from the DenyVerbs listings.
I saved the INI file and it worked! So for me these steps were necessary next to the ExtensionlessUrlHandler hints.
Windows Webserver 2008 R2 (64 bit), IIS 7.5.
I'm using this in combination with DotNetNuke (DNN) WebAPI. ASP.Net 4.0
My update method:
[HttpPut]
[DnnAuthorize(StaticRoles = "MyRoleNames")]
public HttpResponseMessage UpdateMETHOD(DTO.MyObject myData)
I have faced the same issue with you, then solved it,
Here are solutions, I wish it maybe can help
First
In the IIS modules Configuration, loop up the WebDAVModule, if your web server has it, then remove it
Second
In the IIS handler mappings configuration, you can see the list of enabling handler, to choose the PHP item, edit it, on the edit page, click request restrictions button, then select the verbs tab in the modal, in the specify the verbs to be handle label, check the all verbs radio, then click ok, you also maybe see a warning, it shows us that use double quotation marks to PHP-CGI execution, then do it
if done it, then restart IIS server, it will be ok
Besides all above solutions, check if you have the "id" or any custom defined parameter in the DELETE method is matching the route config.
public void Delete(int id)
{
//some code here
}
If you hit with repeated 405 errors better reset the method signature to default as above and try.
The route config by default will look for id in the URL. So the parameter name id is important here unless you change the route config under App_Start folder.
You may change the data type of the id though.
For example the below method should work just fine:
public void Delete(string id)
{
//some code here
}
Note: Also ensure that you pass the data over the url not the data method that will carry the payload as body content.
DELETE http://{url}/{action}/{id}
Example:
DELETE http://localhost/item/1
Hope it helps.
Here is how you allow extra HTTP Verbs using the IIS Manager GUI.
In IIS Manager, select the site you wish to allow PUT or DELETE for.
Click the "Request Filtering" option. Click the "HTTP Verbs" tab.
Click the "Allow Verb..." link in the sidebar.
In the box that appears type "DELETE", click OK.
Click the "Allow Verb..." link in the sidebar again.
In the box that appears type "PUT", click OK.
I am using an ashx file in an MVC application and none of the above answers worked for me. IIS 10.
Here's what did work. Instead of changing "ExtensionlessUrl-Integrated-4.0" in IIS or web.config I changed "SimpleHandlerFactory-Integrated-4.0" for "*.ashx" files:
<add name="SimpleHandlerFactory-Integrated-4.0" path="*.ashx"
verb="GET,HEAD,POST,DEBUG,PUT,DELETE"
type="System.Web.UI.SimpleHandlerFactory"
resourceType="Unspecified" requireAccess="Script"
preCondition="integratedMode,runtimeVersionv4.0" />
Trial an error is not the correct way to fix this problem. What needs to be done is:
To identify the source that blocks your PUT/DELETE requests
then you can remove it, disable it or even better configure it:
1- In order to know the source , you have to configure the Failed Request Tracing in IIS.
2- You have "Add" what Errors to log
Make sure you use short life span for this tracing entry to avoid overwhelming your system with log files. IIS will generate a separate xml file for each call.
3- Make the erroneous request using Postman or Swagger to generate a tracing error entry.
4- From the previous screen, you can select "View Trace Logs" to take you to the generated log files.
5- Open the erroneous log file using internet explorer. And accept any messages.
6- Notice the source that blocks your request.
7- disable it either in Modules or Mapping Handler from IIS interface or in your web.config as demonstrated by other posters.
I am not sure if you have edited right configuration file. Try following steps
open %userprofile%\ducuments\iisexpress\config\applicationhost.config
By default bellow given entries are commented in the applicationhost.config file. uncomment these entries.
<add name="WebDAVModule" image="%IIS_BIN%\webdav.dll" />
<add name="WebDAVModule" />
<add name="WebDAV" path="*"
verb="PROPFIND,PROPPATCH,MKCOL,PUT,COPY,DELETE,MOVE,LOCK,UNLOCK"
modules="WebDAVModule" resourceType="Unspecified" requireAccess="None"
/>
The another reason can be the following:
I changed my Url for Web Api method according to this answer:
Url.Action("MyAction", "MyApiCtrl", new { httproute = "" })
But this method creates link like:
/api/MyApiCtrl?action=MyAction
This works correctly with GET and POST requests but not with PUT or DELETE.
So I just replaced it with:
/api/MyApiCtrl
and it fixed the problem.
You can convert your Delete method as POST as;
[HttpPost]
public void Delete(YourDomainModel itemToDelete)
{
}
In IIS 8.5/ Windows 2012R2, Nothing mentioned here worked for me.
I don't know what is meant by Removing WebDAV but that didn't solve the issue for me.
What helped me is the below steps;
I went to IIS manager.
In the left panel selected the site.
In the left working area, selected the WebDAV, Opened it double clicking.
In the right most panel, disabled it.
Now everything is working.
I added requireAccess="None" to web.config like this
<configuration>
<location path="." inheritInChildApplications="false">
<system.webServer>
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<remove name="WebDAV" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" requireAccess="None"/>
<add name="WebDAV" path="*" verb="PROPFIND,PROPPATCH,MKCOL,PUT,DELETE,COPY,MOVE,LOCK,UNLOCK" modules="WebDAVModule" resourceType="Unspecified" requireAccess="None" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,DELTE" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" responseBufferLimit="0" />
</handlers>
<aspNetCore processPath=".\Informing.Gateway.Api.exe" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" hostingModel="InProcess" />
</system.webServer>
</location>
</configuration>
And It worked. That's it
For those poor souls, searching for a way to get a simple aspx file handle PUT, PATCH and DELETE requests (yeah, webforms are so last century, but they are still in use). It's not removing WebDav or any of the mentioned fixes before. It's PageHandlerFactory-Integrated-4.0
This is all the magic you need to get a simple aspx file (for example log-request.aspx) accept all the verbs:
<system.webServer>
<handlers>
<remove name="PageHandlerFactory-Integrated-4.0" />
<add name="PageHandlerFactory-Integrated-4.0" path="*.aspx" verb="*" type="System.Web.UI.PageHandlerFactory" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>

Asp.NET Web API - 405 - HTTP verb used to access this page is not allowed - how to set handler mappings

I wrote REST service using ASP.NET Web API.
I'm trying to send HttpDelete request, however I get the following error:
405 - HTTP verb used to access this page is not allowed
I think I'm close to the solution, I found out that I should enable IIS remote management , go to Handler Mappings section and add DELETE verb to the appropriate position...
but the problem is that there is a lots of different positions on the list...
(sth like here: http://www.somacon.com/p126.php).
Which one should I edit?
Few of them don't have extension, e.g. "ExtensionUrlHandler-Integrated-4.0" and I added DELETE verb to it, but it still doesn't work...
It was just a shot in the dark to modify that one, so should I modify different position? If so, which one? Or maybe is there anything more what I should do?
The same web service work perfectly fine on my local service, so I guess the problem is with the remote IIS...
Greetings
You don't need to uninstall WebDAV, just add these lines to the web.config:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
</system.webServer>
Common cause for this error is WebDAV. Make sure you uninstall it.
Change Your Web.Config file as below
<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>
Change Your Web.Config file as below. It will act like charm.
In node <system.webServer> add below portion of code
<modules runAllManagedModulesForAllRequests="true">
<remove name="WebDAVModule"/>
</modules>
After adding, your Web.Config will look like below
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<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="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 had this problem and I solved the following:
open IIS
Select the Backend Site
in features view: open Handler Mapping
in the Handler Mapping window, Find WebDAV
in Edit Module Mapping, open Request Restrictions
Check your web.confiq file"
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
If none of the above solutions solved your issue like in my case (still stuck with my RestClient module facing 405 ) try to request your Api with a tool like Postman or Fiddler. I mean the problem may be elsewhere like a bad formatted request.
I discover that my RestClient module was asking a 'Put' with an Id paremeter not well formatted :
http://myserver/api/someresource?id=75fd954d-d984-4a31-82fc-8132e1644f78
instead of
http://myserver/api/someresource/75fd954d-d984-4a31-82fc-8132e1644f78
Incidiously, bad formatted request returns 405 - Method Not Allowed (IIS 7.5)
Uncommon but may help some.
ensure you're using [HttpPut] from System.Web.Http
We were getting a 'Method not allowed' 405, on a HttpPut decorrated method.
Our problem would seem to be uncommon, as we accidentally used the [HttpPut] attribute from System.Web.Mvc and not System.Web.Http
The reason being, resharper suggested the .Mvc version, where-as usually System.Web.Http is already referenced when you derive directly from ApiController we were using a class that extended ApiController.
I've had this happen (405 method not allowed) when the web api post method I was calling had primitive types for parameters, instead of a complex type that was accessed from the body. Like so:
This worked:
[Route("update"), Authorize, HttpPost]
public int Update([FromBody] updateObject update)
This didn't:
[Route("update"), Authorize, HttpPost]
public int Update(string whatever, int whatever, string whatever)
This error is coming from the staticfile handler -- which by default doesn't filter any verbs, but probably can only deal with HEAD and GET.
And this is because no other handler stepped up to the plate and said they could handle DELETE.
Since you are using the WEBAPI, which because of routing doesn't have files and therefore extensions, the following additions need to be added to your web.config file:
<system.webserver>
<httpProtocol>
<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="C:\windows\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="C:\windows\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" />
Obviously what is needed depends on classicmode vs integratedmode, and classicmode depends on bitness. In addition, the OPTIONS header has been added for CORS processing, but if you don't do CORS you don't need that.
FYI, your web.config is the local to the application (or application directory) version whose top level is applicationHost.config.
If it is IIS 8.0 check if HTTP Activation is enabled.
Server manager -> IIS -> Manage (see right top) -> Add Roles and Features -> ... -> get to WCF configuration and then select HTTP Activation.
None of the above worked for me and i was trouble shooting using a support page(https://support.microsoft.com/en-us/help/942051/error-message-when-a-user-visits-a-website-that-is-hosted-on-a-server)then i compared the application host file with one of the working copy and seems like i was missing a bunch of handlers and when i added back those into application host its start working.
I was missing all these,
<add name="xamlx-ISAPI-4.0_64bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="xamlx-ISAPI-4.0_32bit" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="xamlx-Integrated-4.0" path="*.xamlx" verb="GET,HEAD,POST,DEBUG" type="System.Xaml.Hosting.XamlHttpHandlerFactory, System.Xaml.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="rules-ISAPI-4.0_64bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="rules-ISAPI-4.0_32bit" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="rules-Integrated-4.0" path="*.rules" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="xoml-ISAPI-4.0_64bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="xoml-ISAPI-4.0_32bit" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="xoml-Integrated-4.0" path="*.xoml" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="svc-ISAPI-4.0_64bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" />
<add name="svc-ISAPI-4.0_32bit" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" />
<add name="svc-Integrated-4.0" path="*.svc" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" preCondition="integratedMode,runtimeVersionv4.0" />
<add name="rules-64-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="rules-ISAPI-2.0" path="*.rules" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="rules-Integrated" path="*.rules" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
<add name="xoml-64-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="xoml-ISAPI-2.0" path="*.xoml" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="xoml-Integrated" path="*.xoml" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
<add name="svc-ISAPI-2.0-64" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness64" />
<add name="svc-ISAPI-2.0" path="*.svc" verb="*" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v2.0.50727\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv2.0,bitness32" />
<add name="svc-Integrated" path="*.svc" verb="*" type="System.ServiceModel.Activation.HttpHandler, System.ServiceModel, Version=3.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="integratedMode,runtimeVersionv2.0" />
In our case, the problem was with federated signon between a .Net site and ADFS. When redirecting to the ADFS endpoint the wctx parameter needed all three parameters for the
WSFederationAuthenticationModule.CreateSignInRequest method: rm, id, and ru
Thanks to Guillaume Raymond for the tip to check the URL parameters!
Besides all above solutions, check if you have the "id" or any custom defined parameter in the DELETE method is matching the route config.
public void Delete(int id)
{
//some code here
}
If you hit with repeated 405 errors better reset the method signature to default as above and try.
The route config by default will look for id in the URL. So the parameter name id is important here unless you change the route config under the App_Start folder.
You may change the data type of the id though.
For example the method below should work just fine:
public void Delete(string id)
{
//some code here
}
Note: Also ensure that you pass the data over the url not the data method that will carry the payload as body content.
DELETE http://{url}/{action}/{id}
Example:
DELETE http://localhost/item/1
Hope it helps.
I will add for those that get stuck trying to run PHP (Laravel in may case) or other unique IIS hosting situation with the 405 error, that you need to change the verbs in the handler for that for that specific situation... so since I was using PHP I went to the PHP handler and in the Request Restrictions, then Verbs tab, add the verbs you need. This was all I needed to add to the web.config to enable CORS in Laravel.
<handlers>
<remove name="php-5.6.40" />
<add name="php-5.6.40" path="*.php" verb="GET,HEAD,POST,PUT,DELETE,OPTIONS" modules="FastCgiModule" scriptProcessor="C:\Program Files (x86)\PHP\v5.6\php-cgi.exe" resourceType="Either" requireAccess="Script" />
</handlers>
This may not be applicable to pure "Web API", and probably not for popular public-facing sites, but if you have this error 405 - Method Not Allowed issue on a website with IIS 10, with application built using AspNetCore 2.2, MVC 2 (or 3) and Angular 9, this was my experience. The error msg tells me that I could reach the MVC controller, but that "PUT" was not allowed (or found or listed) as one of my Http verb options on my MVC controller.
I could login with POST (because "Login()" was the name of my MVC controller method decorated with [HttpPost(route)]) and I could use the GET verb successfully. I use Routes for navigation.
But I could not use POST to create a new entry, PUT to edit them or DELETE to remove them. I received the "405" error.
In my case, removing the WebDAV references from web.config only changed the error I was receiving from a "405" to "400 - Bad Request".
But, this info was helpful, too, so I went back to Development mode, changed my MVC Controller methods names to match the HTTP Verb names, like "PUT" now matches to controller method "Put()" - even using [FromBody]. "DELETE" verb now matches to "Delete()" method name and POST matches to "Post()". I did not remove or change any necessary parameters like "id", etc, from the new method name.
I began testing again and received errors in dotnet server compile showing a problem with cross-site antiforgery issues in MVC Controllers paths.
I am also using antiforgery header/cookies in StartUp.cs, and it works in login POST, so I did not change anything in StartUp.cs.
But my MVC controller classes were decorated with the [AutoValidateAntiforgeryToken] attribute (don't fully understand why I used it, just followed my example), and my MVC controller methods were decorated with [HttpPut], etc.
So, because of the dotnet compile error, I removed the class-level attribute [AutoValidateAntiforgeryToken], but left the [HttpPut], etc, attributes in place at method-level for each MVC controller.
This was my solution, edited the web.config to remove WebDAV, made controller method names match http verbs and removed [AutoValidateAntiforgeryToken] attribute from MVC controller classes - since my website is private, not public facing.
I still have the Login header x-xsrf-token / cookies / antiforgery stuff in my StartUp.cs, and it still works on login. Still investigating how to get it to work at the MVC controller class level however.
But, for now, I can POST, PUT and DELETE with no error.
Update - from reading a few other posts about the **400 - Bad Request" issue, I found this link to "ASP.NET Core Web Api Antiforgery". It was very helpful. After doing the updates that the article suggested which included adding an MVC AntiForgeryController and an Angular Injectable service, I am able to PUT, POST and DELETE with CRSF turned on for my Controllers, using "ValidateAntiForgeryToken" on most controllers, but "Ignoring" some methods(), like the article suggests.
Besides the changes in the article, I also had this app registration in my StartUp.cs in the Configure() method - I have no public-facing routes except "login":
app.Use(nextDelegate => context =>
{
string path = context.Request.Path.Value;
string[] directUrls = { "/<first restricted url route>", "/<second restricted url route>", "/<third>" };
if (path.StartsWith("/api") || string.Equals("/", path) ||
directUrls.Any(url => path.StartsWith(url)))
{
var tokens = antiforgery.GetAndStoreTokens(context);
context.Response.Cookies.Append("XSRF-REQUEST-TOKEN", tokens.RequestToken,
new CookieOptions()
{
HttpOnly = false,
Secure = false,
IsEssential = true
});
}
return nextDelegate(context);
});

How to ASP.NET MVC3 Route to accept any type of file (Dot in URL)

ASP.NET MVC 2 Issue - Dot in Route gives an example to allow dot (.) in url and allow .svc file.
My question is, how to allow any kind of file, I tried:
<httpRuntime relaxedUrlToFileSystemMapping="true" />
<remove extension=".*"/>
Not working! What I want is: for any kind of URL (any chars) can processed by MVC3 Route(MapRoute).
That's a very very very bad idea. You want people to be able to download your web.config? see your passwords? download your database? IIS and MVC deliberately block many kinds of extensions because not doing so is highly insecure.
here is the solution:
First: it will NOT cause security leak, if you visit /web.config, you will get
HTTP Error 404.8 - Not Found
The request filtering module is configured to deny a path in the URL that contains a hiddenSegment section.
Unless you change the hiddenSegment of course.
here is the solution, at web.config file:
<system.webServer>
<handlers>
<add name="Static-Favicon" path="favicon.ico" verb="GET" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="Static-Robot" path="robots.txt" verb="GET" modules="StaticFileModule" resourceType="File" requireAccess="Read" />
<add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*" verb="GET,HEAD,POST,DEBUG" 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" 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" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Static-Favicon and Static-Robot can be removed, if you like your MVC handle these two files as well.
Btw, you still need the <remove extension=".svc" /> to handle svc file, and relaxedUrlToFileSystemMapping for special codes in url

Resources