Nullable<int> SelectedID of the DropDownList has always a TRUE ModelState although the ID is Null

Nov 8, 2012 at 5:57 PM

Hello Jeremy,

I am using a DropDownListFor and a nullable int as the SelectedId which I send to the controller.

The ViewModel and the controller both have as parameter/property a nullable int. Thus the modelbinding can work of the mvc framework. But when I select nothing in my DropDown the Id is null. Thats fine BUT why is the ModelState TRUE when I used the Rule NotNull() or NotEmpty() ?

Nov 8, 2012 at 8:10 PM

My unit tests:

 

[Test]
        public void DeleteListReleaseViewModel_ReleaseIsNotSelected_ReturnsIsNotValid()
        {
            new DeleteReleaseListViewModelValidator().ShouldHaveValidationErrorFor(x => x.SelectedId, (int?)null);
        }

        [Test]
        public void DeleteListReleaseViewModel_ReleaseIsSelected_ReturnsIsValid()
        {
            new DeleteReleaseListViewModelValidator().ShouldNotHaveValidationErrorFor(x => x.SelectedId, new DeleteReleaseListViewModel() { SelectedId = 1 });
        }

Both tests succeed. But when I do manual testing then in the controller the ModelState is true although the SelectedId is NULL.

Why the difference in the behavior?

Coordinator
Nov 9, 2012 at 7:50 AM

Sounds like your validators are not being hooked up correctly. The fact that your test passes means that your validator is working, but if ModelState.IsValid is true, then this means the validator is not firing. Make sure that FluentValidation's MVC integration is properly configured, and that your model classes are correctly annotated with the ValidatorAttribute, eg:

[Validator(typepof(MyValidator))]
public class MyModel { 
}

public class MyValidator : AbstractValidator<MyModel> {

}

Nov 9, 2012 at 11:28 AM

This time my Model is annotated correctly with the typeof(DeleteReleaseListViewModelValidator).

I will put together a sample repro for you this weekend. Probably then I find the failure ;-)

Nov 14, 2012 at 8:37 PM

Hello Jeremy,

sorry for the late reply. Have had no time to answer earlier.

I have ripped my application to show only one delete releaseviewmodel dialog.

It is still as I said at the beginning.

1.) Using a DropDownListFor the bound SelectedId is a nullable integer.

2.) The controller also accepts a nullable integer.

3.) Initially the DropDownListFor is bound to an empty List<ReleaseViewModel>

4.) Confirming the deletion of an empty DropDownListFor and the controller gets a null value for the selectedId

5.) BUT why is the Modelstate.IsValid  TRUE ?

6.) I have setup the RuleFor().NotEmpty for the SelectedId

Here is the sample Visual Studio 2010 project. I have packed the solution as a 9,2 MB .7zip file.

http://www.sendspace.com/file/wk1si6

In order that  you can run this solution you should do an update with the nuget package manager to get missing packages

in the case it does not build.

I would be pleased if you could have a look at it and tell me what is wrong.

Thank you very much for your time.

Cheers,

BastienPascal

Coordinator
Nov 15, 2012 at 8:11 AM

The method signature of your Delete method isn't correct - it should be:

 public ActionResult Delete(DeleteReleaseListViewModel model) 

... not 

 public ActionResult Delete(int? selectedId) 

FluentValidation is invoked as part of the model binding process after MVC has copied property values to the destination object. Your validator is defined as an AbstractValidator<DeleteReleaseListViewModel>, but as your action method wasn't taking a DeleteReleaseListViewModel instance, FluentValidation had nothing to do.

Nov 15, 2012 at 5:17 PM

I agree. This problem I also had with the Data annotations.

I need a model that the model can be validated...

Thanks, then I will take my former approach wich worked and was correct then, DeleteReleaseListViewModel as param.