使用EntityFramework(Database First)方法的DataAnnotations

4
我有一个项目,其中包含一个数据库模型类和一个单独的EDMX EF模型。在同一个解决方案中,我有一个Web服务,它访问这个项目以及模型类。我希望模型类对前端进行数据注释以进行验证,但是没有被验证过。 为了简洁起见,模型类(在我的模型项目中)如下所示。我的Web服务引用这个类并用作接口。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization; 

[DataContract]
[MetadataType(typeof(CustomerMetaData))]
public partial class Customer
{
}

public class CustomerMetaData
{
    [DataMember]
    public object CustomerID { get; set; }

    [Required]
    [StringLength(50)]
    [DataType(DataType.EmailAddress)]
    [DataMember]
    public object Email { get; set; }
}

当我点击表单的“提交”按钮时,它会尝试添加记录并且不进行任何验证。发生运行时错误,告诉我需要提供电子邮件地址。显然,我希望这种验证在数据注释的前端完成。
如何实现这一点?
当记录尝试添加时,一个实际的运行时错误返回,表示电子邮件地址不应为空。这是正确的。数据库列需要一个值。
我以为通过在模型中具有数据注释,如果前端出现了问题,一旦表单尝试发布并且模型无效,则应在表单上显示相应的数据注释错误。我认为没有必要编写任何特定的客户端验证。模型应该为您处理。我的这种假设是否不正确?
网络上有关于如何使用 CodeFirst 进行此操作的文章,但我没有看到使用 DataBaseFirst 的文章。怎么办?
再次,我的 Customer 类如下所示。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel;
using System.Runtime.Serialization;

namespace YeagerTechModel
{
    [Serializable]
    [DataContract]
    //[MetadataType(typeof(CustomerMetaData))]
    public partial class Customer
    {
        public Customer()
        {
            this.Projects = new HashSet<Project>();
        }

        [DataMember]
        public short CustomerID { get; set; }

        [Required]
        [StringLength(50)]
        [DataType(DataType.EmailAddress)]
        [DataMember]
        public string Email { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string Company { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string FirstName { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string LastName { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string Address1 { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string Address2 { get; set; }

        [StringLength(50)]
        [DataType(DataType.Text)]
        [DataMember]
        public string City { get; set; }

        [StringLength(2)]
        [DataType(DataType.Text)]
        [DataMember]
        public string State { get; set; }

        [StringLength(10)]
        [DataType(DataType.Text)]
        [RegularExpression(@"^\d{5}(-\d{4})?$")]
        [DataMember]
        public string Zip { get; set; }

        [StringLength(12)]
        [DataType(DataType.PhoneNumber)]
        [DataMember]
        public string HomePhone { get; set; }

        [StringLength(12)]
        [DataType(DataType.PhoneNumber)]
        [DataMember]
        public string CellPhone { get; set; }

        [StringLength(100)]
        [DataType(DataType.Url)]
        [DataMember]
        public string Website { get; set; }

        [StringLength(50)]
        [DataType(DataType.EmailAddress)]
        [DataMember]
        public string IMAddress { get; set; }

        [DataMember]
        public System.DateTime CreatedDate { get; set; }

        [DataMember]
        public Nullable<System.DateTime> UpdatedDate { get; set; }

        public virtual ICollection<Project> Projects { get; set; }
    }
}

当我在客户端调试"if (ModelState.IsValid)"时,该属性始终返回true。就好像DataAnnotations根本没有被识别出来一样。调试时,我检查了ModelState对象,并且所有属性的值都在那里(在所有情况下都是空字符串,因为我试图强制出错)。我应该在电子邮件地址上得到一个isRequired错误,但我故意留空。

[HttpPost]
        public ActionResult Create(YeagerTechWcfService.Customer cust)
        {
            if (ModelState.IsValid)
            {
                try
                {
                    db.AddCustomer(cust);
                    TempData["ErrCode"] = "Customer successfully added.";
                    return RedirectToAction("Index", "Home");
                }
                catch (Exception ex)
                {
                    ViewData["ErrCode"] = "CustErr";
                    ViewBag.Error = ex.Message;
                    return View();
                }
            }
            else
                return View();
        }

你在使用什么作为你的用户界面?Silverlight?WPF? - Adam Jones
你是否在提交时使用 ModelState.IsValid 检查模型的状态? - Quintin Robinson
一旦点击提交按钮,我将转到我的控制器中处理帖子并检查“如果(ModelState.IsValid)”的方法,这通常在不应该为真时是真的。我故意制造错误,看看是否捕捉到验证。 - sagesky36
2个回答

1

不幸的是,这个注释似乎只影响渲染,而不是验证。我刚刚遇到了DataType.Url的同样问题,并且在问题Is the DataTypeAttribute validation working in MVC2?中也讨论了它(尽管是针对MVC 2 - 但问题在3中似乎相同)。

只需在其上放置一个正则表达式数据注释:

[RegularExpression(@"\w+([-+.']\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*", ErrorMessage = "Email was invalid.")]

0

稍微扩展一下这个话题,在MVC 3中你可以采用另外一种方式来使用验证。我使用的是MVC 3 + EF数据库先行生成,然后我可以在扩展/部分类Model中使用如下代码:

[MetadataType(typeof(Foobar.Metadata))]
[Serializable]
public partial class Foobar
{
    private sealed class Metadata
    {
        [Required]
        [MinLength(10)]
        public object Name { get; set; }
    }

    // Other stuff here
}

然后,当我在控制器操作中向我的小 Foobar 提供无效名称时,我可以使用 TryValidateModel 而不是 ModelState.IsValid 很好地获取验证错误(可怕的恐惧,我不绑定数据)。

        Foobar c = new Foobar();
        c.Name = "ponies";

        var y = TryValidateModel(c);
        if (!y)
        {
            foreach (var item in ModelState.Values)
            {
                foreach (var err in item.Errors)
                {
                    DoxLog.Error(err.ErrorMessage, err.Exception);
                }
            }
        }

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接