ASP MVC Route issue with dot "." - asp.net-mvc

I have this route:
file{FileId}/{name}
It works perfectly unless name has a dot in it.
For example, these work:
file1/blah, file90/foo -
but it doesn't:
file1/blah.doc
All I get in this case is 404 error. Seems like it looks for the actual file blah.doc instead of use routing system.
This problem happens only in production server. I've even tried
httpRuntime relaxedUrlToFileSystemMapping="true"
but it didn't help.

Everything after the '.' is the file extension. If that extension isn't mapped to ASP.NET, it won't get handed off to the ASP.NET handler. IIS looks for a static file instead. So you need to add a handler for your case (web.config), then your route will be able to catch the request.
<validation validateIntegratedModeConfiguration="false" />
<handlers>
<add name="FileHandlerDot" verb="GET" path="file*/*.*" type="System.Web.Mvc.MvcHttpHandler, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
</handlers>
</validation>

Related

Purpose of UrlRouting.axd

What is the purpose of "UrlRouting.axd" in web.config?
To get ASP.NET routing to work in IIS integrated mode everybody suggests adding the following line, with absolutely zero explanation as to why it should make routing work:
<add name="UrlRoutingHandler" preCondition="integratedMode" verb="*" path="UrlRouting.axd" type="System.Web.HttpForbiddenHandler, System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
At first blush this line makes no sense because it just maps "UrlRouting.axd" (that is never invoked from the client) to the forbidden handler (which will always return an error). I don't really like mindlessly copy-pasting things I have no understanding of, so an explanation of how it works will help me. :)

Extension-less IIS wildcard mapping

I want to configure a wildcard mapping for a specific path, and send the requests to a HttpHandler. My URLs look like this:
http://www.example.com/api/v1/conversation/forums/232?some=value
http://www.example.com/api/v1/conversation/posts/212
This configuration doesnt match the URLs above.
<location path="api/v1/conversation">
<system.webServer>
<handlers>
<add name="ApiProxy" verb="*" path="*" preCondition="integratedMode" type="DemoProject.ApiProxy, DemoProject" />
</handlers>
</system.webServer>
</location>
It works when I add an extension to my URLs:
http://www.example.com/api/v1/conversation/forums/232.axd?some=value
http://www.example.com/api/v1/conversation/posts/212.axd
How do I make this work extension-less?
It turned out, that this problem was related to my website was running Umbraco CMS. Umbraco CMS has an AppSetting called "umbracoReservedPaths", which asks Umbraco to ignore specific paths.
The value was set to:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/" />
After adding ~/api/, everything worked as expected:
<add key="umbracoReservedPaths" value="~/umbraco,~/install/,~/api/" />

URL Pattern Routing MVC 3

I want to know how to have something like this in the url in asp.net MVC
/Article/12.20.2013
I tried below and its working fine for /Article/12-20-2013 but not for /Article/12.20.2013. I have below in the Global.asax
routes.MapPageRoute("Blog",
"/Article/{entryDate}",
new {controller = "Article", action = "Entry")};
I also tried something like below
routes.MapPageRoute("Blog",
"/Article/{month}.{Date}.{year}",
new {controller = "Article", action = "Entry")};
but no luck..
Please guide me with some sample.
I believe the issue is that IIS might be treating ".2013" as a file extension and trying to find a handler for it. What we need to do is to have MVC process all requests.
If you are on IIS 6 this you will need to do a wildcard mapping to aspnet_isapi.dll. If you are on IIS 7 you can set the runAllManagedModulesForAllRequests="true":
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
</modules>
</system.webServer>
You need to change web.config to force every url starting with Article to be treated as a MVC url
<system.webServer>
<handlers>
<add name="UrlRoutingHandler"
type="System.Web.Routing.UrlRoutingHandler,
System.Web, Version=4.0.0.0,
Culture=neutral,
PublicKeyToken=b03f5f7f11d50a3a"
path="/Article/*"
verb="GET"/>
</handlers>
</system.webServer>
Then your routing should be working fine.

Why would FederatedAuthentication.WSFederationAuthenticationModule be null in MVC Azure ACS Federated Authentication?

I'm trying to put together FederatedAuthentication with .NET 4.5, MVC 4, and active redirect using a custom server-side login page, using code from this tutorial, and from this code sample.
Redirecting to the LogOn method of my AccountController works fine, and the method looks like this:
public ActionResult LogOn()
{
HrdClient hrdClient = new HrdClient();
WSFederationAuthenticationModule fam = FederatedAuthentication.WSFederationAuthenticationModule; /*** Fails here because this is null **/
HrdRequest request = new HrdRequest(fam.Issuer, fam.Realm, context: Request.QueryString["ReturnUrl"]);
IEnumerable<HrdIdentityProvider> hrdIdentityProviders = hrdClient.GetHrdResponse(request);
ViewData["Providers"] = hrdIdentityProviders;
return View();
}
This fails because FederatedAuthentication.WSFederationAuthenticationModule is null.
Using VS 2012, I've run the new Identity and Access wizard (which seems to replace the old STS dialog). This has given me a folder of FederationMetadata, which appears correct, and several modifications to my Web.Config. In particular, the modules section looks like this:
<system.webServer>
<validation validateIntegratedModeConfiguration="false" />
<modules runAllManagedModulesForAllRequests="true">
<add name="WSFederationAuthenticationModule" type="System.IdentityModel.Services.WSFederationAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
<add name="SessionAuthenticationModule" type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" preCondition="managedHandler" />
</modules>
And having seen SO answers 8937123 and 8926099, I've added the following as well:
<httpModules>
<add name="WSFederationAuthenticationModule" type="Microsoft.IdentityModel.Web.WSFederationAuthenticationModule, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" />
</httpModules>
And finally my nuget packages config shows Microsoft.IdentityModel, which is correctly referenced by the MVC app:
<packages>
<package id="Microsoft.IdentityModel" version="6.1.7600.16394" targetFramework="net45" />
</packages>
I've also seen this question on social.msdn, which just seems to suggest that the STS dialog does need to be run.
Can anybody explain why FederatedAuthentication.WSFederationAuthenticationModule would be null, and what I can do to stop this happening?
I managed to fix this myself, and since there are a few unanswered questions similar to this on SO, I'll leave the question up and post my own answer.
The issue is to do with upgrading the MVC application to .NET 4.5. Much of the WIF functionality remains the same (at least on the surface), but the classes have all moved to different assemblies. I fixed my problem following the migration guidelines here: http://msdn.microsoft.com/en-us/library/jj157089.aspx
The most important thing is to remove old references to the Microsoft.IdentityModel package (v 3.5.0) and make sure they are replaced by similar references to the System.IdentityModel and System.IdentityModel.Services dlls, which should be version 4.0, and come from the GAC rather than an external package.
My steps to fix were:
Clean out all the junk I'd added to Web.Config and start again with a default MVC Config file.
Remove the Microsoft.IdentityModel package and de-reference the dll
Run the Access and Identity wizard in VS 2012
Duplicate the System.IdentityModel.Services.WSFederationAuthenticationModule reference from <system.webServer><modules> in <system.web><httpModules>
Add <authentication mode="Forms"><forms loginUrl="~/Account/LogOn" /></authentication>
Compile, test, dance little jig of delight...
And this got the original WIF3.5 / MVC3 Code Sample working under.NET 4.5

Why does MvcHttpHandler is mapped from *.mvc?

By default the web.config file for MVC project have the following element:
<handlers>
<remove name="MvcHttpHandler"/>
<add name="MvcHttpHandler" preCondition="integratedMode"
verb="*" path="*.mvc" type="System.Web.Mvc.MvcHttpHandler"/>
</handlers>
My problem is that my site returns 404.14, after knocking out all the usual suspects I changed the path (form the snippet above) attribute in the web.config to be "*" and voilĂ ! MVC handler kicks in.
So my question is how does *.mvc even suppose to work? I mean my urls are http://mysite.com/home/index (or even only http://mysite.com/) there is no *.mvc in them.
Am I missing something?
By changing the path you are telling the routing engine to add the .mvc extension to the Url. You probably do not have the .mvc extension mapped in IIS and receive an error.
See here on information about IIS and MVC especially if you are using IIS 6.0:
http://haacked.com/archive/2008/11/26/asp.net-mvc-on-iis-6-walkthrough.aspx

Resources