MVC3验证属性打破了模型

时间:2011-09-30 21:22:44

标签: asp.net-mvc asp.net-mvc-3

我正在使用MVC3。我有一个我用fluidNhibernate创建的模型对象。它包含一些值类型,还有一些通过流体创建的其他对象的引用类型。延迟加载已启用。为了使引用类型在我的视图中显示为下拉框,我的代码如下:

@Html.DropDownListFor(m => m.TheObject.objId, new SelectList(Model.TheObjects, "ObjId", "ItemToDislpay"))

在将模型传递给视图之前,控制器会将List<TheObject>分配给Model.TheObjects

我的控制器中的编辑操作:

    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);
            }
        }

属性示例:

[Required(ErrorMessage = "Please enter Username")]
public virtual string UserName { get; set; }

一切正常,直到我将验证属性添加到模型属性。我将属性分配给哪个参数无关紧要。只要我至少有一个验证属性ModelState.IsValid返回false,并且我在非post操作中指定的所有列表在myModel中都为null。我尝试禁用客户端验证,但这没有帮助。可能导致这种情况的原因是什么?

我认为列表应该被传回,但我猜不是。如果所需的字符串存在,为什么验证失败呢?

似乎FirstName验证在服务器端失败ModelState.IsValid表示缺少名字,而模型对象显然填写了First Name字段。以下是我的视图处理FirstName的方式:

    <div class="editor-field">
        @Html.EditorFor(model => model.FirstName)
        @Html.ValidationMessageFor(model => model.FirstName)
    </div>

以下是我的提交方式:

<input type="submit" value="Save" />

客户端验证正确捕获空的FirstName字段,并停止提交,但如果我填写FirstName,那么服务器端代码会给我上述问题。

3 个答案:

答案 0 :(得分:1)

您的问题仍然有点模糊,但这可能会对您的问题有所帮助。

将此属性添加到模型中:

[MetadataType(typeof(MyModelTypeMeta))]
public partial class MyModelType
{
    ...
}

并添加MyModelTypeMeta类,如下所示,添加一个字段以匹配每个字符串属性,并告诉模型绑定器让空字符串值保持为空而不是将它们更改为null,这通常会导致字符串属性失败绑定(因为你没有在模型中将它们定义为可为空)

public class MyModelTypeMeta
{
    [DisplayFormat(ConvertEmptyStringToNull=false)]
    public string myProperty;
}

答案 1 :(得分:0)

看看你添加了什么,我打赌问题是空的List&lt; someObject&gt;当它至少应该是一个空列表时为null。 (对于List&lt; someObject2&gt;属性也是如此)

在MyModelType的构造函数中,您应该将它们初始化为空列表,以便绑定器不会将它们视为null。类似的东西:

public MyModelType()
{
    myModel.TheObjects = new List<SomeObject>();
    myModel.TheObjects2 = new List<SomeObject2>();
    ...
}

答案 2 :(得分:0)

好的,我发现了问题。感谢Neil N帮助我解决问题。首先,如果验证失败,则需要在回发操作中重新分配列表,因为它们不会从视图中保留,并且在将模型发送回视图时我们将再次需要它们。

现在,问题的核心是这个。我模型中的一个字段是与模型类型相同的属性。具体而言,每个用户都具有管理员属性,该属性也是用户类型。它是由nhibernate延迟加载的引用类型。当我根据用户的需要修饰FirstName属性时,这也适用于用户的管理器。 manager对象只有UserId字段集,因为这是我们绑定到视图中的下拉列表。通过查看ModelState.Values,我发现错误消息说在值索引9下需要名字。关键的故障排除步骤现在是查看ModelState.Keys集合并找到具有相同索引9的项目,该项目具有Manager.FirstName的值。因此,它是具有空FirstName的管理器对象,而不是正在编辑的直接User对象。

我想现在的问题是我应该如何解决这个问题。我应该以不同方式进行绑定吗?我是否在nHibernate方面做了些什么?我应该custom validation吗?我应该以某种方式指定Manager对象,以检查是否为Manager选择了有效的userId?我很想听听一些建议。非常感谢大家的帮助。