I'm new to MVC. I'm having trouble trying to accomplish having a route setup in the following manner:
System/{systemName}/{action}
Where systemName is dynamic and does not have a "static" method that it calls. i.e.
http://sitename.com/Systems/LivingRoom/View
I want the above URL to call a method such as,
public void RouteSystem(string systemName, string action)
{
// perform redirection here.
}
Anyone know how to accomplish this?
routes.MapRoute(
"Systems_Default",
"System/{systemName}/{action}",
new { controller="System", action = "RouteSystem", systemName="" }
);
Should route your request as you specified.
Note that with the above route, your Url should be:
http://sitename.com/System/LivingRoom/View
I had a similar problem. I used the following route.
routes.MapRoute(
"BlogSpecific", // Route name
"{blogSubFolder}/{controller}/{action}/{id}", // URL with parameters
new { blogSubFolder = "", controller = "", action = "", id = "" } // Parameter defaults
);
blogSubFolder just gets passed to my controller actions as a parameter. Controller and action all work just as they usually do. Just swap out blogSubfolder with your "System" paramter and that will hopefully work for you.
It looks like you intend to route to a controller based on the system name. If that is correct then you would simply need this:
routes.MapRoute("Systems",
"Systems/{controller}/{action}"
new{controller = "YourDEFAULTController", action = "YourDEFAULTAction"});
Please note that the third line only sets the default values specified if they are NOT included in the url.
Given the route above, MVC would route this:
http://sitename.com/Systems/LivingRoom/View
to the View action method on the LivingRoom controller. However this:
http://sitename.com/Systems/LivingRoom
would route to the YourDEFAULTAction method on the LivingRoom controller.
Related
I am making a documentation for the OSS I am about to publish. The url is going to be like /Documentation/{class name} . All the documentation view are named as {namespace}_{classname}. Basically i wonder if there is a way to direct all requests to /Documentation/* to a method inside my Documentation controller so that i can do something like
return View({class name});
instead of having to make a method for each class
You can handle that in routing.
routes.MapRoute(
"Docs", // Route name
"Documentation/{className}", // URL with parameters
new { controller = "Documentation", action = "Show", className = "" } // Parameter defaults
);
That assumes of course that you have a DocumentationController with a Show attribute.
So, I've been trying for a few hours now to workaround something that should theoretically be very simple. Let's take this sample url:
http://sample.com/products/in/texas/dallas
This maps onto a specific route:
routes.MapRoute(
"products",
"products/in/{state}/{city}",
new { controller = "Products", action = "List", state = UrlParameter.Optional, city = UrlParameter.Optional });
In my action method, I can do lookups to make sure "texas" and "dallas" exist, and that "dallas" exists within Texas. That's all fine and dandy. However, in the situation where the city doesnt exist (either because the geo is incorrect, or mispelled), I want it to back up the state level. Example:
http://sample.com/products/in/texas/dallax
That should issue a redirect to
http://sample.com/products/in/texas
The "easy" way to do this was to simply issue a Redirect call like so:
return Redirect("/products/in/" + stateName);
However, I'm trying to decouple this from the URL structure; for example, if we ever decided to change how the route looks (say, change the pattern to products/around/{state}/{city}), then I would have to know that I need to make updates to this controller to fix the URL redirect.
If I can make a solution that just inspects the route values and can figure things out, then I don't have to worry if I change the route pattern, because the route values could still be figured out.
Ideally, I would have liked to do something like this:
return RedirectToRoute(new { controller = "Products", action = "List", state = state });
(Note, that is is a simplified example; the "required" route pieces like controller name and action method name would be determined by Generic argument and Expression inspection respectively).
That actually performs the redirect, HOWEVER, the route values from the current request get appended onto the redirect and thus you get in a redirect loop (note that I didn't include the city route value in the route object). How do I stop the "city" route value from being included in this redirect?
I've tried the following things to get rid of the route value:
Compose my own RouteValueDictionary / anonymous route data object and pass that to the overload of RedirectToRoute.
Create my own action result to inspect RouteTable.Routes and find the route myself, and do the replacement of the tokens myself. This seems the most "kludgy", and would seem to be re-inventing the wheel.
Make a method like RedirectWithout that takes a key value and calls RedirectToRouteResult.RouteValues.Remove(key) - which also didnt work.
I've also attempted to add a null value for the key I don't want to add; however, this alters the route to something that isnt correct - ie new { controller = "Products", action = "List", state = stateName, city = (string)null } issues a redirect to /Products/List?state=Texas which is not the right URL.
It all seems to stem from the RedirectToRoute taking the current request context to construct the virtual path data. Is there a workaround?
If you were using T4MVC, you should be able to do something like this:
return RedirectToAction(MVC.Products.List(state, null));
Have you tried this?
return RedirectToRoute(new
{
controller = "Products",
action = "List",
state = state,
city = null,
});
Reply to comments
Maybe MVC is confused because your optional parameter is not at the end. The below should work with the above RedirectToRoute that specifies city = null:
routes.MapRoute(
"products",
"products/in/{state}/{city}",
new
{
controller = "Products",
action = "List",
// state = UrlParameter.Optional, // only let the last parameter be optional
city = UrlParameter.Optional
});
You can then add another route to handle URL's where state is optional:
routes.MapRoute(null, // I never name my routes
"products/in/{state}",
new
{
controller = "Products",
action = "List",
state = UrlParameter.Optional
});
I'd like to have one route that gives the option of two urls but maps to one action. A good example would be for multilingual application. Lets take english and french for example.
This seems simple at first, technically you can do:
routes.MapRoute(
"the hi route english" ,
"welcome/sayhi/{id}" ,
new { controller = "Welcome" , action = "SayHi" , id = UrlParameter.Optional }
);
routes.MapRoute(
"the hi route french" ,
"bienvenu/direallo/{id}" ,
new { controller = "Welcome" , action = "SayHi" , id = UrlParameter.Optional }
);
But that means that you'll have to define two routes for every action. Or a little better solution, create a custom Route class that takes more params to handle bilingualism.
If I go option 1 or 2, It means I have to define every single routes of the WelcomeController because I cannot use {action} in my route.
Ideally, i'd like to be able to define at least action name via metadata and then grab it via reflection or something.
i.e.:
[ActionName( { "fr", "direallo" }, {"en", "sayhi"})]
public ActionResult SayHi(string id){
//check current thread culture...
}
I am not quite sure where to starts, any ideas? Tips?
Thank you,
You have several options starting points here, roughly they are (in order of implementation complexity):
A route per language (as you outlined above)
A regex route constraint e.g.
routes.MapRoute(
"the hi route",
"{controllerName}/{actionName}/{id}",
new { controller = "Welcome" , action = "SayHi" , id = UrlParameter.Optional },
new { controllerName = #"welcome|bienvenu", actionName = #"sayhi|direallo" }
);
You could create a base controller, which is inherited by a subclass per language and define a language specific action name for each base controller action method
You could create your own (or use the one provided in the answer to the comment by Justin Pihony) custom routing constraint
I thought I had at least a bases for understanding routing in MVC after all the documentation I have read, only to fail at it when attempting to utilize it.
I have the following two routes declared in my Global.aspx
routes.MapRoute(
"", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Admin", action = "List", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
I have a AdminController that I have a few methods, one that is "List" method that renders a list of products to a "List" view.
I thought I understood how RedirectToAction works, and I added an "Add" method (see below) that adds a new Product and returns a RedirectToAction which I understood would be the proper way to redirect to the List action on the same "AdminController"
[HttpPost]
public ActionResult Add(Product product) {
if (_prodRepo.Add(product)) {
return RedirectToAction("List", "Admin");
}
return View("Add", product);
}
However, on the return of the "Add" it always attempts to route to the path website.com/Account/Login/ReturnUrl=%2f.
However, if I go to website.com/Admin it does render the list as I expect. But when using the RedirectToAction as in the example above, it attempts to go to the /Account/Login (Controller/action).
It was my understanding that the RedirectToAction("List", "Admin") would route to the "List" method on the AdminController controller and that I was using it as expected.
Can someone please help me understand the reasoning behind this. But also, could someone post some recommended articles for understanding the whole MVC routing including how the web.config works with routing.
Finally, it was also my understanding that route discovery by the framework is done in the order they are specified in your routes.MapRoute() declaration and stops at the first one that matches. Therefore, if the first one is listed as Controller = "Admin", Action = "List", I would expect by convention that this is the correct route it would first match and return.
Your routes need to be different (the url parameter) since the first route with a matching url will be used.
This will therefore work for you:
routes.MapRoute("Admin",
"admin/{action}/{id}",
new { controller = "Admin", action = "List", id = UrlParameter.Optional });
The defaults (third parameter in the method) are used if the parameters isn't found/specified in the uri.
As for your question regarding /Account/Login/ReturnUrl=%2f. The login redirections are handled by the MembershipProvider and not by the standard routing mechanism.
I have set up two custom extensions to enable MVC in IIS6.
So the site can be accessed with a URL of either something like...
mysite/mycontroller.europe/myaction
or like...
mysite/mycontroller.america/myaction
What is the most robust way of finding the extension from the RequestContext instance?
So I would like to be able to write something like...
var location = reqContext.......GetExtenstion(); // location = "europe"
and obviously have that work even if the setup of the site/directories changes a little.
Define a route:
routes.MapRoute(
"DefaultWithExtension",
"{controller}.{extension}/{action}",
new { controller = "Home", action = "Index", extension = "america" }
);
and then:
var extension = RequestContext.RouteData.GetRequiredString("extension");
Also you can just define extension as a string parameter for all relevant actions for the controllers, in which case it will be directly available.
e.g.
public ActionResult myaction(string extension)
This does still need the mapRoute entry defined above.