If action name found then call action, if not call a default action in MVC Routing - asp.net-mvc

this is my current routing
routes.MapRoute(
"Default", // Route name
"{action}/{id}", // URL with parameters
new { controller = "MarketingSite", action = "index", id = "" } // Parameter defaults
);
so whenever I visit domain.com/test
This would invoke the test action in the controller called MarketingSite.
What I want to achieve is when I visit domain.com/load-from-db and since I don't have an action called load-from-db, I want to direct the request to a specific action and load-from-db becomes the parameter for that action. In that action, i'm going to read something from the database based on the parameter and then return a view. If I specify an action that exist, then it would just call that action.
Any help?

First note - the routing engine will apply the routes in the order you list them, checking each, and continuing if it cannot match. You currently have the "default" route setup as a catch-all - if is doesn't find a controller it uses "MarketingSite", if there is no action it uses "index". If I am understanding your problem, you don't want an "Index" action at all, you want to call another action, and pass the query to that.
You could try:
//Look for a matching action
routes.MapRoute(
"MatchAction", // Route name
"{action}/{id}",
new { controller = "MarketingSite", id = UrlParameter.Optional}
);
//With a single segment, pass that to a specific action as a parameter.
routes.MapRoute(
"load-from-db", // Route name
"{load-from-db}", // URL with parameters
new { controller = "MarketingSite", action = "MyAction"}
);
//With no segments (ex. domain.com/) use the Index on MarketingSite as default.
routes.MapRoute(
"Default", // Route name
"", // URL with parameters
new { controller = "MarketingSite", action = "Index"}
);
However, these routes might not accomplish exactly what you are looking for - getting your routes mapped in MVC can be a bit tricky. You should check this this out, and design your routes accordingly.
Hope that helps,
Chris

Override the HandleUnknownAction method on the MarketingSite controller:
protected override void HandleUnknownAction(string actionName) {
// TODO: check for actionName in database
}

Related

Added a route and the behaviour changed

I would like to optimize the appearance of the URL like below:
http://localhost:3817/Affaire/SearchAffaires?OnlyFavorite=True
So I added a new route:
routes.MapRoute(
"Search Affaire Only Favorite", // Route name
"{controller}/{action}/OnlyFavorite", // URL with parameters
new { controller = "Affaire", action = "SearchAffaires", OnlyFavorite = true } // Parameter defaults
);
Now the URL is easier to read:
http://localhost:3817/Affaire/SearchAffaires/OnlyFavorite
But a new problem is occured: the other links on my page have changed because of the routing!
Example here: .../Affaire/SearchAffaires?LabelName=Baxter&OnlyLabel=True&OnlyFavorite=True
Before it was: .../Affaire/SearchAffaires?LabelName=Baxter&OnlyLabel=True
As you can see, the variable OnlyFavorite has been added to the URL. Finally I found the reason of this behaviour: the routing system is keen to make a match against a route, to the extent that it will reuse segment variable values from the incoming URL. The best way to deal with this behavior is to prevent it from happening. It is strongly recommend that you
do not rely on this behaviour, and that you supply values for all of the segment variables in a URL pattern.
That's a little bit annoying because I have a lot of variables!
Any solution on that problem? Why is that behaviour not happening whith one single route (the default one)?
Thanks
It looks like if I've registering routes like this, i get away from problem:
routes.MapRoute(
"Search Affaire", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Affaire", action = "SearchAffaires" } // Parameter defaults
);
routes.MapRoute(
"Search Affaire Only Favorite", // Route name
"{controller}/{action}/OnlyFavorite", // URL with parameters
new { controller = "Affaire", action = "SearchAffaires", OnlyFavorite = true } // Parameter defaults
);

In ASP.Net MVC routing, how can you route 2 different paths that look the same, but have different types?

In ASP.Net MVC, I want 2 different routes:
http://mysite.com/foo/12345
and
http://mysite.com/foo/bar
In the class Foo, I have 2 methods that return ActionResult
public ActionResult DetailsById(int id)
{
. . . some code
}
and
public ActionResult DetailsByName(string name)
{
. . . some code
}
How do I set up 2 routes so that if the parameter is an int, it goes to DetailsById, but otherwise goes to DetailsByName?
You can use a route constraint for the first route.
routes.MapRoute("DetailsById",
"foo/{id}",
new { controller = "foo", action = "DetailsById" },
new { id = #"\d+" } // Parameter constraints
);
routes.MapRoute("DetailsByName",
"foo/{id}",
new { controller = "foo", action = "DetailsByName" }
);
The first route will only accept ids that match the regex (which accepts numbers only). If it doesn't match the first route, it will go to the second.
Use something like this:
routes.MapRoute(
"DetailsById",
"Foo/{Id}",
new {controller="Foo", action="DetailsById"},
new {Id= #"\d+" }
);
routes.MapRoute(
"DetailsByName",
"Foo/{Name}",
new {controller="Foo", action="DetailsByName"}
);
Remember that the routes are checked from top to bottom and stop at the first match.
I'm assuming that you already have a default route set up for your id parameter.
The only thing you will need to do is add a map route in your global.asax.cs:
routes.MapRoute(
"Foo_DetailsByName",// Route name
"Foo/DetailsByName/{name}",// URL with parameters
new { controller = "Foo", action = "DetailsByName", name = String.Empty } // Parameter defaults
);
In some cases, this can be accomplished through a route constraint. A common scenario is the ability to have my domain.com/482 behave the same way as my domain.com/products/details/482, where you do not want the 482 to be matched as a controller but as a Product ID.
Route constraints are regular expressions, though, so while you can use regex to match the pattern of the route, you are not actually matching based on data type.
See: http://www.asp.net/mvc/tutorials/creating-a-route-constraint-cs

How can I pass the URL to the controller while routing ignores it?

Is there a way within asp.net MVC 2 whereby I can route a request and have a portion of the URL ignored and passed to the controller as a variable?
My needs state that I must store pages dynamically in a database, and they should be accessible by looking at the URL and reading the URL segments to find the relevant page. Effectively, I need a Site controller, to which the remaining portion of the URL will be passed.
Site-Controller/this/is/a/page
So this in case the site controller would pick up the /this/is/a/page 'string'
Is this possible?
Thanks!
Yes, use a wildcard route, like:
routes.MapRoute(
"SiteController", // Route name
"Site-Controller/{*url}", // URL with parameters
new { controller = "SiteController", action = "Index" }, // Parameter defaults
null // constraints
);
Then your action looks like:
public ActionResult Index(string url)
{
}
Create a wildcard Route in Global.asax which captures everything after the first segment of the url and passes it to your Action method:
routes.MapRoute("Page",
"Site-Controller/{*urlsegments}",
new {
controller = "Site-Controller",
action = "YourAction",
urlsegments = ""
});
Make sure your Action method accepts a 'urlsegments' parameter and you can work with it from there:
public ActionResult YourAction(string urlsegments)
{
// Do something with the segments here
}

Can I constrain a route parameter to a certain type in ASP.net MVC?

I have the following route:
routes.MapRoute(
"Search", // Route name
"Search/{affiliateId}", // URL with parameters
new { controller = "Syndication", action = "Search" } // Parameter defaults
);
Is there a way I can ensure "affiliateId" is a valid Guid? I'm using MVCContrib elsewhere in my site and I'm fairly it provides a way to implement this kind of constraint.... I just don't know what it is!
You could write regex constraints:
routes.MapRoute(
"Search", // Route name
"Search/{affiliateId}", // URL with parameters
new { controller = "Syndication", action = "Search" }, // Parameter defaults
new { affiliateId = "SOME REGEX TO TEST GUID FORMAT" } // constraints
);
I've never heard of this. I fear it would cause some confusion if you mistakenly used the wrong type for the affiliateId parameter in one of your action methods.

Route Links - Url.Action

I'm trying to return my links so they display as /Area_1419.aspx/2/1.
I've managed to get that result in example 2 but I don't understand why it works, as I would exspect example 1 below to work.
I don't see how Example 2 knows to go to the Area_1419 controller?
Route
routes.MapRoute(
"Area_1419 Section",
"Area_1419.aspx/{section_ID}/{course_ID}",
new { controller = "Home", action = "Index" }
);
Links Example 1
<a href='<%=Url.Action("Area_1419",
new { section_ID="2", course_ID="1" })%>'><img .../></a>
Returns: /Home.aspx/Area_1419?section_ID=2&course_ID=1
Links Example 2
<a href='<%=Url.Action("index",
new { section_ID="2", course_ID="1" })%>'><img .../></a>
Returns: /Area_1419.aspx/2/1
Remember - URLs are detached from your controllers and their actions.
That means - even bizzare URL such as "trolololo/nomnomnom/1/2/3" might and might not call Home/Index or any other controller/action combo.
In your case - example 2 actually does not know how to go to Area_1419 controller.
Url.Action figures out url from these route details:
"Area_1419.aspx/{section_ID}/{course_ID}"
But link still will call Home controller Index action because of default route values:
new { controller = "Home", action = "Index" }
Assuming that you got Area_1419 controller with Index action, your route should look like:
routes.MapRoute(
"Area_1419 Section",
"Area_1419.aspx/{section_ID}/{course_ID}",
new { controller = "Area_1419", action = "Index" } //changes here
);
This is what you are calling.
UrlHelper.Action Method (String, Object)
Generates a fully qualified URL to an action method by using the specified action name and route values.
This method overload does not try to figure out appropriate controller. It assumes that you know it (takes it out from current route values) and understands first string argument as an action name.
Try to use this one.
UrlHelper.Action Method (String, String, Object)
Generates a fully qualified URL to an action method by using the specified action name, controller name, and route values.
In your case:
Url.Action("Index","Area_1419", new { section_ID="2", course_ID="1" });
You can use Url.RouteUrl(), in your case
Url.RouteUrl("Area_1419 Section", new { controller = "Home", action = "Index", section_ID="2", course_ID="1"}
to be sure you use the correct route name, and get the correct URL no-matter-what.

Resources