ASP.NET MVC4 routing ignored for static files - asp.net-mvc-4

I have an ASP.NET MVC3 application .NET4 in which a routing exists for content files, which are served from a resource inside a class library.
Routing is configured as follows
routes.MapRoute("Resources", "Default{Content}/{*contentpath}", new {controller = "Resource", action="GetResource"});
So if there is a request DefaultMvcScripts/test.js, the GetResource method will be called.
However, when converted to MVC4 ,.NET4.5 this doesn't work anymore, GetResource is not called anymore, it bypasses routing even if I put
routes.RouteExistingFiles = true;
For a request DefaultMvcScript/test (without extension), routing is not ignored (I can see GetResource being called).
Can I have the old behaviour back, so that even if I specify an extension, routing is honoured.

I think you're just missing the last step - you need to configure your app so that the handler pipeline pays attention to requests for static files.
In they system.webserver section of the web config you need to add a handler for the static files you want to serve. You need to use the TransferRequestHandler
<add name="staticHandler" path="*.js" verb="GET" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersion4.0"/>
See Jon Galloway's article for a complete description
http://weblogs.asp.net/jongalloway/asp-net-mvc-routing-intercepting-file-requests-like-index-html-and-what-it-teaches-about-how-routing-works

Apparently, adding this to the web.config restores previous behaviour:
<modules>
<remove name="UrlRoutingModule-4.0" />
<add name="UrlRoutingModule-4.0" type="System.Web.Routing.UrlRoutingModule" preCondition="" />
</modules>
The preCondition="" seems to be the trick.
Source: http://www.britishdeveloper.co.uk/2010/06/dont-use-modules-runallmanagedmodulesfo.html

Related

.Net core request filtering and file downloads

We have an .net core Web application which simply hosts files for some of our client applications updates.
We decided to add Application insights in one of these client applications, and the file ApplicationInsights.config is a part of update.
The request to https://server/path/to/update/ApplicationInsights.config throws 404 error.
So far I’ve tried :
Add “.config” extension in static files definition on the startup : no effect (This worked for .exe and .dll)
Enable folder browsing for this folder, still no effect
It seems to be related to some out-of-box requests filtering.
The question is :
How do I disable all download restriction on a specific folder (Best)
OR
How do I disable ALL filtering for *.config files
Thank you in advance
That's because the default FileExtensionContentTypeProvider doesn't provide a mapping for *.config files.
To make it serve *.config files, simply create your own ContentTypeProvider, or add mapping for *.config :
var myContentTypeProvider= new FileExtensionContentTypeProvider();
myContentTypeProvider.Mappings.Add(".config","text/plain");
app.UseStaticFiles(new StaticFileOptions{
RequestPath = "/path/to/update",
FileProvider = new PhysicalFileProvider(
Path.Combine(Directory.GetCurrentDirectory(),"path/to/update"),
ExclusionFilters.None
),
ContentTypeProvider = myContentTypeProvider,
});
[Update]
After a discussion, the following Web.Config ( by OP) works:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.webServer>
<security>
<requestFiltering>
<fileExtensions>
<remove fileExtension=".config" />
<add fileExtension=".config" allowed="true" />
</fileExtensions>
</requestFiltering>
</security>
</system.webServer>
</configuration>

WebAPI AttributeRouting with version number as parameter

I am trying to set up a route to my MVC controller action with the following template:
[Route("app/{appId:length(20)}/validate/{version}")]
The idea is that the resulting URL would then look something like this:
(I'm adding a space to make the localhost url try not resolve...)
http:/ /localhost:2642/api/update/v1/app/6A6EE0B355C34DBFB381/validate/1.0.0.0
The problem I have is that this would give me a 404 error.
If I remove the Route attribute and use the built-in MVC routing, it works. The url then is:
http:/ /localhost:2642/api/external/CheckForUpdate?appId=6A6EE0B355C34DBFB381&version=1.0.0.0
This should work since I know Nuget has got versions in their URL's, but I think they use the built-in MVC router.
I also tried to add the :regex() markup in the template for the route so validate the string format, but that didn't work. If I pass in a normal string or a value such as 1_0_0_0 it works. Thing is I don't want to go through the effort to manipulate the version string before sending it to the api and then in the api itself.
Any ideas on what I am doing wrong?
If you make your routing attribute
[Route("app/{appId:length(20)}/validate/{version:regex(^([1-9]\\d+|[0-7])(\\.\\d{1,3}){0,3}$)}")]
and make sure you accept the parameters in the method
public Task<IHttpActionResult> Get(string appId, string version)
{
//magic
}
then in the web.config, system.webServer > handlers section change the *. to *
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
to
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*" verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
and also make sure
<modules runAllManagedModulesForAllRequests="true">
exists in <system.webServer>

imageresizer 4.0.5 combined with servicestack blocking images

When requesting images on path site/image.jpg or site/image.jpg?process=no i only get a 404 while site/image.jpg?maxwidht=2000 works just fine.
removing the servicestack handler from web.config resolves the issue:
<system.webServer>
<handlers>
<add path="*" name="ServiceStack.Factory" type="ServiceStack.HttpHandlerFactory, ServiceStack" verb="*" preCondition="integratedMode" resourceType="Unspecified" allowPathInfo="true" />
</handlers>
How can I make servicestack and imageresizer run together on IIS8?
That configuration causes all requests to be given to ServiceStack, preventing middleware from working. It's a terrible practice if one values interoperability, and I'm suprised to see it.
Because if its location at the top of the queue, it is preventing the StaticFileModule & StaticFileHandler from handling static requests, yet failing to serve them itself.
You may want to install ImageResizer in a subfolder/sub application to avoid a conflict. Example w/ service stack.
ImageResizer has a way to 'fixup' frameworks which don't handle VPPs correctly. In this case, static files aren't getting handled correctly, so the detection doesn't work. You can set <pipeline vppUsage="Always" /> to force this code path.

AttributeRouting: Why is my POST, but not my PUT routed? [duplicate]

I have written a site that uses ASP.NET MVC Web API and everything is working nicely until I put it on the staging server. The site works fine on my local machine and on the dev web server. Both dev and staging servers are Windows Server 2008 R2.
The problem is this: basically the site works, but there are some API calls that use the HTTP PUT method. These fail on staging returning a 404, but work fine elsewhere.
The first problem that I came across and fixed was in Request Filtering. But still getting the 404.
I have turned on tracing in IIS and get the following problem.
168. -MODULE_SET_RESPONSE_ERROR_STATUS
ModuleName IIS Web Core
Notification 16
HttpStatus 404
HttpReason Not Found
HttpSubStatus 0
ErrorCode 2147942402
ConfigExceptionInfo
Notification MAP_REQUEST_HANDLER
ErrorCode The system cannot find the file specified. (0x80070002)
The configs are the same on dev and staging, matter of fact the whole site is a direct copy.
Why would the GETs and POSTs work, but not the PUTs?
For those of you who do not have WebDAV enabled but are still running into this issue using MVC 4's Web API's...
Steve Michelotti documented a solution that worked for me here.
At the end of the day, I enabled all verbs (verb="*") to the ExtensionlessUrlHandler-Integrated-4.0 handler in my web config.
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true" />
<handlers>
<remove name="ExtensionlessUrlHandler-Integrated-4.0" />
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Those IIS servers have web-dav module installed on them and i bet it is not needed and it was installed because the person installing ticked all boxes.
Just remove web-dav from iis.
Alternatively use web.config to remove web dav module:
<system.webServer>
<modules>
<remove name="WebDAVModule" />
</modules>
...
It seems there are a number of reasons that this occurs. None of the above quite worked for me. I already had the ExtensionlessUrlHandler settings in web.config with all the required HTTP verbs. In the end I had to make the following changes in IIS:
In IIS select your website and double-click Handler Mappings
Find ExtensionlessUrlHandler-ISAPI-4.0_32bit and double-click
In the dialog that appears, click Request Restrictions
On the Verbs tab add the missing HTTP verbs separated by commas (in my case it was PUT and DELETE
Click Ok where required and answer Yes in the Edit Script Map dialog that pops up.
Repeat for ExtensionlessUrlHandler-ISAPI-4.0_64bit
Hope this helps somebody :)
My hosting provider could NOT uninstall WebDAV as this would affect everyone.
This, runAllManagedModulesForAllRequests="true" , worked but was not recommended.
Many fixes included removing the module for WebDAVModule but that still didn't work. I removed the handler also, and finally I could use all verbs POST GET PUT DELETE.
Remove WebDAVModule and WebDAV in modules and handlers.
<modules>
<remove name="WebDAVModule" />
</modules>
<handlers>
<remove name="WebDAV" />
</handlers>
I fixed this removing the UrlScan ISAPI filter
In my case, none of these solutions applied.
I fixed it by changing my app pool to Integrated instead of Classic.
The handler:
<add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" />
is not going to work with a Classic app pool, since its preCondition is integratedMode.
Rick Strahl from West-Wind recommended the following:
< handlers>
< 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>
Which Worked very well for me.
Hi For me none of the solutions worked. I finally got it working doing this :
1) In IIS select you application.
2) Go to Request Filtering
3) Then select the HTTP Verbs tab
4) I found the PUT and other verbs to have allowed to false but wasn't able to just edit so I removed the verb then either in the pane on the right select allow verb or right click on the list and select it. Enter the verb you're having troubles with and voilà !
Hope this will help someone !
I resolved this by changing my application pool for the website to Integrated mode when it was previously on Classic mode.

404 when running .net 4 WCF service on IIS (no svc file)

I'm testing out a REST service in WCF on .net 4 - i.e. no svc file. It works great when running against the VS dev server but when I switch it to run against IIS I get 404s when trying to browse the help page or hit any of the service methods.
I've dropped back to a bare bones service to just get it running on IIS but I'm not sure what's wrong with it.
The global.asax simply has
protected void Application_Start(object sender, EventArgs e)
{
RouteTable.Routes.Add(new ServiceRoute("", new WebServiceHostFactory(), typeof(DataPortalService)));
}
and the service itself is as simple as it gets:
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class DataPortalService : IDataPortalService
{
[WebGet(UriTemplate = "Test/TestMethod")]
public string TestMethod()
{
return "Hi!";
}
}
[ServiceContract]
public interface IDataPortalService
{
[OperationContract]
string TestMethod();
}
and config file of
<configuration>
<system.web>
<compilation debug="true" targetFramework="4.0" />
</system.web>
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
<standardEndpoints>
<webHttpEndpoint>
<standardEndpoint name="" helpEnabled="true" automaticFormatSelectionEnabled="true" />
</webHttpEndpoint>
</standardEndpoints>
</system.serviceModel>
</configuration>
Hitting the /help page or the method gives me a 404.0.
I presume I'm just missing some setting in IIS to kick it in to life although it's a bit daft that it works fine on the dev server but not IIS.
Solved it after a dig around some other forums.
I initially added the following to my web config:
<system.webServer>
<handlers>
<remove name="svc-Integrated-4.0" />
<add name="svc-Integrated-4.0" path="*" verb="*" type="System.ServiceModel.Activation.ServiceHttpHandlerFactory, System.ServiceModel.Activation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" resourceType="Unspecified" requireAccess="Script" preCondition="integratedMode,runtimeVersionv4.0" />
</handlers>
</system.webServer>
Clearly by default IIS doesn't know what to do with the extensionless requests and passed them on to the static file handler.
Given that MVC is using the same routine architecture I figured that the basic MVC site template must have some config in similar to the above since my MVC sites have worked fine when moved to IIS.
It turns out that they have a slightly different config and have the following entry instead:
<system.webServer>
<validation validateIntegratedModeConfiguration="false"/>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
Both configs seem to work ok but I settled on using the 2nd option in this case.
I had runAllManagedModulesForAllRequests="true" in my web.config but still couldn't get past the 404.0. Also tried installing "IIS 7 Recommended Configuration" without any luck. Rerunning aspnet_regiis solved the problem to me.
In the Run dialog box, type cmd, and then click OK.
At the command prompt, use the cd command to change the directory of the Aspnet_regiis.exe version you want to use. By default, Aspnet_regiis.exe is located in the following directory: systemroot\Microsoft.NET\Framework\versionNumber
Then run the following command: aspnet_regiis -ir
This will register "svc-Integrated-4.0" in the Handler Mappings.
HTTP 404 code can be returned also if you don't have some components of .NET framework installed.
There's for instance Windows Communication Foundation HTTP Activation feature in .NET Framework 3.5 and in .NET Framework 4.6 there are HTTP Activation, Message Queuing (MSMQ) Activation and a few more.
In Windows 10 these features aren't installed by default, so please keep in mind to take a look at Windows Features.
On IIS 5.1 on my machine, the .svc page was served only when I added HTTP Handler at Web Site level as well as virtual folder level. This should ideally work by inheritance!
Extention : .svc
Executable :
c:\WINDOWS\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll