What is the difference between results of
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
and
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{*id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
What does "*" do, other than without it.
Marking id with an asterisk will flag it as a "catch-all" parameter, e.g.
/Content/List/1 --> id = "1"
/Content/List/My/Content --> id = "My/Content"
However, with the following route: "{controller}/{action}/{id}" the second URL would not match at all.
More information on catch-all parameters on MSDN:
To handle additional segments in this manner you mark the last
parameter with an asterisk (*). This is referred to as a catch-all
parameter. A route with a catch-all parameter will also match URLs
that do not contain any values for the last parameter. The following
example shows a route pattern that matches an unknown number of
segments. query/{queryname}/{*queryvalues}
here is a similar question. the second one is just cause it to cached with the Catchall mapping.
Related
I want to implement a custom route in my MVC app and I just can't get it to work. I want to keep the exist default route as specified when you create your MVC app.
The routes I want to be valid should look like this:
default: /{controller}/{action}/{id}
new custom: /{controller}/{appid}/{action}/{id}
With the custom domain, I will be passing the appid in with every request, but the {id} should be optional. The routes are thus defined as follow:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Updates", action = "Index", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "NewPackageRoute",
url: "{controller}/{appid}/{action}/{id}",
defaults: new { controller = "apps", appid = "00000000000000000000", action = "Index", id = UrlParameter.Optional }
);
On the AppsController, I have an action method Index:
public ActionResult Index(string appid, string id)
If I supply the id parameter, this action method is hit as expected. I am expecting this method to also be called if the {id} parameter is not supplied, thus leaving the id parameter as null. This however does not happen.
How should I define my route differently? Should I perhaps rather make use of AttributeRouting for achieve my goal?
I should maybe also add... If I call the Search action on the Apps controller, I can get to the action. This would happen through the default route...
Hope I have all and enough info...
Oh my, but I guess I should've tried before I posted this. I left this issue for a day and now I got it working without any effort...
Thanks #StephenMuecke. You did point out the ordering of the routes which I forgot about. I played with the order initially, but at that point I had other issues in the route definitions that caused it not to work.
All I added was as length check on the appid route value and it is working... My routes are defined as follow now:
routes.MapRoute(
name: "NewPackageRoute",
url: "apps/{appid}/{action}/{id}",
defaults: new { controller = "Apps", action = "Index", id = UrlParameter.Optional },
constraints: new { appid = #"^[a-zA-Z0-9]{20}" }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Updates", action = "Index", id = UrlParameter.Optional }
);
I want to hide the controller name from URL. I am using the below code.
routes.MapRoute(
name: "Customized",
url: "{action}",
defaults: new { controller = "Home", action = "Default", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Default", id = UrlParameter.Optional }
);
This works perfecly.
but only works when i type
http :// domain/ActionName
otherwise, I still able to see
http :// domainname/controller/action
Is there any way to http ://domain/ActionName even if user tried to type
http :// domainname/controller/action
If you have only one Controller (Home) I guess you can have only one route definition ( assuming all your actions share the same parameter pattern) :
routes.MapRoute(
name: "Customized",
url: "{action}/{id}",
defaults: new { controller = "Home", action = "Default", id = UrlParameter.Optional }
);
You could potentially do something hacky like check the actual path once you got into the action and if it's not the right path, then redirect to the right path, but that technically causes two requests and could hammer your server if done frequently enough.
MVC Routing employs short-circuit logic to match the request path with an appropriate action. It doesn't care that there may be a "better" route that the user should have used, it only cares that it found a match.
My main starting page is ApplicantProfile, so my default route looks like this:
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "ApplicantProfile", action = "Start", id = UrlParameter.Optional }
);
This controller has no index for public access, but all others do. What I would like is the wildcard equivalent, e.g.
routes.MapRoute(
name: "Others",
url: "{controller}/{action}/{id}",
defaults: new { controller = "*", action = "Start", id = UrlParameter.Optional }
);
How can I achieve this?
This should take care of it:
routes.MapRoute(
name: "Default",
url: "ApplicantProfile/{action}/{id}",
defaults: new { controller = "ApplicantProfile", action = "Start", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { action = "Index", id = UrlParameter.Optional }
);
Assuming you have ApplicantProfileController, HomeController and OtherController, this will result in:
/ApplicantProfile → ApplicantProfileController.Start
/Other → OtherController.Index
/SomeOtherPath → default 404 error page
/ → default 404 error page
See http://www.asp.net/mvc/tutorials/older-versions/controllers-and-routing/asp-net-mvc-routing-overview-cs for an introduction to routing. It's a bit old, but it covers the basics well.
Routing happens top-down, meaning it stops at the first match in the routing table. In the first case, you will match your ApplicantProfile route first, so that controller is used. The second case gets Other from the path, finds a matching controller and uses that. The last 2 do not find a matching controller and there is no default specified so a default 404 error is returned. I'd suggest putting in a proper handler for errors. See the answers here and here.
This should work as per your requirement
routes.MapRoute(
name: "ApplicantProfile",
url: "ApplicantProfile/Start/{id}",
defaults: new { controller = "ApplicantProfile", action = "Start", id = UrlParameter.Optional }
);
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
First one is url which will route you to "Start' Action, other one is default replace "Home" controller with your default one
The default should goto profile controller with start action and all the other request should land to index action what ever the controller.
Use the IRouteConstraint to add the constraint to the URL for Other Routes and place that above the default controller with the constraint on the Route for the controller.
You can add a check if the controller is not ApplicationProfile use it.
I hope this helps.
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.
When I use Html.ActionLink() the URL created is not in the desired format:
Html.ActionLink(Model.ProductCode, "Update", new { id = Model.ProductId })
Makes this URL
/Update?id=1
When I want to have this URL:
/Update/1
What routing options create the 2nd URL? This is our preferred URL style.
Both URLs work and the correct page is displayed - however we want to only use /id
In Global.asax the MVC default route handles both URLs
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" }); // Parameter defaults
I can replicate the issue by having a route about my default route that still matches the general pattern. Example:
routes.MapRoute(
"Default2", // Route name
"{controller}/{action}", // URL with parameters
new { controller = "Home", action = "Index"} // Parameter defaults
);
When places above my default route, I get the ?id=1 in my URL. Can you confirm that this ActionLink is not matching any routes above the route that you are expecting it to match?
EDIT: The below does not impact the URL
However, it could still be advantageous to use the UrlParameter.Optional in other scenarios. Leaving for prosperity unless mob rule says otherwise.
new UrlParameter.Optional value. If you set the default value for a
URL parameter to this special value, MVC makes sure to remove that key
from the route value dictionary so that it doesn’t exist.
I think you need to adjust your route slightly. Change id = "" to id = UrlParameter.Optional
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional });
This is what we use for the default route and the behavior that you are looking for is how our applications behave.
See This question/answer.
Which version of MVC are you using? If you're in MVC3, you'll need to add a fourth parameter to your call to Html.ActionLink(), passing in a null.
I've just stumbled upon this and decided to answer. It turned out that both Url.Action() and Html.ActionLink() use the first route in the route collection to format the resulted URL. So, the first mapped route in the RegisterRoutes() shoild be:
routes.MapRoute(
name: "Default",
url: "{controller}/{id}/{action}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
instead of "{controller}/{action}/{id}". The route name (i.e. "Default") does not matter, only the order does matter
routes.MapRoute(
name: "Default",
url: "{controller}/{action}/{id}",
defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);