18

I've created a fairly straight forward page with a check box:

@using (Html.BeginForm("MyController", "MyAction", FormMethod.Get))
{
  @Html.CheckBoxFor(x => x.MyCheckBox)
  <input type="submit" value="Go!" />      
}

The URL is populated with the MyCheckBox value twice!? As such:

MyAction?MyCheckBox=true&MyCheckBox=false

It only duplicates the value if the check box is true. If set to false it will only appear once in the query string.

The code above is simplified as I have a couple of drop downs and a textbox on the form which work fine. I don't think there's anything unusual about the code which I've left out from this question.

Has anyone had a similar issue with query string parameters being duplicated?

4 Answers 4

18

This behaviour is by design of the checkbox control. The standard HTML checkbox control passes no value if it is not checked. This is unintuitive. Instead, the ASP.Net checkbox control has 2 elements, the standard control which is visible and also a hidden control with a value of 'False'.

Therefore, if the checkbox is not checked, there will be one value passed: False.
If it is checked, there will be two values, True and False. You therefore need to use the following code to check for validity in your code:

bool checkboxChecked = Request.QueryString["MyCheckBox"].Contains("True");
Sign up to request clarification or add additional context in comments.

4 Comments

Interesting stuff, but what if you're particular about the neatness of the URL? It looks a bit daft having the parameter twice!?
It may be unsightly, but 99% of your userbase won't understand it. If you're really worried about the neatness of your URLs you could pass the data by post and create a specific route for the form.
Yes, you're right. I'll leave it as GET and stop being so pedantic. Many thanks Rory.
pay attention on .ToLower(): bool checkboxChecked = Request.QueryString["MyCheckBox"].ToLower().Contains("true");
4

Accepted answer is correct however in my case in a recent development the MVC behaviour is misleading.

The MVC Html.CheckBox(...) and Html.CheckBoxFor(...) generate an extra input of 'type=hidden' with the same ID as the checkbox control, leading to the duplicate URL parameters. I got around this problem by simply including the mark up desired as follows:

@if(checkTrue){
    <input type="checkbox" id="MyCheckBox" name="MyCheckbox" checked="checked">
}else{
    <input type="checkbox" id="MyCheckBox" name="MyCheckbox">
}

Would be better wrapped upin a helper to use in place of the MVC code so the value check is encapsulated.

As part of my application, the controller maintains sets of query parameters using both form injection and link injection using helpers in order to preserve state (of paging/filtering controls for example) when clicked to navigate within the same controller scope. As a result of this feature, the check box element is always set back to false if the standard MVC helpers are used. It's a good thing I noticed and did not waste much time on this bug.

1 Comment

Your remark is not correct, ASP.NET MVC generates an extra input of type hidden and not text when using the CheckBoxFor helpers. See stackoverflow.com/questions/2697299/…
2

In my model, I had a collection of checkboxes like so:

public class PrerequisitesViewModel
{
    public List<StudentPrerequisiteStatusViewModel> PrerequisiteStatuses { get; set; }
}

public class StudentPrerequisiteStatusViewModel
{
    public long Id { get; set; }

    public string Name { get; set; }

    public bool IsSelected { get; set; }
}

In order to get everything to bind correctly, I had to actually convert the values from the querystring and parse them manually with the following code:

// fix for how MVC binds checkboxes... it send "true,false" instead of just true, so we need to just get the true
for (int i = 0; i < model.PrerequisiteStatuses.Count(); i++)
{
    model.PrerequisiteStatuses[i].IsSelected = bool.Parse((Request.QueryString[$"PrerequisiteStatuses[{i}].IsSelected"] ?? "false").Split(',')[0]);
}

Alas, it works, but I can't believe this is necessary in MVC! Hopefully, someone else knows of a better solution.

1 Comment

i agree, it should be unnecessary in MVC! a querystring with a delimited list of the active checkboxes should suffice e.g. mycheckboxlist=1,5,6,10
2

I solve this issue with use @Html.HiddenFor

<input id="checkboxId" type="checkbox" value="true" onchange="changeCheckboxValue()">
@Html.HiddenFor(m => m.MyCheckBox, new { @id = "hiddenId" } )

<script>
  function changeCheckboxValue() {
    document.getElementById("checkboxId").value = document.getElementById("hiddenId").checked;
  }
</script>

Comments

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.