Asking for the best way to address this issue:
in my controller I have the following action
public ActionResult Member(string id){return View();}
another action in the same controller
public ActionResult Archive(string year){return View();}
in my global.asax
routes.MapRoute(
"Archive", // Route name
"{controller}/{action}/{year}", // URL with parameters
new { controller = "Home", action = "Index", year = "" } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id="" } // Parameter defaults
);
if I call this url mysite.com/archive/2009 this works because the action expecting parameter with a name "year" and the first route schema works with this request. But if I call this url mysite.com/member/john it will result in this url mysite.com/member?id=john
So it looks like if my first route in global.asax have the same construction but different parameter name, the one with the right parameter name will have the right url (mysite.com/archive/2009) but for the other won't. How can I solve this issue? I can change the route table to expect a generic parameter name like "param", but I need to change all the signature of the action to "param" as well and it is not very descriptive (param instead year or param instead id).
Try this:
routes.MapRoute(
"Archive", // Route name
"Home/Member/{id}", // URL with parameters
new { controller = "Home", action = "Member", id = "" } //
Parameter defaults
);
routes.MapRoute(
"Archive", // Route name
"{controller}/{action}/{year}", // URL with parameters
new { controller = "Home", action = "Index", year = "" } // Parameter defaults
);
You are allowed to use literals in the second parameter, and they will act as filters. The more specific your route is, the closer you need to put it to the top of the route configuration, the routing system will choose the first route that matches.
Here is a link to more detailed background information. Some of the syntax has changed since the article was written but the basic rules seem up to date.
Related
asp.net mvc routing pattern is
{"some_parameter/{controller}/{action}/{id}"}
Is this a valid format if some_parameter can be null or string empty
I believe that what you wanted is {some_parameter}/{controller}/{action}/{id} (notice curly brackets around "some_parameter") and in that case it shouldn't be null or empty, I think. How do you think your end URL might look like to match the route in case when some_parameter is empty? "mysite.com//mycontroller/myaction/myid"?
Routing engine just matches patterns. If you want to handle both {some_parameter}/{controller}/{action}/{id} and {controller}/{action}/{id}, just define both routes.
Edit
I've just reordered the route registration so that it would work:
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new {
controller = "home",
action = "index",
id = UrlParameter.Optional }
);
routes.MapRoute(
"Default", // Route name
"{some_parameter}/{controller}/{action}/{id}", // URL with parameters
new {
some_parameter = UrlParameter.Optional,
controller = "home",
action = "index",
id = UrlParameter.Optional
}
);
They should be registered in that order. Additionally the second route requires an id and some_parameter parameter otherwise it will never be hit because of the route before it. Even though the some_parameter and id parameters are set to optional, that would never happen because the route before would catch it if it was empty.
simple question. I want something like:
http:/ /www.mywebsite.com/microsoft or http:/ /www .mywebsite.com/apple
so microsoft and apple should be like id but i use it just like controller in the default
this is the default route
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "index", id = UrlParameter.Optional } // Parameter defaults
);
This produce something like http:/ /www.mywebsite .com/home/aboutus or http: //www.mywebsite .com/products/detail/10
I added another route
routes.MapRoute(
"Partner", // Route name
"{id}", // URL with parameters
new { controller = "Home", action = "Partners"}, // Parameter defaults
new { id = #"\d+" }
);
but this has constraint that only allow numeric id.
how do I accomplish what I wanted.
thanks
If the expression can contain only letters and digits you could modify the constraint:
routes.MapRoute(
"Partner", // Route name
"{id}", // URL with parameters
new { controller = "Home", action = "Partners"}, // Parameter defaults
new { id = #"^[a-zA-Z0-9]+$" }
);
Not sure exactly what you are trying to achieve but it looks like you need a custom route constraint. Take a look here for an example:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Custom-route-constraint-to-validate-against-a-list.aspx
Remember to register the route constraint first
If you don't want to provide a numeric constraint, just delete the 4th parameter, ie
routes.MapRoute("Partner", "{id}", new { controller = "Home", action = "Partners"});
The 4th parameter is an anonymous object that provides constraints for the route parameters that you have defined. The names of the anonymous object members correspond to the route parameters - in this case "controller" or "action" or "id", and the values of these members are regular expressions that constrain the values that the parameters must have in order to match the route. "\d+" means that the id value must consist of one or more digits (only).
I have a controller called MetricsController with a single action method:
public class MetricsController
{
public ActionResult GetMetrics(int id, string period)
{
return View("Metrics");
}
}
I want to route calls to this controller like this:
http://mysite/metrics/getmetrics/123/24h
I've mapped an additional route in my Global.asax.cs like this:
routes.MapRoute(
"Metrics",
"{controller}/{action}/{id}/{period}",
new { controller = "Metrics", action = "GetMetrics", id = 0, period = "" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
I just added this to the default template project that Visual Studio 2010 creates.
When I run the application, instead of defaulting to the HomeController, it starts in the MetricsController instead.
Why is this happening? There's nothing in the url when I start the application that matches the url pattern specified in the Metrics route.
This is all being tried in Visual Studio 2010 using the built-in web server.
Because it matches first root, of course.
Thing is - when You provide default values - they become optional. If every one of routedata values are optional and route is first - it's guaranteed that it will hit first.
Something like this should work:
routes.MapRoute(
"Metrics",
"Metrics/GetMetrics/{id}/{period}",
//assuming id, period aren't supposed to be optional
new { controller = "Metrics", action = "GetMetrics" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Remove the defaults from your Metrics route:
routes.MapRoute(
"Metrics",
"{controller}/{action}/{id}/{period}",
new { controller = #"Metrics", action = "GetMetrics"}
);
With the default values MVC is able to map to the GetMetrics action in the Metric controller pretty much any URL that you pass to it.
In short: it's using the Matrics route because it matches the Matrics route.
In long: The default route defines defaults for all the route components and all of the route components are optional. All that your Metrics route is doing is adding another optional route parameter with a default... it's basically no different from the default route because the whole route contains optional parameters.
If you want it to work, you need to differentiate your Metrics route from the default route.
E.g.
routes.MapRoute(
"Metrics",
"metrics/{action}/{id}/{period}",
new { controller = #"Metrics", action = "GetMetrics", id = 0, period = "" }
);
HTHs,
Charles
Side note:
There's nothing
in the url when I start the
application that matches the url
pattern specified in the Metrics
route.
Let's look at this from a different angle - what in the url matches the url pattern specified in the default route?
I'm interested to know how people handle the following situation.
Assume we have a DataField and each DataField can have unlimited number of DataValues
We have 2 controllers to handle the manipulation of these objects
DataFieldController
DataValueContoller
Now if we ever need to add a new DataValue we need to know the ID of the CustomDataField. The following URL would be used,
/CustomDataValue/Add/1
1 = DataField ID
However, because the ASp.Net MVC engine binds the parameter name to the model (IE in the case below. My DatValeu Object would have its ID replaced, when I am actually trying to pass through the FieldID)
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Site", action = "Home", id = UrlParameter.Optional } // Parameter defaults
);
How can we handle this? Doing the following obviously will not work.
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Site", action = "Home", id = UrlParameter.Optional } // Parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{fieldid}", // URL with parameters
new { controller = "Site", action = "Home", fieldid = UrlParameter.Optional } // Parameter defaults
);
I assume this is a common problem, I just cant find the obvious solution at the moment. It would be ok if the Signature was differant but both are /String/String/Int
==========================
How can these routes work then?
/DataValue/Add/{DataFieldID}
/DataValue/Edit/{ID}
/DataValue/List/{DataFieldID}
Must I add 3 routes?
Use constraints in routes like this:
routes.MapRoute(
"Default", // Route name
"CustomDataValue/{action}/{fieldid}", // URL with parameters
new { controller = "Site", action = "Home", fieldid = UrlParameter.Optional } // Parameter defaults
);
It makes sure only URLs starting with "CustomDataValue" calls this route. It's declared as a constant, different from the default route. Make sure these specified routes are declared before the default route. Since there are no restrictions, all URLs are matched to it.
Update
I guess you have to call DataValueController methods with URLs like http://domain.com/CustomDataValue/Add/23. If that's the case use the following route:
routes.MapRoute(
"CustomData", // Route name
"CustomDataValue/{action}/{fieldid}", // URL with parameters
new { controller = "DataValue", action = "List", fieldid = UrlParameter.Optional } // Parameter defaults
);
This will work if you have action methods in DataValueController named List/Add/Edit.
What is the problem below?
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "test" } // Parameter defaults
);
routes.MapRoute(
"Default1", // Route name
"{controller}/{action}/{name}", // URL with parameters
new { controller = "Home", action = "Report", name = "" } // Parameter defaults
);
When I navigate to /home/index "id" parameter takes the default value of "test" but when I navigate to home/report the name parameter is null.
In short, if the route definition is the first in the route table, then the parameter takes its default value. But the others below don't.
These two routes {controller}/{action}/{id} and {controller}/{action}/{name} are ambiguous. It cannot distinguish between /home/index/id and /home/report/abc, it is always the first route in the route definition which will be caught because in the second case it thinks that id = "abc".
Use Phil Haack Routes debugger.. to get more clear view how your routes are reacting on diferent paths.
download