1

Edited: To remove superfluous code that may cloud the issue.

The model that is used is as follows:

public class StockProcessSearchModel : BaseSearchModel
{
    public bool IsOutOfStock { get; set; }
}

public class BaseSearchModel
{
    public bool IsExpected { get; set; }
    public bool IsInStock { get; set; }
}

Here is the only defined route:

public static void RegisterRoutes(RouteCollection routes)
{
    routes.MapRoute(
        name: "Home",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Authorisations", action = "Index", id = UrlParameter.Optional });
}

The input in the view is nothing special / just dumb html.

<input type="submit" value="Arrivals" name="DisplayArrivals" />

Now I've set the scene, the issue is a bit odd... it is giving the following querystring when I click the DisplayArrivals input, i.e. it duplicates the parameter descriptors but not the value, i.e. true then false:

http://localhost:55607/StockProcess?IsExpected=true&IsExpected=false&IsInStock=true&IsInStock=false&IsOutOfStock=false

(I should add that the parameters should be: IsExpected=true&IsInStock=true&IsOutOfStock=false)

Running Fiddler4 it tells me that the requested URL (immediately once the input is clicked) is:

http://localhost:55607/StockProcess?IsExpected=true&IsExpected=false&IsInStock=true&IsInStock=false&IsOutOfStock=false

and a break-point in the DisplayArrivals code proves that the 'duplication' is occurring before my own code does anything?!?! Which leads me to believe it must be a routing / mapping / model binding issue.

I would like to know why it is duplicating these querystring elements and more importantly how to prevent it.

EDIT: As requested here is how I generate the inputs for the IsInStock and IsExpected and IsOutOfStock:

@if (!Model.IsInStock && !Model.IsExpected && !Model.IsOutOfStock)
{
    @Html.CheckBox("IsExpected", true)
    @Html.CheckBox("IsInStock", true)
}
else
{
    @Html.CheckBoxFor(m => m.IsExpected)
    @Html.CheckBoxFor(m => m.IsInStock)
}

@Html.CheckBoxFor(m => m.IsOutOfStock)
Paul Zahra
  • 9,522
  • 8
  • 54
  • 76
  • With all of the irrelevant pieces that you did include, the one important piece you didn't include was how you're generating the `IsInStock` inputs. – StriplingWarrior Nov 03 '15 at 16:35

1 Answers1

1

The browser will only send a value for this checkbox if it is checked, so there would be no way to tell, by looking at the request, whether the checkbox was left empty or whether it simply didn't exist on the page that the user was looking at.

In order to work around this, ASP.NET inserts a hidden input saying that IsInStock is false. That way, you'll always see a value for IsInStock when the form is submitted, but if they checked the box there will be a second, true value posted, which will override the first when MVC's model binding kicks in.

It may seem odd, but I've not seen it cause any problems.

See Why does the CheckBoxFor render an additional input tag, and how can I get the value using the FormCollection? for further discussion.

Community
  • 1
  • 1
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • Ahh... very interesting... and strange... and confusing... I haven't tested the application fully but your right in that the parameter value detection on the actions I have tested seem to work fine, I was just worried seeing the duplication in the querystring. – Paul Zahra Nov 03 '15 at 16:48