【问题标题】:Is it possible to use ModelState against a nested Model in ASP.NET MVC3?是否可以对 ASP.NET MVC3 中的嵌套模型使用 ModelState?
【发布时间】:2014-01-29 17:11:39
【问题描述】:

我有一个嵌套模型,即:

MySuperClass
  ConfigClass
  DataClass

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

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

我在视图中使用 MySuperClass.ConfigClass 属性。

我在 DataClass 属性(例如“必需”)上有 Validation DataAnnotations。

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

    [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)

【问题讨论】:

  • 你能告诉我们这些类的具体代码吗?

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


【解决方案1】:

嵌套对象被验证,只要它们不为空,因此您只需要确保Model.DataClassDataClass 的一个实例而不是空。最简单的方法是在 MySuperClass 的构造函数中:

public MySuperClass()
{
     DataClass = new DataClass();
}

【讨论】:

  • 谢谢。我实际上是在更新 ctor 中的实例。此外,如果“DataClass”为空,那么我的 EditorFor 字段中会出现空值,而我不是。我得到了进来的值,我可以编辑和保存它们,它们保存得很好,除了一切都被视为有效。就好像验证器只检查“MySuperClass”而不是“MySuperClass.DataClass”。我正在使用基于“必需”的验证器进行测试。再次感谢。
  • ModelState.IsValid 是否真的返回 true,或者您是否只允许提交没有必填字段的表单?
  • 现在发现返回 False,所以工作正常。不太确定我做了什么,可能是修复另一个错误的结果。但很高兴知道我可以使用它。
【解决方案2】:

我在这样的一个项目中解决了与您相同的问题,您需要创建过滤器并将其用于从操作发送到视图以及从视图发布到操作(发布操作):

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

最后,视图与您使用的常规形式相同。

【讨论】:

  • 谢谢你,但现有的嵌套类确实有效。
【解决方案3】:

嵌套模型应该在 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>

【讨论】:

  • 感谢您的全面努力。在 Chris 的帮助和我的错误修复下,我差不多到了那里,而且他来得更快。
猜你喜欢
  • 1970-01-01
  • 2011-11-13
  • 1970-01-01
  • 1970-01-01
  • 2011-09-27
  • 2023-03-08
  • 2011-04-13
  • 1970-01-01
  • 2014-02-20
相关资源
最近更新 更多