ASP.NET MVC 2模型封装在ViewModel验证中

时间:2010-04-01 14:12:22

标签: asp.net-mvc validation

我正在尝试验证在ASP.NET MVC 2中工作,但没有太大成功。

我有一个包含大量字段的复杂类。 (不要问 - 这是真实情况下最佳实践无法触及的)这通常是我的模型,是LINQ-to-SQL生成的类。

因为这是生成的代码,所以我根据http://davidhayden.com/blog/dave/archive/2009/08/10/AspNetMvc20BuddyClassesMetadataType.aspx创建了一个MetaData类。

public class ConsultantRegistrationMetadata
{

    [DisplayName("Title")]
    [Required(ErrorMessage = "Title is required")]
    [StringLength(10, ErrorMessage = "Title cannot contain more than 10 characters")]       
    string Title { get; set; }

    [Required(ErrorMessage = "Forename(s) is required")]
    [StringLength(128, ErrorMessage = "Forename(s) cannot contain more than 128 characters")]
    [DisplayName("Forename(s)")]
    string Forenames { get; set; }
       // ...

我已将此附加到我生成的类的部分类中:

[MetadataType(typeof(ConsultantRegistrationMetadata))]
public partial class ConsultantRegistration
{
   // ...

因为我的表单很复杂,所以它有很多依赖项,例如SelectLists等,我已将其封装在ViewModel模式中 - 并将ConsultantRegistration模型作为属性包含在内:

public class ConsultantRegistrationFormViewModel
{
    public Data.ConsultantRegistration ConsultantRegistration { get; private set; }

    public SelectList Titles { get; private set; }
    public SelectList Countries { get; private set; }
 // ...

所以它本质上是ViewModel => Model

我的观点有:

    <p>
        <%: Html.LabelFor(model => model.ConsultantRegistration.Title) %>
        <%: Html.DropDownListFor(model => model.ConsultantRegistration.Title, Model.Titles,"(select a Title)") %>
        <%: Html.ValidationMessage("Title","*") %>
    </p>

    <p>
        <%: Html.LabelFor(model => model.ConsultantRegistration.Forenames) %>
        <%: Html.TextBoxFor(model => model.ConsultantRegistration.Forenames) %>
        <%: Html.ValidationMessageFor(model=>model.ConsultantRegistration.Forenames) %>
    </p>

问题是,元数据类上的验证属性无效。我尝试通过接口来做,但也没有效果。我开始认为原因是因为我将我的模型封装在ViewModel中。

我的控制器(创建动作)如下:

[HttpPost]
        public ActionResult Create(Data.ConsultantRegistration consultantRegistration)
        {
            if (ModelState.IsValid) // this is always true - which is wrong!!
            {
                try
                {

                    consultantRegistration = ConsultantRegistrationRepository.SaveConsultantRegistration(consultantRegistration);

                    return RedirectToAction("Edit", new { id = consultantRegistration.ID, sectionIndex = 2 });
                }
                catch (Exception ex)
                {
                    ModelState.AddModelError("CreateException",ex);
                }
            }

            return View(new ConsultantRegistrationFormViewModel(consultantRegistration));

        }

如注释中所述,尽管Validaiton注释的字段无效,但ModelState.IsValid属性始终返回true。 (Forenames是一个关键的例子)。

我错过了一些明显的东西 - 考虑到我是MVC的新手吗?我正在追踪Jon Galloway在http://www.asp.net/learn/mvc-videos/video-10082.aspx演示的机制。

(我知道这与ASP.NET MVC Model/ViewModel Validation类似,但该帖似乎谈到了xVal。我不知道那是什么,并怀疑它适用于MVC 1)

1 个答案:

答案 0 :(得分:1)

我一直试图让这项工作有一段时间。根据你所包含的代码,我认为你做得对。

我认为问题在于javascript验证器应该被“发送”到页面中。关于这个问题的SO还有其他一些问题,我认为它们中的任何一个都没有提供全面的解决方案。据我所知,MVC2 RC仍然破碎。

更新:

如果在将属性应用于发出的代码时有效,请看一下:

When using Data Annotations with MVC, Pro and Cons of using an interface vs. a MetadataType

可能是MetadataType属性不起作用。如果您按照上述问题中的建议尝试界面,它是否有效?

另外,另一个问题是:MetadataType and client validation in ASP.NET MVC 2

那是一个相当新的,并确认这仍然是MVC2中的一个错误。