是否可以对ASP.NET MVC3中的嵌套模型使用ModelState?

时间:2014-01-29 17:11:39

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

我有一个嵌套模型,即:

MySuperClass
  ConfigClass
  DataClass

我将“MySuperClass”传递给包含Form的View。此表单上的元素使用LINQ进行模型绑定,即:

EditorFor(model=>model.DataClass.Name)
EditorFor(model=>model.DataClass.DateOfBirth)   

我在View中使用MySuperClass.ConfigClass属性。

我在DataClass属性上有Validation DataAnnotations,例如“Required”。

我回到控制器中的表单处理程序:

    [HttpPost]
    public ActionResult Index(MySuperClass mySC, string unused = "") 

    //ModelState not firing.... on empty required columns
    if (ModelState.IsValid))

我认为“mySuperClass”就像一个ViewModel。

如何让验证工作?

修改

还使用验证助手:

@Html.EditorFor(model=>model.DataClass.Name)
@Html.ValidationMessageFor(model => model.DataClass.Name)

3 个答案:

答案 0 :(得分:1)

嵌套对象进行验证,只要它们不为空,因此您只需要确保Model.DataClassDataClass的实例而不是null。最简单的方法是在MySuperClass

的构造函数中
public MySuperClass()
{
     DataClass = new DataClass();
}

答案 1 :(得分:1)

我在我的一个项目中解决了和你一样的麻烦,你需要创建过滤器并在从动作发送到视图以及从视图到动作发布(后期动作)时使用它:

public abstract class ModelStateBase : ActionFilterAttribute
{
    protected static readonly string Key = typeof(ModelStateBase).FullName;
}

public class OnGetMetaData : ModelStateBase
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        if (!filterContext.Controller.ViewData.ModelState.IsValid)
        {
            if ((filterContext.Result is RedirectResult) || (filterContext.Result is RedirectToRouteResult))
            {
                filterContext.Controller.TempData[Key] = filterContext.Controller.ViewData.ModelState;
            }
        }

        base.OnActionExecuted(filterContext);
    }
}

public class OnPostMetaData : ModelStateBase
{
    public override void OnActionExecuted(ActionExecutedContext filterContext)
    {
        var modelState = filterContext.Controller.TempData[Key] as ModelStateDictionary;

        if (modelState != null)
        {
            if (filterContext.Result is ViewResult)
            {
                filterContext.Controller.ViewData.ModelState.Merge(modelState);
            }
            else
            {
                filterContext.Controller.TempData.Remove(Key);
            }
        }
        base.OnActionExecuted(filterContext);
    }
}

在获取和发布操作中,您可以这样做:

  [OnPostMetaData]
    public ActionResult Index()
    {
        return View();
    }


    [HttpPost, OnGetMetaData]
    public ActionResult Index(MySuperClass mySuperClass)
    {
        if (ModelState.IsValid)
        {
            //do something
        }

        return View();
    }

最后视图与您使用的常规表单相同。

答案 2 :(得分:1)

嵌套模型应该适用于MVC 3.请尝试使用此示例。

控制器&类

public class HomeController : Controller
{
    public ActionResult IndexNew()
    {
        Sample obj = new Sample() {MyTest=new Test() };
        return View(obj);
    }

    [HttpPost]
    public ActionResult IndexNew(Sample test)
    {            
        return View(test);
    }
}

public class Sample
{
    public Test MyTest { get; set; }
}
public class Test
{
    [Required]
    public string Name { get; set; }
}

查看零件

    @model MvcApplication2.Controllers.Sample

    @{
        ViewBag.Title = "IndexNew";
    }

    <h2>IndexNew</h2>

    <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script>
    <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script>

    @using (Html.BeginForm()) {
        @Html.ValidationSummary(true)
        <fieldset>
            <legend>Sample</legend>
            @Html.TextBoxFor(e => e.MyTest.Name);

            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>
    }

    <div>
        @Html.ActionLink("Back to List", "Index")
    </div>