ASP.net MVC site.master link using HTML.ActionLink - asp.net-mvc

I have the following code in my site.master for a menu:
<ul id="menu">
<li><%= Html.ActionLink("My Contact Info", "DetailsbyUserName/" + Html.Encode(Page.User.Identity.Name), "Users")%></li>
</ul>
When I hover over the URL I see that it points to:
http://site/Users/DetailbyUserName/[name]
which is correct.
The issue is that when I put a breakpoint in the Users controller class below:
public ActionResult DetailsbyUserName(string loginName)
{
UserInfo user = repo.GetUserByName(loginName);
return View(user);
}
it seems that the loginName parameter is always null.
Any suggestions?

The problem is that you don't have a Route set up to specify a parameter called "loginName".
I'm guessing that your default Route is swallowing your request, and trying to assign the [name] value to a parameter called "id". If you change the name of the parameter to "id" from "loginName", I bet it will work for you.
Remember that the routing engine maps each URL segment to a named parameter. The default route looks like: "{controller}/{action}/{id}". If you want to have a parameter named "loginName", you would have to come up with a Route that had the segments "{controller}/{action}/{loginName}", that was different from the default route, so that the default route didn't match it first.

try:
Html.ActionLink("My Contact Info", "DetailsbyUserName", "Users", new { loginName = Html.Encode(Page.User.Identity.Name), null);
if your controller is something like this:
public ActionResult DetailsbyUserName(string veryVeryLongParameterName);
I guess you have to use new { veryVeryLongParameterName = "YourParamValue" } in the ActionLink's routeValues parameter.
And also, you need a route for that.
I'm very new to this too, at least that's what I understood about ActionLinks, hope someone can explain it better.

Related

MVC4 Razor Appending ID to a url using route.config

I just cant achieve my goal of getting an id to appear in a URL. Here is an example of what I have done so far.
Here is my BlogController:
public ActionResult BlogPost(int hiddenBlogId)
{
TempData["id"] = hiddenBlogId;
return View(_repository);
}
Here is my route.config:
routes.MapRoute(
"MyBlog", // Route name
"blog/{action}/{id}", // URL with parameters
new { controller = "Blog", action = "blogpost", id = #"0|-?[1-9]\d*" } // Parameter defaults
);
I am completely missing the point somewhere. How can I pick up the parameter which went into my method/action BlogPost and then display it in the output URL.
http://www.mydomain/controller/id
It's so that in the end I should be able to display the title for each blog. I'm using an ID just for simplicity for now. Any help at all would be greatly appreciated.
Your route definition says that the third value is called id, but you are trying to bind hiddenBlogId in the method. The two names need to match. Change the hiddenBlogId action method parameter to id, or map a new route with the {hiddenBlogId} placeholder.

MVC .NET 4 MapRoute + ActionLink or RouteLink issue

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.

Can't get MVC Routing to work

I have a site and the url looks like this;
Home/LocationPage?locationId=f25a9ba4-54dc-4e6a-bdbf-094a5a6f7801
What I would like it to look like is;
Home/My Restaurant
I've tried mapping routes like this;
routes.MapRoute(
"Location",
"{Controller}/{LocationName}",
new { controller = "Home", action = "LocationPage", LocationName = "" }
But can't seem to get the URL to change at all.
Keep the route you just made, but you may need to add in a couple more things.
Add in a route constraint (or override the OnActionExecuting method on the controller or add a attribute to the action method) that looks up the the LocationName route parameter in the database and (if found) adds a locationId parameter to the route parameters. Then create an action called LocationPage that takes a locationId (location Name is optional).
That way you get nice urls coming in, but the action doesn't need to do the lookups.
If you receive a parameter called LocationId in your Action then you need to change your route:
routes.MapRoute(
"Location",
"{Controller}/{LocationId}",
new { controller = "Home", action = "LocationPage", LocationId = "" }
And don't forget that in this way you wouldn't get this parameter as Guid then you should make your logic to retrieve the Guid value by the provided name.

ASPNET MVC3: how to transform an anchor to Html.ActionLink?

I have the following a href link:
title
That i use for showing SEO-friendly urls; i would like, instead of the anchor tag, to use the Html.ActionLink.
How can i transform the anchor in ActionLink considering that i have not the Action name on the url?
You can use Html.ActionLink even when the action is not present in the URL; you just need an appropriate route. Routes are used for both inbound URL matching and outbound URL generation.
First things first, you'll need a route in the Routes collection to be used as a template for the URLs that you want to generate
routes.MapRoute(
null, // name
"News/{id}/{title}", // URL pattern
new { controller = "News", action = "Index" }, // defaults
new { id = "\d+", title = #"[\w\-]*" }); // constraints
This route will only match if id is a number and title contains only word characters and/or hyphens. The route needs to be registered before any more "general" routes as the order of routes is important; the framework stops on the first matching route, it does not try to find a "best" match.
Now you can use Html.ActionLink to generate routes.
#Html.ActionLink("title", "Index", "News", new { id = item.id, title = item.NewsSeoTitle })
You may also want to look at T4MVC (available as a NuGet package) too as it adds some overloads that removes the need for magic strings all over the place
Assuming your controller action looks like
public class NewsController
{
public ActionResult Index(int id, string title)
{
return View();
}
}
T4MVC adds an overload that allows you to use Html.ActionLink like
#Html.ActionLink("title", MVC.News.Index(item.id, item.NewsSeoTitle))
much neater :)
If you are using the custom links which is not corresponding to the controller/action structure, maybe it's better to use your own html extension
public static string SeoLink(this HtmlHelper helper, string itemId, string title, string seoTitle)
{
return String.Format("{1}",
VirtualPathUtility.ToAbsolute(String.Format("~/News/{0}/{1}", itemId, seoTitle)),
title);
}
As for Html.ActionLink: from the name of extension you can find the it work with actions. Of course you can provide such action and controller names to fit your requirements, but it's not a good idea, especially if your code will be supported by any other developer - he will never find such action in controller which is specified in ActionLink as actionName param.

ActionLink not working but RouteUrl does

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.

Resources