I have the following line in Global.asax.cs:
routes.MapPageRoute( "Resorts", "{resortname}", "~/Pages/ViewResort.aspx" );
The intention is to allow a request like:
www.mysite.com/some-resort-name
to load this resource (more or less)
www.mysite.com/Pages/ViewResort.aspx?resortname=some-resort-name
This behavior works fine. However, I'm noticing that ViewResort.aspx is being loaded every time any resource is requested, presumably because my route doesn't contain a literal path segment, like this alternative would:
routes.MapPageRoute( "Resorts", "Resort/{resortname}", "~/Pages/ViewResort.aspx" );
My client is insistent that the only thing after the hostname in the URL be the resort name, so going with the alternate route is not a possibility.
So my question is: is there something special one needs to do to the RouteUrl when it refers to the site's root directory? Failing that, is there a particular pattern that can be implemented on the target page (ViewResort.aspx in this case) to prevent it from being loaded and discarded with each page request?
Your route is acting as a catch-all. In situations like this, you'll need to provide specific routes before the catch-all route in order to give the proper responses for those specific routes. In other words, the only routes that should get through to your catch-all are routes that must redirect to Pages/ViewResort.aspx.
Related
I have two routes in my application, each in a different Controller, that look like this:
[Route("forgot-password", Order = 1)]
[Route("{variable}", Order = 2)]
When I run the application I get the exception:
Multiple controller types were found that match the URL. This can
happen if attribute routes on multiple controllers match the requested
URL.
Remember these actions are in different Controllers. The Order attribute doesn't seem to work across Controllers!.
How can I get this scenario to work in asp.net mvc routing? I want to use attribute based routing and I don't want to change my urls.
The mechanism behind the error is explained here (I guess you are using Web API). Shortly put, precedence is honored only inside a controller.
Also, it is unclear for me why you want such a generic route like:
[Route("{variable}")]
The problem is that all routes in your application have been stored together. Even if it is located in different controllers, it is the same type, so they can "see" each other. In your case "forgot-password" and "{variable}" have the same format, that's why error about multiple routes has been displayed. As #NightOwl888 said, you may use RouteConfig to create a routes, but in that case you have to change your routing values.
I'm upgrading an old asp.net webforms site. I want to make the URLs look nicer, so I'm using the routing system, like this:
void RegisterRoutes(RouteCollection routes)
{
routes.MapPageRoute("account settings",
"settings/account/",
"~/accountsettings.aspx");
}
This works fine. Urls like mydomain.com/settings/account/ look much nicer. However, the page can still be accessed using its physical location, as mydomain.com/accountsettings.aspx. I'd like to forward requests to these old form urls to my new urls.
What's the best way to do this? Is there a simple method I can use, as with RegisterRoutes?
I believe you'll need to let the routing engine know to ignore the route of the physical file using IgnoreRoute:
routes.IgnoreRoute("accountsettings.aspx");
Please double-check the syntax for IgnoreRoute as I don't remember if you'll need to include the relative path or just the file name.
Once you have that working you can trap the 404 that it will generate, possibly in the global error handler in global.asax, and redirect if that was the requested path. This blog posting has an example of how to trap a 404 in the global error handler: http://www.andornot.com/blog/post/Handling-404-errors-with-ASPNET.aspx
If this is a public site and you're concerned about SEO you may also want to consider specifying that it's a permanent redirect using http status code 301. This will tell Google and other search engines that the old page now exists at the new location and you won't lose the value from that page.
Hope that helps!
We are creating a multi-tennant web application where we identify tenants via a subdomain (customer1.ourapp.com, customer2.ourapp.com, etc).
Setup of subdomains has to be data driven - i.e. we don't want to have to modify IIS config (manually or programmatically) every time we get a new customer.
In MVC where is the best place to check that a subdomain in a request is valid (i.e. the subdomain exists in some table in the database)
Some options I've considered,
OnActionExecuting in the controller
In a custom action filter
IIS module
As part of the routing setup - a custom route class that knows about the valid sub-domains - similar to this approach - http://blog.maartenballiauw.be/post/2009/05/20/ASPNET-MVC-Domain-Routing.aspx
I think that conceptually this is a routing task so the last option seems right ?? i.e. a request with a subdomain that doesn't exist is essentially an invalid url so it shouldn't match against a route and should instead fall through to a 404. This would also allow us to explicitly define routes that do or don't require a valid subdomain.
I would create a custom action filter and registered it globally in Global.asax (no worries when adding new controllers).
You can also consider creating a custom MvcHandler and specify it when declaring routes. This will allow you to specify a few routes (ie. for static content), which can be shared between all clients.
Other solution is to use only routing and stick to the single domain, so you don't have to shell out for the expensive SSL certificate for wildcard domain.
I was doing it like this in my Base Controller Class before, however, like #Jakub said, using subdomain will be expensive if you or your client need SSL certificate thereafter.
var dotIndex = HostingEnvironment.SiteName.IndexOf('.');
if (dotIndex > 0)
{
var subdomain = HostingEnvironment.SiteName.Substring(0, dotIndex);
customerCode = subdomain;
}
I am trying to register the route collection in .net based on each session. The code I have works fine, you goto website/username and it loads the correct sub pages, but you have to restart the application to goto website/username2 to load those sub pages. But when the application is restarted the second one works, but then not the first one.
Is there some way to create a different route collection per session not per application using system.web.routing.
Routes are linked to route names and are stored globally for the web application, so you can't really define routes per session.
Can you give an example of why you need different routes for different users?
Most likely it can be solved by simply using route patterns, like setting RouteUrl to somehting like : "member/logo/{size}/{UserName}.jpg", where you can specify UserName and size when generating the route url via Page.GetRouteUrl()
You can create your own route handler. Take a look at : ASP.Net MVC Framework - Create your own IRouteHandler.
Using such approach, you will be able to route differently per request. Each request can then take a look at your session values to get the correct handler.
RouteTable.Routes is static so the same routes are shared across all Sessions. So you can't have a different set of routes for each session.
Does anyone have experiences in providing a custom MvcRouteHandler? In my application I'd like to implement a globalization-pattern like http://mydomain/en/about or http://mydomain/de/about.
As for persistance, I'd like to have a cookie read as soon as a request arrives and if there is a language setting in this cookie apply it (so a user arriving at http://mydomain/ would be transferred to http://mydomain/en/ for example). If there is no cookie present, I'd like to get the first language the browser supports, apply this one and store it in this cookie.
I guess this can't be done with the standard routing mechanism mvc provides in it's initial project template. In a newsgroup I got the tip to have a look at the MvcRouteHandler and implement my own. But its hard to find a sample on how to do that.
Any ideas?
I don't believe a custom route handler is required for what you are doing.
For your "globalized" URIs, a regular MVC route, with a constraint that the "locale" parameter must be equal to "en", "de", etc., will do. The constraint will prevent non-globalized URIs from matching the route.
For a "non-globalized" URI, make a "catch-all" route which simply redirects to the default or cookie-set locale URI.
Place the "globalized" route above the "catch-all" route in Global.asax, so that "already-globalized" URIs don't fall through to the redirection.
You would need to make a new route handler if you want a certain URI pattern to trigger something that is not an action on a controller. But I don't think that's what you're dealing with, here.
You should be able to do this with ASP.NET MVC's default template, I'm doing something similar. Just build your routes as {language}/{controller}/{action}/{id}
Just set a default route that goes to a controller that checks for the language cookie, and redirects the user based on that cookie.