我目前正在为ASP.NET Core MVC编写自己的分页列表。
我在创建以下内容时遇到了困难
我想创建一个UrlHelper扩展方法:Url.PageLink(int page,int pageSize)
在该扩展方法中,我想返回一个链接,该链接重用控制器,操作,查询字符串的所有当前值,此外它还应该在查询字符串中添加/更新页面,pageSize值。
问题:从哪里获取UrlHelper对象中的当前控制器和操作?重建查询字符串的最佳方法是什么?我可以在这里看到url.ActionContext.HttpContext.Request.QueryString ...但我真的必须手动重建它吗?或者是否存在类似AddQueryStringValue(int key,object value)的东西?
非常感谢提前!!!西蒙
现在这样做了:
public static class UrlHelperExtensions
{
public static string Page(this IUrlHelper url, int page, int pageSize)
{
//Reuse existing route values
RouteValueDictionary resultRouteValues = new RouteValueDictionary(url.ActionContext.RouteData.Values);
//Add existing values from query string
foreach (var queryValue in url.ActionContext.HttpContext.Request.Query)
{
if(resultRouteValues.ContainsKey(queryValue.Key))
continue;
resultRouteValues.Add(queryValue.Key, queryValue.Value);
}
//Set or add values for PagedList input model
resultRouteValues[nameof(PagedListInputModel.Page)] = page;
resultRouteValues[nameof(PagedListInputModel.PageSize)] = pageSize;
return url.RouteUrl(resultRouteValues);
}
}
并为页面列表值创建了一个单独的输入模型“PagedListInputModel”...这样我可以确保我可以在所有地方重用它,而不必确保所有需要的视图模型中都包含page和pageSize属性正确的名字。
欢迎任何反馈。
这个问题要求Asp.Net Core。我试图在MVC 5上使用shturm的答案而无法使其工作。我采用了相同的概念并将其改为与MVC 5一起工作。如果有人需要这个版本,我会在这里发布。我还添加了更改动作和控制器的功能。
/// <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);
}
改进Simon的答案:它可以被称为@Url.Current(new {page=42, id=5, foo=bar})
它将保留查询字符串并更新/添加提供的值。
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;
}
}