ASP.NET MVC - Getting Html.BeginForm() to remember Querystring params when submitting via GET

前端 未结 3 1231
深忆病人
深忆病人 2020-12-30 16:04

I have a form rendered via Html.BeginForm(), it exists as a component in the Master page so that it appears on every page in the application. I have done this using Html.Ren

相关标签:
3条回答
  • 2020-12-30 16:40

    A direct to call BeginForm() does keep your query string values. Any other overload tends to fail. I love the ease of using BeginForm() from my forms, but needed a way to class all my styled forms a certain way an not lose the query string values in the action.

    Here is what I came up with:

    public static MvcForm BeginNormalForm<T>(this HtmlHelper<T> htmlHelper)
    {
        var dictionary = new Dictionary<string, object> {{"class", "normal"}};
        var rvd = new RouteValueDictionary();
        if (htmlHelper.ViewContext.HttpContext != null && htmlHelper.ViewContext.HttpContext.Request != null)
        {
            foreach (var key in htmlHelper.ViewContext.HttpContext.Request.QueryString.AllKeys)
            {
                rvd[key] = htmlHelper.ViewContext.HttpContext.Request.QueryString[key];
            }
        }
        var form = htmlHelper.BeginForm(null, null, rvd, FormMethod.Post, dictionary);
        return form;
    }
    

    Seems to work well and keeps my class attribute.

    0 讨论(0)
  • 2020-12-30 16:43

    You'll need to do the hidden form field method.

    Even if you could attach the entire querystring to the end of the URL in the action attribute of the <form> tag, browsers don't pay attention to this when doing GET form submissions.

    Your method isn't too difficult; you'd want to do something like this:

    public static string QueryStringAsHidden(this HtmlHelper helper)
    {
        var sb = new StringBuilder();
        foreach (var key in HttpContext.Current.Request.QueryString.AllKeys)
        {
            if (! key.StartsWith("ProductSearch"))
                sb.Append(helper.Hidden(key, HttpContext.Current.Request.QueryString[key]));
        }
            return sb.ToString();
        }
    

    I put the .StartsWith() in there because you don't want to be on a search page and submit the search string twice (and now you can prepend paging and other search-specific variables with ProductSearch.

    Edit: PS: To get the form to post to the current page, you don't have to explicitly provide action and controller -- you can also send nulls.

    Edit2: Why even bother with a helper method? :)

    <% HttpContext.Current.Request.QueryString.AllKeys.Where(k => !k.StartsWith("ProductSearch")).ToList().ForEach(k => Response.Write(Html.Hidden(k, HttpContext.Current.Request.QueryString[k]))); %>
    

    James

    0 讨论(0)
  • 2020-12-30 17:00

    Use one of the overloads of BeginForm that takes a routeValues object or dictionary.

    Additional properties not in the route will be added as query parameters.

    0 讨论(0)
提交回复
热议问题