Reject (Hard 404) ASP.NET MVC-style URLs - asp.net-mvc

ASP.NET MVC web app that exposes "friendly" URLs:
http://somesite.com/friendlyurl
...which are rewritten (not redirected) to ASP.NET MVC-style URLs under the hood:
http://somesite.com/Controller/Action
The user never actually sees any ASP.NET MVC style URLS. If he requests one, we hard 404 it. ASP.NET MVC is (in this app) an implementation detail, not a fundamental interface.
My question: how do you examine an arbitrary incoming URL and determine whether or not that URL matches a defined ASP.NET MVC path?
For extra credit: how do you do it from inside an ASP.NET-style IHttpModule, where you're getting invoked upstream from the ASP.NET MVC runtime?
Thanks!

why do you have the "hard" urls in the first place then? just change your routing, it seems kind of odd to rewrite something you have complete control over.
If you can't, you probably want something along these lines
Response.StatusCode = (int)HttpStatusCode.NotFound;
return View("NotFound");

Related

What does 'the URL is local' mean?

I am debugging some code and there is this check (in an ASP.NET MVC controller)
if (Url.IsLocalUrl(returnUrl))
So I check the documentation and it says
Returns a value that indicates whether the URL is local.
But what does that mean, 'the URL is local'?
If I hit a webserver, when does the webserver say 'the URL is local' ?
In the ASP.NET MVC blog Preventing Open Redirection Attacks (C#) you can find an explanation of why you should use it, but, as is tradition with MVC's documentation, it's not explained how it works.
You can read that from the source presented there though: it checks whether an URL starts with / or ~/, meaning: whether it is a relative URL which thereby points to the same domain.

How iis distinguish between mvc request and asp.netpage request

How does IIS distinguish between an asp.net mvc request or a normal asp.net page request and how does it process the two different requests?
Can anyone please help me with this?
The routing (generally configured in the global.asax) configures URLs to be handled by controllers/actions instead of actual aspx pages.
If the url doesn't match a route, it will try and find an actual file instead of an action.

asp.net MVC : when is IIS giving a 404 and when does it forward it to my app?

i was wondering about the following:
i can define in IIS what to do with page not founds / 404, and also in my app i can put it in my CustomErrors section or just handle it in code.
Now as i assume IIS always gets the request first, when does it handle the 404 for itself, and when does it let it pass through to my app?
And a side-question: can IIS actually know if a request in asp.net MVC is a 404 because it might or it might not me mapped via any route?
IIS looks at the request extension. If there is a module registered to handle the type of request that came in, then it will forward the request to that module.
For example, if you request foo.jpg from your server, then IIS has a module built in to handle image/jpg content. If that module can't find the file then it returns a 404.
Same thing here. Whatever your MVC handlers don't look for (ie: images), then IIS will take care of in another manner.
can IIS actually know if a request in asp.net MVC is a 404 because it might
or it might not me mapped via any route?
I think it all depends on how your controller factory handles the unmapped request. The DefaultController factory seems to throw an HttpException with code 404 when it cannot find a route and let IIS handle the error display. You can play with this and see it in action by creating your own controller factory.
For example, add the following line to your Application_Start
ControllerBuilder.Current.SetControllerFactory(new TestControllerFactory());
and add this class to a brand new MVC project:
public class TestControllerFactory : DefaultControllerFactory
{
protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
{
if (controllerType == null)
{
//throw new Exception("Oops!"); // yellow screen of death
throw new System.Web.HttpException(404, "Oops not found!"); // bubbles up to IIS
}
return base.GetControllerInstance(requestContext, controllerType);
}
}
Navigate to your project to http://localhost/MvcApplication1/unmapped and see what happens when you throw an HttpException with code 404 versus when you throw a regular Exception (or even an HttpException with a code other than 404)
Make sure you are running your project under IIS (rather than the VS Dev Server) as the they handle these things different.
Now as i assume IIS always gets the request first, when does it handle the 404 for itself, and when does it let it pass through to my app?
Although the request is initially handled by ISS, it passed through to the MVC application. If a file is not found, an HttpException is thrown which bubbles back to IIS. If a file is found, it is served directly bypassing routing.
However, you can modify the behaviour by adjusting the the RouteExistingFiles property. If I'm not mistaken though you will need to create a route to handle all static content when the property is set to true (default is false). However, as a post here suggests, as per Steve Sanderson, that the routing system will first check if the file exists on disk. (See this related SO question which provides better clarification, especially the comments).
Try it yourself. Use the Application_Error() and Application_EndRequest() events in the Global.asax file and inspect the HttpContext.Current.Response object to to see what the final responses are when content is being served.
And a side-question: can IIS actually know if a request in asp.net MVC is a 404 because it might or it might not me mapped via any route?
This is where route configuration comes into play. Since MVC will check to see if the file exists first, if it does, it gets served directly and routing is bypassed. With regards to Controllers and actions, the same will apply. Eg. /SomeController/ActionThatDoesExist is first checked to verify if it is a physical file. Clearly this is not a file and a 404 exception will be returned from the application.
The third aspect I think that may be related to this question is how MVC and IIS work together. By this I am referring to Integrated Mode and Classic Mode. An awesome explanation can be found here.
IIS always handles the request and then forwards it to the MVC application. This is where it is basically decided how to handle it.
If their is already a physical file on the disk, then the whole Routing is bypassed and the file is served. If it can't find the file then it tries matching the Routing. If nothing works then the MVC application may handle the 404 otherwise it throws the HTTPException and IIS handles the 404.
I believe even in Webforms, the 404 scenario is pretty much the same internally. Only difference being the target is always a physical disk but the request still goes to ASP.NET Webforms, incase you want to handle the 404 yourself.
You will want to keep the execution within your MVC app and like others have said, usually IIS will pass the request into MVC first and only then if MVC passes a 404 exception up high enough will IIS get it back and apply it's decision making process.
The key is: handle 404's in MVC properly!

Account for simple url rewriting in ASP.NET MVC redirect

How would you go about redirecting in ASP.NET MVC to take into account some external URL rewriting rules.
For example:
What the user enters: http://www.example.com/app/route
What ASP.NET MVC sees: /route
What I want to redirect to: http://www.example.com/app/other_route
What actually happens when I do a simple RedirectToAction: http://www.example.com/other_route (which doesn't exist, from the outside anyway)
This seems like it should be simple, but I'm drawing a blank.
Just use
RedirectToAction("NewAction", "Controller-Required-If-Diferent-From-Current-Controller");

Map a domain to an MVC area

Anybody got any experience in mapping a domain to an MVC area?
Here's our situation:
Old system (still active but will soon redirect to new store):
www.example.com - our main site where we send traffic
store.example.com - our store site which is a completely separate site that is indexed in google
New system:
www.example.com - same site as before
www.example.com/store - new store site - built in an ASP.NET MVC area
Because store is a separate domain google gives it a separate entry in the search results. I'd like to keep this benefit in future but wondering whether or not there is a good way to map a domain (store.example.com) to the MVC area or if its just going to be more trouble than its worth.
PS. I'm not trying to keep existing indexing - its a completely separate store so thats not possible. I just want to redirect to the corresponding page in the new store. I'm just trying not to lose the benefit of two domains for SEO purposes.
I would use URL Rewriting, either in ASP.NET or in IIS7 Application and Request Routing (ARR) to change incoming requests for store.example.com/... to example.com/store/....
MVC will have no issue with this - it doesn't get to see anything but the new URL and it will generate links only for the new layout.
Other alternatives:
Create a website for the store.example.com that just does a wildcard 301 redirect for each page to the corresponding page on the new site.
If the URLs don't overlap at all, point the old domain to the new MVC site and add duplicate routes for each action, e.g. shop.example.com/info.aspx?item27 might have a route "/info.aspx/{pathinfo*}" ... which loads an Action that knows how to handle the old URL parameters and can do a Redirect to the new Action.
I have sites where there are many URLs mapped onto the same Action - in fact, every legacy URL that has ever been used for a page still works today, including even the old .ASPX URLs which are now served up by an MVC Action. Some legacy URLs are dealt with using a 301 response, others which legitimately have duplicate content on the site are handled as normal but the page also includes a canonical URL to point out which one is the preferred URL.

Resources