3

I have a problem with mvc DropDownList, lots of topics about that, but not one with the same problem.

I want a default selected option for my DropDownList, but i also need additional option for "all" items selection.

So my controller is binding default value of 2 to dropdown

 public ActionResult Index(int? All = 2){ ...

In cshtml i have

 @Html.DropDownList("All","All items")

All list is filled like this

 ViewData["All"] = new SelectList(CommonLists.property_types.Select(x => new { v = x.Value, t = x.Key.ToLower() }), "v", "t", All);

property_types

  public static Dictionary<string, int> property_types = new Dictionary<string, int>() { 
    { "House", 1 }, { "Flat", 2 }, { "Garden", 3 }

So it should work like this

  • when first entered the default selected value is 2, equals to "flat", only "flat" items are displayed (works)
  • user can change it to other option from the list (works)
  • user can change to view all items at once no matter the category selecting "All items" (this is not working)

I have assumed it should work, but to my surprise, when i select "All items" mvc does not return null it just returns the default int value 2, so basically no way to query for all items.

Is this suppose to work like that? The auto generated "All items" is empty value so i assumed mvc would translate it to null, but it is not.

How to fix this?

1 Answer 1

4
+100

The problem isn't that null isn't returned by the POST, but that null IS returned by the POST.

Since your action has a default value of 2. When the action is receiving null the it's initializing the variable with the default value, in that case 2

public ActionResult Index(int? All = 2)

What you want to do it to be able to differentiate between "All items" and the default behavior of the app. It that case, the default behavior is to show only flats

You can achieve that goal by using building the "All items" inside of your controller.

public ActionResult Index(int? All = 2)
{
    var propertyTypesSelectList = new SelectList(property_types.Select(x => new {v = x.Value, t = x.Key.ToLower()}), "v", "t", All).ToList();
    propertyTypesSelectList.Insert(0, new SelectListItem() { Value = "0", Text = "All items"});

    ViewData["All"] = propertyTypesSelectList;
    return View();
}

And changing your View to this

@Html.DropDownList("All") 
Sign up to request clarification or add additional context in comments.

5 Comments

Was suspecting it will be this case, MVC should be more intelligent on this, if they provide an option for adding default option it should return null if it has empty value and not my default value of 2, especially if it is nullable int. Maybe it is good idea to fix it using custom parameter binder, will see.
This is not a problem with MVC. You are giving the null value a double meaning. null From POSTback is means "All Items", while the initial null meant "take de default value". If you remove the = 2 to your Action. Then your previous code will work, but the default value is "All items" and not "Flat"
Yes it is an MVC problem. If i don't provide any value, meaning no form POST "All" field is send it should be 2, but if i select "All items" a form POST field "All" of value empty is send, the controller should get a null value then. It is not a problem of double meaning, it is a problem that mvc can't recognize between no POST field in request and a POST field but with empty value, it is two different things. The truth is it should work the most intuitive way, just as simple as i've shown in my question, no workarounds needed, but it won't.
If you look in the DefaultModelBinder, you will see that the value received is null. It's the .Net framework that "change" that null to 2
Will check that and try to do something about it.

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.