MVC3 routing issue with nullable parameter - asp.net-mvc

I have an odd issue. I have a controller action which takes a couple of optional parameters
Function Index(sectionID As Integer?, title As String) As ActionResult
Return View()
End Function
I then have added a specific route for this action method so that we get pretty urls for this page
routes.MapRoute( _
"By_Section", _
"home/{sectionID}/{title}", _
New With {.controller = "Home", .action = "Index", .sectionID = Nothing},
New With {.sectionID = "\d+"}
)
This all works. However, when I am on a page where the sectionID is set (for example http://localhost/home/index/1/test), the following piece of code produces an odd output.
<%= Url.Action("Index", "Home")%>
Instead of showing http://localhost/home/index as you might expect, it shows http://localhost/home/index/1/test. So it appears it is picking up the sectionID and title from the current url and automatically inserting them into the Url.
How can I prevent this from happening?
Thanks
James

Yes, this is expected behaviour, the routing system will reuse parameter values from the current request if you haven't provided a new value explicitly. The best option when rendering links is to specify explicit values for all of your routing parameters.
<%= Url.Action("Index", "Home", new { sectionID = (int?)null }) %>

Related

How to pass query string parameter in ActionLink in MVC

I am having following action link:
<%= Html.ActionLink("Check this", "Edit", "test",
new { id = id }, new { style = "display:block" })%>
How do I include data=name as query string. Some thing like this:
link?data=name
4th parameter of Html.ActionLink can have any number of properties:
<%= Html.ActionLink("Check this", "Edit", "test",
new { id = id, data=name }, new { style = "display:block" })%>
These properties are inserted into URL based on routing, but if the property name cannot be matched into any route it is added as URL GET parameter.
So if you have standard route {controller}/{action}/{id}, you will get the URL:
test/Edit/[id]?data=[name]
from the above code.
Pass Query String By this way
#Html.ActionLink("Delete Record", "Home", "Delete", new { id=Id},null)
By above code you will get the url like(Suppose Id=1): /Home/Delete/1
and if you want to add more parameters to query string then:
#Html.ActionLink("Delete Record", "Home", "Delete", new { id=Id, Name=name},null)
By above code you will get the url like(Suppose Id=1 and Name=India) :
/Home/Delete/1?Name=India
I got tired of banging my head against a wall with the html.actionlink. Works great when you just want to route it against straightforward routing calls, but absolutely refuses to cooperate when you want to add a simple querystring at the end.
I don't an ID at then end, I want to be able to add some kind of actual Querystring with the "?".
So anywhere I needed a Querystring I switched to using the url.action inside the anchor tag.
<a href='#url.action("Action","route")?Parameter=Value' >Text for Link Name</a>
At least it works and I can stop getting headaches over something that should have been a very simple task. Someone needs to get their heads out of their butts and make the ActionLink work properly for Querystrings in the MVC routing.
I know this is kind of old question but.
In case the below code doesn't generate the <a href="/?param=value" />.
<%= Html.ActionLink("Text", "Action", "Controller", new { param=value }, null)%>
I would advice checking whether you action has at least one [Route] attribute (I used [Route("/")] for example).
Hope it helps.

auto add route parameter to url

i have 2 urls on one page: http://host/home/list and http://host/home/list/1. if i click on second url then first url renders with param 1, so url1 equals ulr2 (url1 = http://host/home/list/1 and url2=http://host/home/list/1)
i use such code
<%= Html.ActionLink("link", "DesignerFiles", "Home", null, null)%> url1
<%= Html.ActionLink("link", "DesignerFiles", "Home", new { id = 1} , null)%> url2
what the problem?
I had a simliar issue with sub level and tertiary navigation elements. IE - a link that should go to /Home/About from the /Home/About/People would append /People to the first link. I used the following method to get this to work correctly:
<%= Html.ActionLink("Link", "About", "Home", new with {.section = nothing}, nothing%>
<%=Html.ActionLink("Link2", "About", "Home", new with {.section = "People"}, nothing%>
That seemed to force the ActionLink to not include the additional parameter that was in the current context of my view. Side note, I changed the dafault {controller}/{action}/{id} to {controller}/{action}/{section} - which is why you see section in my route values.

ASP.NET MVC Url.Action routing error

I've been using this some while now, but I can't seem to figure out, where could be mistake in this simple code:
<a href="<%= Url.Action("Page", new { page=(Model.PageIndex + 1) }) %>" >a</a>
With this routing table:
routes.MapRoute(
"Paging",
"Home/Page/{page}",
new { controller = "Home", action = "Index" }
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = "" } // Parameter defaults
);
And of course this method
public ActionResult Index(int? page)
I am getting instead of expected address http://localhost:58296/Home/Page/1 the one http://localhost:58296/Home/Page?page=1
When using
<%= Html.RouteLink("a", "Paging", new { page=(Model.PageIndex+1) }) %>
it works.. Please, where is my mistake? I want image link, so if there is a way to insert it into Html.RouteLink, I would appriciate that info too.
Thanks in advance.
There's a bunch of items to cover here for you to fully understand what's happening. Sorry, this will be a bit long.
routes.MapRoute(
"Paging",
"Home/Page/{page}",
new { controller = "Home", action = "Index" }
);
First, this is the route you want to hit. You do not include the action route parameter, '{action}', in the route path. The only action this route can possibly take is the value you have specified as the default action value "Index".
<a href="<%= Url.Action("Page", new { page=(Model.PageIndex + 1) }) %>" >a</a>
Second, in your link you are setting an action of Page. The route you are expecting does not accept action as a parameter and the only action it is aware of is Index. When Url.Action looks for possible routes in your route table, it will skip the route you want because that route does not accept an action of Page. The default route is valid though because you are implicitly supplying a controller, Home, explicitly supplying an action, Page, allowing the framework to supply a default for id, string.Empty, and any other parameters are tacked on as query parameters, page.
When you changed the Url.Action to "Index", the Url.Action method inspected the routes table and found the route with the action of Index specified for the Home controller with a parameter of page and everything is happier.
Hope that helps and isn't too confusing.
I don't know why, but
<%= Url.Action("Index", new { page=(Model.PageIndex + 1) }) %>
works and it displays and directs to /Home/Page/1 . If someone could explain it to me, I would be gratful.

Asp.Net MVC Call another controller from view

Let say I'm on the page "Home/Index" and I want to go to the page MyOtherController/Index/1
How can I do this ?
I try :
<%= Html.ActionLink("Test", "Index", "MyOtherController", new { id=item.Id }) %>
Did I also have to add a route in Global.aspx file ?
One option is to specify the name of the controller in the list of routevalues:
<%= Html.ActionLink("Test", "Index"
, new { controller = "MyOtherController", id = item.Id }) %>
An alternative is to use the overload of ActionLink with htmlAttributes = null:
<%= Html.ActionLink("Test", "Index"
, "MyOtherController", new { id = item.Id }, null) %>
The default route in the ASP.NET MVC template takes care of the routing in this case.
I don't believe ActionLink has an overload matching that particular signature. You would need to add "null" after your route values to find a matching one (for htmlAttributes). Ole's solution would be cleaner though so it's really a matter of preference. It also will help with readability so you don't have to guess whether each parameter is link text, an action/controller, etc.

asp.net mvc Html.ActionLink() keeping route value I don't want

I have the following ActionLink in my view
<%= Html.ActionLink("LinkText", "Action", "Controller"); %>
and it creates the following URL http://mywebsite.com/Controller/Action
Say I add an ID at the end like so: http://mywebsite.com/Controller/Action/53 and navigate to the page. On this page I have the markup I specified above. Now when I look at the URL it creates it looks like this:
http://mywebsite.com/Controller/Action/53 (notice the addition of the ID)
But I want it to remove the ID and look like it did originally, like this http://mywebsite.com/Controller/Action (notice no ID here)
Any ideas how I can fix this? I don't want to use hard coded URLs since my controller/actions may change.
The solution is to specify my own route values (the third parameter below)
<%= Html.ActionLink("LinkText", "Action", "Controller",
new { id=string.Empty }, null) %>
It sounds like you need to register a second "Action Only" route and use Html.RouteLink(). First register a route like this in you application start up:
routes.MapRoute("ActionOnly", "{controller}/{action}",
new { controller = "Home", action = "Index" } );
Then instead of ActionLink to create those links use:
Html.RouteLink("About","ActionOnly")
The problem is the built in methods take input from the URL you are currently on as well as what you supply. You could try this:
<%= Html.ActionLink("LinkText", "Action", "Controller", new { id = ""}) %>
That should manually wipe the id parameter.
Don't know why, but it didn't work for me (maybe because of Mvc2 RC). Created urlhelper method =>
public static string
WithoutRouteValues(this UrlHelper helper, ActionResult action,params string[] routeValues)
{
var rv = helper.RequestContext.RouteData.Values;
var ignoredValues = rv.Where(x=>routeValues.Any(z => z == x.Key)).ToList();
foreach (var ignoredValue in ignoredValues)
rv.Remove(ignoredValue.Key);
var res = helper.Action(action);
foreach (var ignoredValue in ignoredValues)
rv.Add(ignoredValue.Key, ignoredValue.Value);
return res;
}
If you either don't know what values need to be explicitly overridden or you just want to avoid the extra list of parameters you can use an extension method like the below.
View
The implementation details are in this blog post
I explicitly set the action name as "Action/". Seems a little like a hack but it's a quick fix.
#Html.ActionLink("Link Name", "Action/", "Controller")
Another way is to use ActionLink(HtmlHelper, String, String, RouteValueDictionary) overload, then there are no need to put null in the last parameter
<%= Html.ActionLink("Details", "Details", "Product", new RouteValueDictionary(new { id=item.ID })) %>
The overloads of Html.ActionLink are changed on the later versions of MVC. On MVC 5 and above. This is how to do this:
#Html.ActionLink("LinkText", "Action", "Controller", new { id = "" }, null)
Note I passed "" for id parameter and null for HTMLATTRIBUTES.
I needed my menu links to be dynamic. Rather than implement a lot of extra code and routing for every single page I simple dispensed with the HTML helper.
#item.MenuItemName

Resources