Question

I was looking at an Action in an ASP.NET MVC Controller that looked about like so:

public ActionResult SomeAction( SomeClass sc, OtherClass oc ) {

    if( ModelState.IsValid ) {

        ... // do things

    }

    return View();

}

And I began to wonder what exactly ModelState.IsValid is checking. In other words, given that there are multiple parameters, what is the model? Does it validate the fields in the first parameter, sc, or does it look at all of the fields in all parameters, or what?

It seems clear that one could create a wrapper class, such as

public class WholeModel {

    public SomeObject sc {get; set;}
    public OtherClass oc {get; set;}

}

and pass that in, in which case clearly that whole thing would be the model. But do we need to do that? Why or why not, and how does the model binder determine what needs to be checked?

Was it helpful?

Solution

I set up a test with these models:

public class SimpleFormModel {

    [Required]
    public Guid aGuid { get; set; }

    [Required]
    public String aString { get; set; }

    [Required]
    public int anInt { get; set; }

    public SimpleFormModel( ) {
        this.aGuid = new Guid( "ABCD1234-ABCD-ABCD-ABCD-ABCD1234EF56" );
        this.anInt = 42;
        this.aString = "The string from the base constructor.";
    }
}

public class AdditionalFormModel {
    [Required]
    public string aString2 { get; set; }
    [Required]
    public int anInt2 { get; set; }
}

and a controller with this action:

public ActionResult MultipleParameters( SimpleFormModel modelOne, AdditionalFormModel modelTwo ) {
    if( !ModelState.IsValid ) {
        modelOne.aString = "The model isn't valid.";
    }

    return View(modelOne);
}

and also this View:

@model SimpleFormModel

@{
    ViewBag.Title = "MultipleParameters";
}

<h2>MultipleParameters</h2>

<form action="/Home/MultipleParameters" method="post">

    <input name="aGuid" type="text" value="@Model.aGuid"/><br />
    <input name="anInt" type="text" value="@Model.anInt"/><br />
    <input name="aString" type="text" value="@Model.aString"/><br />
    <br />
    <button type="submit">Update</button>

</form>

No matter what, the string shows up in the form as "The model isn't valid.", as I'm not providing the required properties for AdditionalFormModel. So, yes the model binder is checking the validity of both classes, even though the only indication that it has that an AdditionalFormModel should be included is that class's presence in the Action's parameter list.

If I remove the [Required] attributes from AdditionalFormModel's properties, then the string is updated fine and the models are considered valid. Alternatively, I can provide an explicit parameterless constructor for AdditionalFormModel that initializes each required property, like in SimpleFormModel, and that works as well.

It would still be nice to see an answer with some insight into the process that results in this behavior, but this answers whether it checks both or not.

OTHER TIPS

it will validate all parameters, even if they are nested clases.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top