MVC Html.ActionLink not passing querystring properly - model-view-controller

This seems like it should be pretty straight forward, but I'm apparently confused.
I have a List view that displays a paged list. At the bottom I have a set of actionlinks:
<%= Html.ActionLink("First Page", "List", new { page = 1} ) %>
<%= Html.ActionLink("Prev Page", "List", new { page = Model.PageNumber - 1 }) %>
<%= Html.ActionLink("Next Page", "List", new { page = Model.PageNumber + 1 }) %>
<%= Html.ActionLink("Last Page", "List", new { page = Model.LastPage } )%>
I'm using the basic default routes setup, except with "List" substituted for "Index":
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "List", id = UrlParameter.Optional } // Parameter defaults
);
The problem is that the ActionLink helpers are generating links of the form:
http://localhost:2083/Retrofit?page=2
rather than
http://localhost:2083/Retrofit/?page=2
(with the trailing slash after the controller name & before the query string). When the first URL is routed, it completely loses the query string - if I look at Request.QueryString by the time it gets to the controller, it's null. If I enter the second URL (with the trailing slash), it comes in properly (i.e., QueryString of "page=2").
So how can I either get the ActionLink helper to generate the right URL, or get the Routing to properly parse what ActionLink is generating?
Thanks.

You need to choose one of two actions:
Modify your route to take a page parameter instead of the default id, and modify the signature of your action method accordingly.
Modify the calls to Html.AcitonLink() so they name the parameter id - that is, change new { page = ... } to new { id = ... }.

This is an old question but for others I thought I would add the answer you are looking for is add both to the routeValues parameter like
Html.ActionLink("Last Page", "List", new { id = Model.ID, page = Model.LastPage } )

Related

Make link Ajax.ActionLink in MVC 4

Beeing new to Ajax i need help with how to add the querystring and invoke the Index action without a postback. Now the link looks like this:
#sectionGroup.Term, #sectionGroup.Count
My guess is using Ajax.ActionLink but how do i create the querystring?
Everything that you add to the routeValues and doesn't match a route segment will be added to the querystring.
Using your example, it would look something like this with Ajax.ActionLink:
#Ajax.ActionLink(
sectionGroup.Term + ", " + sectionGroup.Count,
"Index",
new { section = sectionGroup.Term },
new AjaxOptions { UpdateTargetId = "id-of-container" }
)
In your Index action you need to return a partial view when it is requested with ajax. This will remove the layout (master page) from the response.
if (Request.IsAjaxRequest())
return PartialView(model);
return View(model);
Remember to add a reference to the jquery.unobtrusive-ajax.js file.

Rendering of #Ajax.ActionLink is messed up by adding a new route

I have an ActionLink:
<td>
#Ajax.ActionLink(item.HostedBy, "_DetailsMerged", "Marcher",
new { id = item.HostedById },
new AjaxOptions
{
UpdateTargetId = "marcherId" + #i ,
HttpMethod="GET",
InsertionMode = InsertionMode.Replace,
})
</td>
that displays the appropriate link when I just have default routing. However, introducing a route for a geolocation proxy, (which implments IRouteHandler and is a custom route handler) BEFORE the default routing:
routes.Add("WebgisUscproxy", new Route("WebgisUscproxy", new OpenLayers_Bronze.Utility.WebgisUscProxyHandler()));
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
while working OK for semi-hard-coded links in my client javascript ajax call (that look like: /WebgisUscproxy?zip=10003), screws up how the #Ajax.ActionLink links are rendered. They ALSO pick up '/WebgisUscproxy'. So I get:
http://localhost:59723/WebgisUscproxy?action=_DetailsMerged&controller=Marcher&id=1
instead of:
http://localhost:59723/Marcher/_DetailsMerged/1
which is what I want, and get with just the default routing. Putting:
routes.Add("WebgisUscproxy", new Route("WebgisUscproxy", new OpenLayers_Bronze.Utility.WebgisUscProxyHandler()));
AFTER the default route handler also doesn't work, as the default routing now matches semi-hard-coded links, like '/WebgisUscproxy?zip=10003'.
==========================================================================
I've found a work-around, though I hope somebody posts something more direct.
routes.MapRoute("webgisusc", "WebgisUscProxy",
new { controller = "Utility", action = "WebgisUsc" }
).RouteHandler = new OpenLayers_Bronze.Utility.WebgisUscProxyHandler();
I had created an empty Utility controller, and was going to add a dummy "WebgisUscProxy"
action to it, but it turns out that there's no need for even a dummy UtilityController. This route definition works, all by itself.

Hyperlink to call action method

I'm trying to figure out a trivial creation of a hyperlink (either through using an Html.ActionLink or plain hyperlink markup) to call a certain controller action and pass in a userId
In have a controller with an Index action. I have a hyperlink in another unrelated view where I need to all that controller's index action and pass in a userId which is param in the action method.
Update:
Html.ActionLink("Test Something", "Index", "Tests", new { #userId = #Model.User.UserId }, null)
that is an example of what I tried. Problem is, it's not showing Tests/ in the url when I moue over the url during runtime
You could use the ActionLink helper from any view anywhere in the application:
#Html.ActionLink(
"call index", // linkText
"index", // action
"home", // controller
new { userid = "123" }, // routeValue
null // htmlAttributes
)
Assuming default routes this should generate:
call index

Html.ActionLink equivalent of a specific URL format

I want to use Html.ActionLink to return an anchor tag with href like /Product/22/Product-Name, where Product is my controller name and 22 is my id and Product-Name is my title.
In my global.asax, I have set the following route :
routes.MapRoute(
"ProductRoute", // Route name
"Product/{id}/{title}", // URL with parameters
new { controller = "Product", action = "Index", id = UrlParameter.Optional });
I tried using following code
#Html.ActionLink(model.Name, null, "Product",
new { id = model.Id, title = model.Name.Replace(" ","-") }, null)
but it yields Product/Browse/22?title=Product-Name. This code is in Browse View returned by Browse action of Catalog controller and that's why it picks up the Browse in between.
Strangely, the same code works fine in the Index View returned by Index action of the Home Controller. What's the reason for this difference? . Am I missing something or this is a bug in Asp.net MVC3.
What Should I do to achieve my stated URL format. For the meantime, I am using this code
#product.Name
make sure you have defined the custom route before the default route and try
#Html.ActionLink(model.Name,
"Index",
new {controller="Product", id = model.Id, title = model.Name.Replace(" ","-") }, null)
the first parameter is the DisplayName, second the ActionResult's name and then the RouteValues

ASP.NET MVC 3 Controller route - make everything under home controller appear under the domain

Currently everything under homecontroller appears in the URL as
example.com/Home/{Action}
Is there a way we can keep all other routing the way it is but ONLY special case home controller so everything under home comes under the domain.
like
example.com/about
example.com/contact
example.com/error
instead of creating new controller classes for each of them.
EDIT:
The other URL's like
example.com/user/details/123
example.com/user/edit/123
Which are in the userController should work the same as they are now
I think the best way is:
routes.MapRoute("home", "home", new { controller = "Home", action = "Index" });
routes.MapRoute("about", "about", new { controller = "Home", action = "About" });
routes.MapRoute("contact", "contact", new { controller = "Home", action = "Contact" });
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
and when you want to create a link, use:
#Html.RouteLink("Home", "home", new{/* route values */}, new {/* html attribues */})
OR:
#Html.RouteLink("Home", "home")
instead of:
#Html.ActionLink("Home", "Index", "Home", new{/* route values */}, new {/* html attribues */})
this works for me, and should work for you too.
UPDATE:
you can create a symbol like # (or - or anything else), before the action part in url, to make the url unique, such as:
routes.MapRoute(
"test", // route name
"#{action}", // url and parameters
new {controller = "MyHome", action = "Home"} // parameter defaults
);
routes.MapRoute(
"Default", // Route name
"{controller}/{action}/{id}", // URL with parameters
new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
);
in this way, your urls are different from the Default map-route and you can create urls like:
site.com/#Home
site.com/#About
site.com/#Contact
but the first, in my idea, is better and I always use that.
Using the Attribute Routing of MVC5, I did similar to Javad_Amiry answer, by placing a route for each action in HomeController:
public class HomeController : Controller
{
[Route("about")]
public ActionResult About()
{
return View();
}
I think this is more maintainable than placing every action in the global RouteConfig.cs file. Better still to combine Attribute Routing with convention-based routing, so new actions added to controller will work by default without a Route attribute (eg: /Home/action) but can be improved by adding the Route attribute (eg: /action).
You could simply modify the default route and remove the controller bit from the url and specify that it will always be Home in the default values:
routes.MapRoute(
"Default",
"{action}/{id}",
new { controller = "Home", action = "Index", id = UrlParameter.Optional }
);
Obviously you realize that this limits your application to a single controller which is HomeController as now you no longer have any possibility to set it in your url. Stuffing all the actions in a single controller is a bad practice IMHO and violates a couple of principles like RESTful routing and SRP.
ASP.NET MVC root url’s with generic routing

Resources