Quick Tip: QueryStrings with ASP.NET MVC BeginForm

July 11th, 2016

Sometimes, you need a query string from a Html.BeginForm. In this quick tip, I use a modified BeginForm to pass the current query string.

When a developer writes a form on an ASP.NET MVC web page, they may need to borrow the query string to find out what state the page is in.

Yet, with the Html.BeginForm, there isn't a way to capture the query string when it posts.

When you use ASP.NET MVC's Html.BeginForm(), it ignores the query string. What happens if I need that query string on the post back? I could pass in a query string for paging and use a variable like pageSize=100, but I need to pass in the pageNumber. I need a way to pass everything to the server.

Today, I provide a quick and easy way to pass in the query string from your forms.

Quick! To The Code!

As you know, the Html.BeginForm() is an Html Helper. So the easiest way to we can make this work is to create an extension to the extension (crazy, huh?)

The good news is we can make this really simple to put in place.

Helpers/Html/FormExtensions.cs

public static class FormExtensions
{
    public static IDisposable BeginFormQueryString(this HtmlHelper helper,
        string action, string controller, FormMethod method)
    {
        var query = helper.ViewContext.RequestContext.HttpContext.Request.QueryString;
        var routeValues = query.ToRouteValueDictionary();
        return helper.BeginForm(action, controller, routeValues, method);
    }
}

Extensions/ListExtensions.cs

public static RouteValueDictionary ToRouteValueDictionary(this NameValueCollection collection)
{
    var routeValues = new RouteValueDictionary();
    foreach (string key in collection)
    {
        routeValues[key] = collection[key];
    }
    return routeValues;
}

All we need to do is convert the query string parameters from a NameValueCollection into a RouteValueDictionary. Since this may prove useful later, I made this it's own extension method.

Since we already have an Html.BeginForm() with existing parameters, we pass in the routeValues and the rest, as they say, is history.

To use our new extension, replace your Html.BeginForm() with Html.BeginFormQueryString().

What was once this:

@using (Html.BeginForm("Index", "Home", FormMethod.Post))
{
    <div class="form-group">
        @Html.LabelFor(e => e.Vendor.VendorName, "Vendor", new { @class = "col-sm-3 control-label" })
        <div class="col-sm-9">
            @Html.TextBoxFor(e => e.Vendor.VendorName, new { @class = "form-control first", placeholder = "Enter Vendor Name" })
        </div>
    </div>
    .
    .
}

is now this:

@using (Html.BeginFormQueryString("Index", "Home", FormMethod.Post))
{
    <div class="form-group">
        @Html.LabelFor(e => e.Vendor.VendorName, "Vendor", new { @class = "col-sm-3 control-label" })
        <div class="col-sm-9">
            @Html.TextBoxFor(e => e.Vendor.VendorName, new { @class = "form-control first", placeholder = "Enter Vendor Name" })
        </div>
    </div>
    .
    .
}

Conclusion

Since ASP.NET MVC is always built with extensibility in mind, using the existing BeginForm HtmlHelper proves to be an easy solution.

Please post your comments below.