2

I have a view similarly declared on this link.

<div id="personSection">
<!-- We have more than one personspecificmodel -->
 @if (Model.PersonSpecificModels != null)
 {
     for (var i = 0; i < Model.PersonSpecificModels.Count; i++)
     {            
         <div>
             <div class="formColumn2">@Html.EditorFor(x => x.PersonSpecificModels[i].childProperty1)</div>
             <div class="formColumn2">@Html.EditorFor(x => x.PersonSpecificModels[i].childProperty2)</div>
         </div>
     }
 }
 else
 {
     <!-- This is the form for the new user -->
         <div>
             <div class="formColumn2">@Html.EditorFor(x => x.PersonSpecificModels.childProperty1)</div>
             <div class="formColumn2">@Html.EditorFor(x => x.PersonSpecificModels.childProperty2)</div>
         </div>        
 }

The challenge that I have is that I have a model that have the following declaration:

public class PersonModel {
    // Some properties, annotations, etc
    [Required(ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "ValidationErrorRequiredField")]
    [StringLength(100, ErrorMessageResourceType = typeof(Messages), ErrorMessageResourceName = "StringLength")]
    public string property1 { get; set; }
    public List<PersonSpecificModel> PersonSpecificModels { get; set; }

    public class PersonSpecificModel {
        // Some declarations further
        public string childProperty1 { get; set; }
        public int childProperty2 { get; set; }
    }
}

Before, there is a 1:1 relationship between PersonModel and PersonSpecificModel. One of the things that we need to do is to allow multiple PersonSpecificModels. Think of having a user having different bank account details.

The code that handles submit of this view is this:

    [HttpPost, ValidateInput(false)]
    public new ActionResult MyAction(PersonModel model)
    {      
        if (ModelState.IsValid) // multiple PersonSpecificModels fail here
        {
        }
    }

There is no issue when I am adding a new person to the model. The challenge that I have right now is that when a user have more than 1 PersonSpecificModels, the validation fails as it can't see properly the collection.

[Question] Would there be any way to properly validate the collection with the existing model definition? The model validation fails on the first line alone.

Community
  • 1
  • 1
Patrick
  • 318
  • 3
  • 13
  • Not clear what your question is. Does `PersonModel` contain a property `List`? How are you generating the view for each `PersonSpecificModel`? –  Feb 25 '15 at 01:00
  • Yes, there is a property that contains List. The view is generated similar to the link declared above. – Patrick Feb 25 '15 at 01:02
  • So what problem are you having (and you need to include the relevant code in your question, not a link) –  Feb 25 '15 at 01:04
  • I have modified the question and made it more specific and clear. The question is how can I possibly validate the multiple PersonSpecificModel using the old 1:1 model? In the previous implementation, 1:1 relationship works well but not 1:many. – Patrick Feb 25 '15 at 01:32
  • As an aside, `(Model.PersonSpecificModels != null)`; `IEnumerable` should be declared as an empty set (rather than null). _(See http://stackoverflow.com/questions/1969993/is-it-better-to-return-null-or-empty-collection)_ – Brad Christie Feb 25 '15 at 01:37
  • Still not clear. The first part of view (`if` block) suggests property `PersonSpecificModels` is a collection (but you model does not include a collection property, or indeed any property named `PersonSpecificModels`). The second part of the view (`else` block) suggests property `PersonSpecificModels` is an object - it cant be both. You need to show the real model definition. –  Feb 25 '15 at 01:41
  • @BradChristie that is noted. – Patrick Feb 25 '15 at 01:52
  • @StephenMuecke I edited it again to make it clear - this latest edit i think shows that there's a collection of type PersonSpecificModel. The question now is that now that I have multiple copies of the PersonSpecificModel in my collection, how would I be able to validate them accordingly to the old model? I am not sure if I am missing on something regarding this one. – Patrick Feb 25 '15 at 01:53
  • Still don't understand the problem. First it needs to be a property not a field `public List PersonSpecificModels { get; set; }` and if you have only one `PersonSpecificModel` object, add it to the collection and use the `for` loop as your are doing. You don't need `@if (Model.PersonSpecificModels != null)` - it should never be null` and the `else` block is not required at all. –  Feb 25 '15 at 02:04
  • I missed that one - yes that's a property. The reason why it does have an if-else is because it reuses the same View for 'Add' and 'Edit'. If the action is 'Add', then Model.UserInformations is empty. If there's at least 1, then Model.UserInformations is not empty. Validation works well if the action is 'Add'. I am wondering how would I extend that validation now that the reference to the model includes an index. – Patrick Feb 25 '15 at 02:17
  • I suspect your wanting to dynamically add (and perhaps delete) new `PersonSpecificModels` in the view, in which case you need javascript/jquery to add new elements to the DOM. [This answer](http://stackoverflow.com/questions/28019793/submit-same-partial-view-called-multiple-times-data-to-controller/28081308#28081308) gives some options for doing that. –  Feb 25 '15 at 02:29
  • Not really. If you would look at the code, the UserInformations count has been established based on the number of records in the DB. I just wanted to extend the validation done on a single record (as in Creating a New PersonSpecifcModel data) to the multiple PersonSpecificModel. What happens when I hit on "Save" and the controller performs the action, ModelState.IsValid becomes false. – Patrick Feb 25 '15 at 02:34
  • You do not need the else block. If your wanting to 'add' one item only, then add that item (a default `PersonSpecifcModel` object) to the collection and use the `for` loop. –  Feb 25 '15 at 02:39
  • I am actually asking how to validate a list of PersonSpecificModel items similar to that of a single item. If I perform an 'Add', validation works. Now, that I have multiple PersonSpecificModel, I want the validation work to work similarly. The validation no longer works because the Validation looks for Model.PersonSpecificModel.Property1 and not Model.PersonSpecificModel[x].Property1. – Patrick Feb 25 '15 at 02:46
  • It does work. If you have `@Html.TextBoxFor(x => x.PersonSpecificModels[i].childProperty1)` and `@Html.ValidationMessageFor(x => x.PersonSpecificModels[i].childProperty1)` And what do you mean it looks for `Model.PersonSpecificModel.Property1`? `PersonSpecificModel` is typeof `List` which does not have a property `Property1` (that would throw an exception!) –  Feb 25 '15 at 03:16

1 Answers1

1

You can validate each of them manually and handle as you see fit:

ICollection<ValidationResult> results = new List<ValidationResult>();

bool valid =
    Validator.TryValidateObject(obj, new ValidationContext(obj), results, true);

// results is an out collection parameter containing error messages...
BrunoLM
  • 97,872
  • 84
  • 296
  • 452