I am currently writing my own paged list for ASP.NET Core MVC.
I struggle while creating the following:
I want to create a UrlHelper extension method: Url.PageLink(int page, int pageSize)
Within that extension method I want to return a link which reuses ALL current values for controller, action, querystring and in addition it should add/update the page, pageSize values in the querystring as well.
Questions: From where do I get the current controller and action in the UrlHelper object? What is the best way to rebuild the querystring? I can see it here url.ActionContext.HttpContext.Request.QueryString... but do I really have to manually rebuild it? Or does something like AddQueryStringValue(int key, object value) exist?
Thanks so much in advance!!! Simon
Improvement of Simon's answer:
It can be called as @Url.Current(new {page=42, id=5, foo=bar})
It will preserve query string and update/add provided values.
public static class UrlHelperExtensions
{
/// <summary>
/// Get current URL with substituted values while preserving query string
/// </summary>
/// <param name="helper"></param>
/// <param name="substitutes">Query string parameters or route data paremers. E.g. new { action="Index", sort = "asc"}</param>
/// <returns></returns>
public static string Current(this IUrlHelper helper, object substitutes)
{
RouteValueDictionary routeData = new RouteValueDictionary(helper.ActionContext.RouteData.Values);
IQueryCollection queryString = helper.ActionContext.HttpContext.Request.Query;
//add query string parameters to the route data
foreach (var param in queryString)
{
if (!string.IsNullOrEmpty(queryString[param.Key]))
{
//rd[param.Key] = qs[param.Value]; // does not assign the values!
routeData.Add(param.Key, param.Value);
}
}
// override parameters we're changing in the route data
//The unmatched parameters will be added as query string.
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(substitutes.GetType()))
{
var value = property.GetValue(substitutes);
if (string.IsNullOrEmpty(value.ToString()))
{
routeData.Remove(property.Name);
}
else
{
routeData[property.Name] = value;
}
}
string url = helper.RouteUrl(routeData);
return url;
}
}
The question asks for Asp.Net Core. I was trying to use shturm's answer on MVC 5 and could not get it to work. I took his same concepts and changed it to work with MVC 5. If anyone needs this verison, I'm posting it here. I also added the ability to change the action and controller.
/// <summary>
/// Get URL with substituted values while preserving query string.
/// </summary>
/// <param name="helper">The url helper object we are extending.</param>
/// <param name="action">The action we want to direct to.</param>
/// <param name="controller">The controller we want to direct to.</param>
/// <param name="substitutes">Query string parameters or route data paremers. E.g. new { action="Index", sort = "asc"}</param>
/// <returns>The route string.</returns>
public static String ActionWithOriginalQueryString(this UrlHelper helper, String action, String controller, object substitutes)
{
RouteValueDictionary routeData = new RouteValueDictionary(helper.RequestContext.RouteData.Values);
NameValueCollection queryString = helper.RequestContext.HttpContext.Request.QueryString;
//add query string parameters to the route data
foreach (var param in queryString.AllKeys)
{
if (!string.IsNullOrEmpty(queryString[param]))
{
//rd[param.Key] = qs[param.Value]; // does not assign the values!
routeData.Add(param, queryString[param]);
}
}
// override parameters we're changing in the route data
//The unmatched parameters will be added as query string.
foreach (PropertyDescriptor property in TypeDescriptor.GetProperties(substitutes.GetType()))
{
var value = property.GetValue(substitutes);
if (string.IsNullOrEmpty(value?.ToString()))
{
routeData.Remove(property.Name);
}
else
{
routeData[property.Name] = value;
}
}
//Set the controller and the action.
routeData["controller"] = controller;
routeData["action"] = action;
//Return the route.
return helper.RouteUrl(routeData);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With