Visual studio 使用实体数据模型自定义验证MVC 3

Visual studio 使用实体数据模型自定义验证MVC 3,visual-studio,asp.net-mvc-3,entity-framework,validation,Visual Studio,Asp.net Mvc 3,Entity Framework,Validation,我正在使用MVC3进行一个项目。我首先创建了一个数据库(带有必要的约束,如PK和FK),并使用ADO.NET实体数据模型将该数据库添加到我的WebApplicatione中。一切似乎都很好,但我无法灵活地进行验证。这里有一些代码来澄清我的问题 编辑:添加视图+正确的模型。此版本未导入数据库,但结果相同 --模型---- namespace CustomValidation.Models { 公共类人物:IValidatableObject { 公共int Id{get;set;} [必

我正在使用MVC3进行一个项目。我首先创建了一个数据库(带有必要的约束,如PK和FK),并使用ADO.NET实体数据模型将该数据库添加到我的WebApplicatione中。一切似乎都很好,但我无法灵活地进行验证。这里有一些代码来澄清我的问题


编辑:添加视图+正确的模型。此版本未导入数据库,但结果相同


--模型----

namespace CustomValidation.Models
{
公共类人物:IValidatableObject
{   
公共int Id{get;set;}
[必需]
公共字符串名{get;set;}
[必需]
公共字符串LastName{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
if(String.IsNullOrEmpty(FirstName))
{
var field=new[]{“FirstName”};
返回新的ValidationResult(“Firstname不能为null”,字段);
}
}
}
}
命名空间CustomValidation.Models
{
公共类地址:IValidatableObject
{
公共int Id{get;set;}
[必需]
公共字符串Streetname{get;set;}
[必需]
公共字符串Zipcode{get;set;}
[必需]
公共字符串City{get;set;}
[必需]
公共字符串国家{get;set;}
公众人物{get;set;}
公共IEnumerable验证(ValidationContext ValidationContext)
{
if(String.IsNullOrEmpty(Streetname))
{
var field=new[]{“Streetname”};
返回新的ValidationResult(“Streetname不能为空”,字段);
}
}
}
}
公共类主模型
{
公共列表地址{get;set;}
公众人物{get;set;}
}
}
命名空间CustomValidation.Models
{
公共类DBEntities:DbContext
{
公共数据库集人物{get;set;}
公共数据库集地址{get;set;}
}
}
----控制器----

namespace CustomValidation.Controllers
{
公共类HomeController:控制器
{
公共行动结果索引()
{
主模型=新的主模型();
Model.Person=newperson();
Model.address=新列表();
Model.Address.Add(新地址());
Model.Address.Add(新地址());
返回视图(模型);
}
[HttpPost]
公共行动结果指数(主模型)
{
DBEntities _db=新的DBEntities();
if(TryValidateModel(Model.Person))
{
_db.People.Add(Model.Person);
_db.SaveChanges();
}
其他的
{
返回视图(模型);
}
for(int i=0;i
以下是我的看法:

@model CustomValidation.Models.MasterModel
@{
ViewBag.Title = "Index";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.FirstName)
@Html.EditorFor(m => Model.Person.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.LastName)
@Html.EditorFor(m => Model.Person.LastName)
</div>

</fieldset>
for (int i = 0; i < Model.Addressess.Count; i++)
{
<fieldset>
    <legend>Address</legend>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Streetname)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Addressess[i].Streetname)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Streetname)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Zipcode)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].Zipcode)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Zipcode)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].City)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].City)
        @Html.ValidationMessageFor(model => Model.Addressess[i].City)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Country)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].Country)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Country)
    </div>

</fieldset>

}
    <p>
        <input type="submit" value="Create" />
    </p>
}
@model CustomValidation.Models.MasterModel
@{
ViewBag.Title=“Index”;
}
创造
@使用(Html.BeginForm()){
@Html.ValidationSummary(true)
人
@LabelFor(m=>Model.Person.FirstName)
@EditorFor(m=>Model.Person.FirstName)
@LabelFor(m=>Model.Person.LastName)
@EditorFor(m=>Model.Person.LastName)
for(int i=0;imodel.address[i].Streetname)
@Html.EditorFor(model=>model.address[i].Streetname)
@Html.ValidationMessageFor(model=>model.address[i].Streetname)
@Html.LabelFor(model=>model.address[i].Zipcode)
@Html.EditorFor(model=>model.address[i].Zipcode)
@Html.ValidationMessageFor(model=>model.address[i].Zipcode)
@Html.LabelFor(model=>model.address[i].City)
@EditorFor(model=>model.address[i].City)
@Html.ValidationMessageFor(model=>model.address[i].City)
@Html.LabelFor(model=>model.address[i].Country)
@Html.EditorFor(model=>model.address[i].Country)
@Html.ValidationMessageFor(model=>model.address[i].Country)
}

}
问题(我在调试类似的东西时注意到)是,在请求进入我的操作之前,MVC首先为您的集合运行验证器。因此,如果我在表单中只填写了Person,则在验证模型时。Person只返回false(我猜是因为地址的必填字段)所以它会回到我的观点

我需要一些变通方法,让我能够决定要在操作中验证集合的哪些实例

在网上搜索了很长时间后,我一直找不到任何解决方案

我希望有人能帮助我


另外,我是Visual Studio和MVC 3的新手,所以请不要对我太苛刻:)

为了验证返回到您的操作的模型的子模型,您需要将
TryValidateModel
应用到特定的子模型,并使用包含模型前缀的重载。如果查看生成的HTML,您将请参阅Person字段的前缀为
Person
,第一个地址字段的前缀为
Addressess[0]
,第二个地址字段的前缀为
Addressess[1]

此外,在调用TryValidateModel之前,必须清除所有模型错误(否则现有错误将导致TryValidateModel返回false)

请执行以下操作:

[HttpPost]
public ActionResult Index(MasterModel model)
{
    var reloadView = true;

    // clear any existing errors
    foreach (var key in ModelState.Keys)
        ModelState[key].Errors.Clear();

    if (TryValidateModel(model.Person, "Person"))   
    {   
        _db.People.Add(model.Person);   
        _db.SaveChanges();   
        reloadView = false;

        for (var i = 0; i < model.Addressess.Count(); i++)
        {
            foreach (var key in ModelState.Keys)
                ModelState[key].Errors.Clear();

            if (TryValidateModel(model.Addressess[i], "Addressess[" + i.ToString() + "]"))
            {
                **// UPDATED CODE**
                // add Person to Address model
                model.Addressess[i].Person = model.Person;

                _db.Addressess.Add(model.Addressess[i]);   
                _db.SaveChanges();   
            }
        }
    }

    if (reloadView)
    {
        // clear and re-add all errors
        foreach (var key in ModelState.Keys)
            ModelState[key].Errors.Clear();

        TryValidateModel(model);
        return View(model);
    }
    else
    {
        // go to some other view
    }
}
[HttpPost]
公共行动结果
@model CustomValidation.Models.MasterModel
@{
ViewBag.Title = "Index";
}

<h2>Create</h2>

@using (Html.BeginForm()) {
@Html.ValidationSummary(true)
<fieldset>
<legend>Person</legend>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.FirstName)
@Html.EditorFor(m => Model.Person.FirstName)
</div>
<div class="editor-label">
@Html.LabelFor(m => Model.Person.LastName)
@Html.EditorFor(m => Model.Person.LastName)
</div>

</fieldset>
for (int i = 0; i < Model.Addressess.Count; i++)
{
<fieldset>
    <legend>Address</legend>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Streetname)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => model.Addressess[i].Streetname)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Streetname)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Zipcode)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].Zipcode)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Zipcode)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].City)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].City)
        @Html.ValidationMessageFor(model => Model.Addressess[i].City)
    </div>

    <div class="editor-label">
        @Html.LabelFor(model => Model.Addressess[i].Country)
    </div>
    <div class="editor-field">
        @Html.EditorFor(model => Model.Addressess[i].Country)
        @Html.ValidationMessageFor(model => Model.Addressess[i].Country)
    </div>

</fieldset>

}
    <p>
        <input type="submit" value="Create" />
    </p>
}
[HttpPost]
public ActionResult Index(MasterModel model)
{
    var reloadView = true;

    // clear any existing errors
    foreach (var key in ModelState.Keys)
        ModelState[key].Errors.Clear();

    if (TryValidateModel(model.Person, "Person"))   
    {   
        _db.People.Add(model.Person);   
        _db.SaveChanges();   
        reloadView = false;

        for (var i = 0; i < model.Addressess.Count(); i++)
        {
            foreach (var key in ModelState.Keys)
                ModelState[key].Errors.Clear();

            if (TryValidateModel(model.Addressess[i], "Addressess[" + i.ToString() + "]"))
            {
                **// UPDATED CODE**
                // add Person to Address model
                model.Addressess[i].Person = model.Person;

                _db.Addressess.Add(model.Addressess[i]);   
                _db.SaveChanges();   
            }
        }
    }

    if (reloadView)
    {
        // clear and re-add all errors
        foreach (var key in ModelState.Keys)
            ModelState[key].Errors.Clear();

        TryValidateModel(model);
        return View(model);
    }
    else
    {
        // go to some other view
    }
}