I have an action like so:
#Html.ActionLink(dinner.Title, "Details", new { id=dinner.DinnerID })
and a route defined like so:
routes.MapRoute(
"PrettyDetails",
"{Id}",
new { controller = "Dinners", action = "Details" },
new { Id = #"\d+" }
);
The action link renders My Dinner
Why does it not display "Details" in the link? Is it because it knows about the routes defined in Global.asax and therefore matches the pattern somehow?
Thanks
Why does it not display "Details" in the link?
Because the route pattern you have defined in your Global.asax is {Id} where id must be an integer. So to answer your question, yes, the Html.ActionLink helper respects the routes you have defined in your Global.asax.
If you want to be able to pass a different action than details you will have to modify your pattern. For example like this: {action}/{id}. Obviously the same stands true for the controller part.
You could use the Html.RouteLink which allows you to specify a route name if you don't want the evaluation to happen in the order of your route definitions in Global.asax. This way you could target a specific route. Of course the arguments you are passing must be coherent with this route.
The answer is "Yes", ActionLink is taking the defined routes into account when rendering the URL.
Related
Okay, so here's the deal. I've got controller called "Hotel" with view called "Index", where I'm trying to produce code allowing me to generate links in form of:
../Hotel?id=1
with ID passed as argument. To do so, I've tried using MapRoute:
#Html.RouteCollection.MapRoute("Hotel", "../{controller}/{id}", new { controller = "hotel" });
together with ActionLink:
#Html.ActionLink("More >>>", "", "Hotel", new { id = item.HotelId }, null)
But the outcome link goes like this:
Hotel/Index/1
Which leads to correct location, but burns visual consistency of all links at my website. I've tried RouteLink as well, but with no success.
Thanks in advance!
Do you want to make all links in the application use the standard querystring format for parameters named "id"? If so, removing the {id} from url and defaults object in the "Default" route should do that for you just fine.
If you want to limit it to the "Hotel" controller, you are on the right track w/ the custom route. First, make sure the custom route comes before the default route definition, and second, define it with nothing beyond the controller/action like:
routes.MapRoute(
"HotelRoute", // Route name
"Hotel/{action}/", // URL with parameters
new { controller="Hotel", action = "Index" } // Parameter defaults
);
Any params you pass in should then be appended to the query string as a name/value pair.
I am trying to define dynamic sections of my site with the root url of the site. I am having some trouble defining the right MVC Route for it. Can someone please help.
My desired url will look like this: http://website.com/[dynamic-string]
But I have other standard pages like: http://website.com/about or http://website.com/faq or even just http://website.com.
My routes don't work correctly with that dynamic string. As shown below.
This is the route for the dynamic-string.
routes.MapRoute(
"CommunityName", // Route name
"{communityName}", // URL with parameters
new { controller = "Community", action = "Community", communityName = UrlParameter.Optional }
);
This is the route for all other STANDARD PAGES
routes.MapRoute(
"Default", // Route name
"{action}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
My routes just don't match up. Everything either gets diverted to one or the other route depending on which route is declared first.
There is no difference between the two routes you mention. How can MVC know which url should be mapped to communityName and which to action? Any url can match both.
You can define your standard pages as a route (before the CommunityName route) or you can catch them in your Community action, see if the name matches a function in your Home controller and then call the right action function.
I've never done this before but you might be able to create a more intelligent routehandler that looks at your controller actions, checks if the action really exists and if true selects that route.
this is beacuse the routes are effectively the same. When you declare the action route you do not state any constraints to the route, for this reason anything will be assumed to be a the action name.
If you want two routes to capture at the same level then you must constrain the action names to those that exist on your controller, this way if it does not match it will pass to the next route.
You can see an example of and advanced constraint here:
http://blogs.planetcloud.co.uk/mygreatdiscovery/post/Custom-route-constraint-to-validate-against-a-list.aspx
In most of the articles, they put this code and explain it but I feel I am not getting it. could any body expalain it in simple terms please.
This question is looks simple but I cannot get it correct in my head.
public static void RegisterRoutes(RouteCollection routes)
{
routes.IgnoreRoute("{resource}.axd/{*pathInfo}");
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
My Questions:
Why do we use route.IgnoreRoute and why the parameters in {} ?
Maproute has First parameter-Default, What that resembles, Second Parameter-"{controller}/{action}/{id}", What this for and third parameter, we use new ?
How do I intrepret these routing?
Why all these?
I have used webforms so far and Cannot get it in?
Any Gurus in MVC could explain all these please?
Why do we use route.IgnoreRoute
This tells routing to ignore any requests that match the provided pattern. In this case to ignore any requests to axd resources.
and why the parameters in {} ?
The {} indicates that the delimited string is a variable. In the ignore route this is used so that any .axd requests are matched.
Maproute has First parameter-Default, What that resembles,
The first parameter is the route name. This can be used when referring to routes by name. It can be null which is what I tend to use.
Second Parameter-"{controller}/{action}/{id}", What this for
This is the pattern that is matched. In this case it is setting up the default route which is a url formed by the controller name, action name and an optional id. The url http://mysite.com/Foo/Bar would call the Bar method on the Foo controller. Changing the url to http://mysite.com/Foo/Bar/1 would pass a parameter with the identifier id and value 1.
and third parameter,
The third parameter supplies defaults. In the case of the default route the default controller name is Home and the default action is Index. The outcome of this is that a request to http://mysite.com would call the Index method on the Home controller. The id part of the route is specified as being optional.
we use new ?
The new keyword is creating an object using the object initializer syntax that was introduced in version 3 of the .Net framework. Microsoft article.
The major advantage of using routing is that it creates a convention for your urls. If you created a new controller called Account and action methods called Index and Review then the methods would be availble at /Account and Account/Review respectively.
First of all: ASP.NET MVC is not a simple version of webforms.
MVC has a special structure. You can find a MVC description here: http://en.wikipedia.org/wiki/Model-View-Controller
MapRoute adds the URL structure mapping. For example, following the default route link like www.domain.com/home/users/1 means that the server should call the users action in the controller called home. The action gets a parameter called id with the value of 1.
If you want to add the new Route you can simply add this uin next way:
routes.MapRoute(
"NewRoad", // Route name
"/photos/{username}/{action}/{id}", // URL with parameters
new { controller = "Photos", action = "Index", string username, id = UrlParameter.Optional } // Parameter defaults
);
following this road the url will be: domain.com/photos/someuser/view/123. We can map the optional parameters like id, and static parameters, like username. By default we call photos controller and index action (if the action not set in ult, server will call default action "index", we set it in the route).
My URL requirement is countryname/statename/cityname. For this I'm writing my own RouteHandler and adding one new route into the routecollection like this:
routes.Add(new Route("{*data}",
new RouteValueDictionary(new
{
controller = "Location",
action = "GetLocations"
}),
new MyRoutehandler()));
Now my question is: How do I generate this type of URL?
I tried Html.ActionLink() but it's asking for an action name and controller name. However, in my URL format I don't have any action name or controller name. How do I solve this?
Is there a reason you can't just use the following with the built-in route handler:
routes.MapRoute("LocationRoute",
"{countryname}/{statename}/{cityname}",
new { controller = "Location", action = "GetLocations" });
That may conflict with the default "{controller}/{action}/{id}" route, but that would happen with your current system anyway (unless you make a custom Route, inheriting from System.Web.Routing.RouteBase, rather than a custom Route Handler). The Route Handler is for handling what to do AFTER the route data has been extracted. Since you're still using Controller and Action, you should still be able to use the MvcRouteHandler. If you want to customize how the Route Data is extracted, you probably want a custom Route.
Btw, if you want to use a route which doesn't involve Controller and Action names, use Html.RouteLink. ActionLink is just a wrapper which puts the controller and action into the RouteValuesDictionary and calls the same internal helper as RouteLink.
Although in this case, the route still has a Controller and Action ("Location" and "GetLocations"), so you can still use ActionLink. I think ActionLink lets you specify a Route Name, so if you give your route a name you can specify that name in ActionLink and it will use that route to generate the URL (I may be wrong about that and if so you can still use RouteLink and manually add the controller and action route values)
I have a route
// Sample URL: /Fixtures/Team/id
routes.MapRoute(
"Fixtures-by-TeamID",
"Fixtures/Team/{teamId}",
new { controller = "Fixtures", action = "GetByTeamID", },
new { teamId = #"\d{1,3}" }
);
and I am trying to use ActionLink in ASP.net MVC p5.
<%= Html.ActionLink(g.HomeTeam.TeamName, "Team", new { teamId = g.HomeTeam.TeamID })%>
However it is not working and giving me
Team A
If I use Url.RouteUrl i get the correct link.
<%=g.HomeTeam.TeamName%>
Team A
Any help would be great? Will this change in ASP.net MVC beta?
Thanks
Donald
In my experience, the only time action routes really work properly is when you only have the single default route. As soon as you start adding custom routes like yours above, action routes become... I guess "finicky" is the right word. The matching system doesn't work exactly how you'd expect it to.
In this case, you said the action was "Team", but this route doesn't match an action of "Team", it only matches "GetTeamByID". So the routing system keeps going and ends up giving you a route based on the default route. The teamId isn't explicitly part of your default route, so it ends up as a query parameter tacked on the end.
MVC Beta has already shipped, and this behavior is unchanged.
Also, don't you find the named route to be clearer anyway? Personally, I do.
I even go one step further and actually create route helpers for all my custom routes, which might look like this in your current example:
<%= g.HomeTeam.TeamName %>
Or even:
<%= Html.LinkToFixturesByTeam(g.HomeTeam) %>
where you can pull the values for name and ID directly from the model.
Try this:
// Sample URL: /Fixtures/Team/id
routes.MapRoute(
"Fixtures-by-TeamID",
"Fixtures/Team/{teamId}",
new { controller = "Fixtures", action = "Team", teamId = -1 }
);
your controller should look like:
public class FixturesController : BaseController // or whatever
{
/*...*/
public ActionResult Team(int teamId)
{
return View("Detail", Team.GetTeamById(teamId)) // or whatever
}
/*...*/
}
And your link would look like
<%= Html.ActionLink("Click here for the team details", "Team", "Fixtures", new { teamId = ViewModel.Data.Id /*orwhateverlol*/ }) %>
(I don't have MVC on this machine so this is all from memory; may have a syntax error or some arguments reversed).
Note your route map's path matches your 1)controller, 2) action 3) argument name. I've found the default action (third argument in MapRoute) works, whereas your overload of that method I've never seen before (may be a holdover from a previous release).
Also observe how your FixturesController matches the path (Fixtures) and the action name matches (Team), and the argument matches as well (teamId).
Lastly, your ActionLink's last argument must match your controller's arguments in name (teamId) and type.
Its a bit too "magical" at this point (there's LOTS of string comparisons going on in the background!). Hopefully this will improve over time. The old Expression style was MUCH MUCH better. You essentially called the method you wished to run, with the values you wished to pass it. I hope they bring that expression style back into the framework. Haack?
Have you tried this yet?
Html.ActionLink<FixturesController>(c => c.GetByTeamID(g.HomeTeam.TeamID), "Team")
Also
You might want to add action = "GetByTeamID" to your constraints.
When a parameter ("action" in this case) is defined only in defaults and not in the route url, it has to be an exact match (unless you force it to go against a particular route as in the RouteUrl case).
To make everything work as is right now, you could add another route to the list just below the above route:
routes.MapRoute(
"Fixtures-by-TeamID1",
"Fixtures/Team/{teamId}",
new { controller = "Fixtures", action = "Team", },
new { teamId = #"\d{1,3}" }
);
OR you could add the action parameter to the route url,
OR you could use the named route as you did.