I’m working with MVC3. I have a model object that I created with fluidNhibernate. It contains some value types, and some reference types of other objects also created through fluid. Lazy loading is enabled. In order for the reference types to show up as dropdown boxes on my view I have code like this:
@Html.DropDownListFor(m => m.TheObject.objId, new SelectList(Model.TheObjects, "ObjId", "ItemToDislpay"))
The controller assigns a List<TheObject> to Model.TheObjects before passing the model to the view.
The edit action in my controller:
public ViewResult Edit(int id)
{
myModelType myModel = //get my model object by id here.
myModel.TheObjects = //assign List<SomeObject> here
myModel.TheObjects2 = //assign List<SomeObject2> here
return View(myModel);
}
[HttpPost]
public ActionResult Edit(MyModelType myModel)
{
if(ModelState.IsValid)
{
....
}
else
{
//We end up here even though the validation should have succeeded
// myModel.TheObjects is null, but I don't know why
return View(myModel);
}
}
Example of attribute:
[Required(ErrorMessage = "Please enter Username")]
public virtual string UserName { get; set; }
Everything is working fine, until I add validation attributes to model properties. It doesn’t matter to which parameter I assign the attribute to. As long as I have at least one validation attribute ModelState.IsValid returns false and all the Lists that I assigned in the non-post action are null in myModel. I tried disabling client side validation but that didn’t help. What could be causing this?
I thought that the lists are supposed to be passed back, but I guess not. Still why is the validation failing if the required string exists?
It seems like the FirstName validation is failing on the server side ModelState.IsValid is saying that First Name is missing, while the model object clearly has the First Name field filled in. Here’s how my view is processing FirstName:
<div class="editor-field">
@Html.EditorFor(model => model.FirstName)
@Html.ValidationMessageFor(model => model.FirstName)
</div>
Here’s how I submit:
<input type="submit" value="Save" />
client side validation correctly catches the empty FirstName field, and stops the submit, but if I fill in the FirstName then the server side code gives me problems described above.
Ok, I figured out the problem. Thanks to Neil N with helping me along with troubleshooting ideas. First of all, the lists need to be reassigned in the postback action if the validation fails, as they don’t get kept from the view and we will need them again when the model is sent back to the view.
Now, the heart of the problem is this. One of the fields in my model is a property that’s of the same type as the model. Specifically, each user has a manager property which is also of type user. It is a reference type that’s lazy loaded by nhibernate. When I decorated the FirstName property as required for the user, this applies to the user’s manager as well. The manager object only has the UserId field set, since that is what we were binding to the dropdownlist in the view. By looking at ModelState.Values I found the error message saying that first name is required in under value index 9. The critical troubleshooting step was to now look at the ModelState.Keys collection and find the item with the same index 9, which had a value of Manager.FirstName. So, it’s the manager object that had a null FirstName, not the immediate User object that was being edited.
I guess the question now is how I should resolve this problem. Should I do my bindings differently? Do I do something on the nHibernate side? Should I do custom validation? Should I somehow specify the Manager object only to check if a valid userId is selected for the Manager? I would love to hear some suggestions. Thanks you very much for everyone’s help.