2

BACKGROUND

I'm working in ASP.NET MVC 5. I have a list of products and want to filter them by name. I have a created a small form that sits above the product list.

CODE

Here is the Razor form

@using (Html.BeginForm("Page", "Inventory", routeValues: new { showDeleted = false }, method: FormMethod.Get))
{
  <div class="row">
    <div class="col-md-12">
      <div class="form-group">
        @Html.LabelFor(model => model.Search.SearchTerm, new { @class = "form-label" })
        <div class="controls">
          @Html.EditorFor(m => m.Search.SearchTerm, new { htmlAttributes = new { @class = "form-control" } })
          @Html.ValidationMessageFor(model => model.Search.SearchTerm, "", new { @class = "text-danger" })
        </div>
      </div>
    </div>
    <div class="col-md-12">
      <button type="submit" class="btn btn-primary pull-right filter">Filter Results</button>
    </div>
  </div>
}

And here is the controller method it is suppose to hit:

public ActionResult Page(SearchViewModel search, bool showDeleted, int page = 1)
{
  var viewModel = _productService.GetPagedProducts(search, showDeleted, page);
  return View(viewModel);
}

Submitting the filter with whatever search terms breaks the application and gives the following error:

The parameters dictionary contains a null entry for parameter 'showDeleted' of non-nullable type 'System.Boolean' for method 'System.Web.Mvc.ActionResult Page(Proj.ViewModels.Shared.SearchViewModel, Boolean, Int32)' in 'Proj.Controllers.InventoryController'. An optional parameter must be a reference type, a nullable type, or be declared as an optional parameter.

I know why it is failing, it is because the showDeleted I've set up is getting ignored and thrown away! But I do not know how to fix this.

4
  • 1
    The answer is here stackoverflow.com/questions/891603/… Commented Nov 7, 2017 at 14:12
  • I think hidden field can help you, @Html.Hidden("showDeleted", false) Commented Nov 7, 2017 at 14:16
  • Thanks @lyz, I understand what to do now. :) Commented Nov 7, 2017 at 14:17
  • Create a specific route for that method - url: "Inventory/Page/{showDeleted} so that its added as a route value, not a query string and then you do not need a hidden input Commented Nov 7, 2017 at 21:00

1 Answer 1

3

Your code will generate the correct form action url with the querystring for the showDeleted parameter

action="/Inventory/Page?showDeleted=False"

But since you are using GET as the form submit method, when the form is submitted, browser will read the input element values from the form and build a querystring and append it to the form action url. This will overwrite your existing querystrings you had there.

If you want to send this in querystring with GET as the form method, you should have an input element in the form with the same name

@using (Html.BeginForm("Page", "Inventory", FormMethod.Get))
{
    @Html.EditorFor(m => m.Search.SearchTerm, 
                          new { htmlAttributes = new { @class = "form-control" } })
    <input type="hidden" name="showDeleted" value="false" />
    <button type="submit" class="btn btn-primary filter">Filter Results</button>

}
Sign up to request clarification or add additional context in comments.

2 Comments

Is that the only way? Why does my routeValues get ditched?
Because you are doing a form submit using GET which will overwrite the querystring items with the form input elements.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.