ASP .Net MVC Routing without Controller and Action Name - asp.net-mvc

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).

Related

Having trouble creating a simple custom route

My goal is to remove "home" from any actions in that controller (see bold).
site.com/home/about
site.com/about
site.com/home/contact
site.com/contact
I created the following custom route that sits above the generic base route:
// Used to hide 'home' in the url
routes.MapRoute(
"Home", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults
);
This almost does what I want. I now get site.com/about, site.com/contact, etc. However, I cannot use index for my other controllers.
site.com/person/create -> works like a charm.
site.com/person/ -> no good.
How can I fix this? Thanks.
These two routes should work as expected:
routes.MapRoute(
"NoHomeRoute", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Person", action= "Index"}, // Parameter defaults
new { controller = #"person|admin|..." } // Parameter constraints
);
routes.MapRoute(
"HomeRoute", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults
);
Since every application has a predefined set of controllers you can put all except home in the upper constraint and it will work. But if you create a new controller, remember to put it in as well. I've put in person for PersonController which you obviously have and also added admin for AdminController you probably don't have, but I needed to put in something to show you the pattern of adding your controllers.
If you're willing to play around with regular expressions, then you could maybe come up with a solution that excludes home instead of includes all except home the way that upper route definitions suggest.
A revised negative constraint
I've checked MVC code and indeed you can define a future proof constraint on the first route definition this way:
routes.MapRoute(
"NoHomeRoute", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Person", action= "Index"}, // Parameter defaults
new { controller = #"(?!home).*" } // Parameter constraints
);
Why should this work? Because the line on ProcessConstraint method has these two lines at the end:
string pattern = "^(" + str + ")$";
return Regex.IsMatch(input, pattern, RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);
// Used to hide 'home' in the url
routes.MapRoute(
"Home", // Route name
"{action}", // URL with parameters
new { controller = "home", action= "index"} // Parameter defaults);
should be the last route you register, otherwise site.com/person is interpreted as an action, since it will match that route first.

Why is the wrong controller being called when I start my ASP.NET MVC2 application?

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?

Asp.Net MVC Routes - Handle Multiple routes with the same signature?

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.

Confusion about MVC Routes

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

URL Routing parameter name, order

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.

Resources