ASP.NET MVC - 创建操作链接保留查询字符串

问题描述 投票:3回答:3

我目前正在为ASP.NET Core MVC编写自己的分页列表。

我在创建以下内容时遇到了困难

我想创建一个UrlHelper扩展方法:Url.PageLink(int page,int pageSize)

在该扩展方法中,我想返回一个链接,该链接重用控制器,操作,查询字符串的所有当前值,此外它还应该在查询字符串中添加/更新页面,pageSize值。

问题:从哪里获取UrlHelper对象中的当前控制器和操作?重建查询字符串的最佳方法是什么?我可以在这里看到url.ActionContext.HttpContext.Request.QueryString ...但我真的必须手动重建它吗?或者是否存在类似AddQueryStringValue(int key,object value)的东西?

非常感谢提前!!!西蒙

c# asp.net-mvc razor asp.net-core asp.net-core-mvc
3个回答
1
投票

现在这样做了:

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属性正确的名字。

欢迎任何反馈。


1
投票

这个问题要求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);
    }

0
投票

改进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;
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.