老读者,第一次海报。
我正在使用 ASP MVC 2 和远程验证。我有一个名为 PersonVM 的模型,AddPersonVM 和 EditPersonVM 继承自该模型。这样我就可以使用一个用户控件来处理两个子类模型之间相同的大部分 UI。
<pre><code>/// <summary> /// This class handles adding and editing people. /// </summary> [MustHaveAtLeastOneOf("HomePhoneNumber", "CellPhoneNumber", ErrorMessage="At least one of the phone numbers must be filled in.")] public abstract class PersonVM : WebViewModel { #region Reference (for Binding) /// <summary> /// Provides a list of person types, e.g. Teacher, Student, Parent. /// </summary> public IEnumerable<PersonType> ListOfPersonTypes { get { if (_listOfPersonTypes == null) { _listOfPersonTypes = Data.PersonTypes .Where(pt => pt.OrganizationID == ThisOrganization.ID || pt.OrganizationID == null) .OrderBy(pt => pt.Name).ToArray(); } return _listOfPersonTypes; } } private IEnumerable<PersonType> _listOfPersonTypes = null; /// <summary> /// Provides a list of schools the person can belong to. /// </summary> public IEnumerable<School> ListOfSchools { get { if (_listOfSchools == null) { _listOfSchools = Data.Schools .Where(s => (s.OrganizationID == ThisOrganization.ID || s.OrganizationID == null) // TODO && s.Deleted == false ) .OrderBy(s => s.Name); } return _listOfSchools; } } private IEnumerable<School> _listOfSchools = null; /// <summary> /// Provides a list of contact types, e.g. Home phone, email. /// </summary> public IEnumerable<ContactType> ListOfContactTypes { get { if (_listOfContactTypes == null) { _listOfContactTypes = Data.ContactTypes .OrderBy(ct => ct.Name); } return _listOfContactTypes; } } private IEnumerable<ContactType> _listOfContactTypes = null; /// <summary> /// Provides a list of genders. /// </summary> public IEnumerable<string> Genders { get { return new string[] { null, "Male", "Female" }; } } /// <summary> /// Returns a list of US states. /// </summary> public List<StaticData.USState> ListOfUSStates { get { return StaticData.USStates; } } #endregion /// <summary> /// Represents the current person being edited. /// </summary> public Person CurrentPerson { get; set; } #region Abstracted Required Fields /* * This is done, since address information, DOB * are not required on the panel, but are required fields here. * I tried implementing an interface called IPersonAddressRequired * with this information in it, but it didn't work. Additionally, * only one instance of [MetadataType] is allowed on a class, * so that didn't work either. */ [Required] [StringLength(100)] public string Address { get { return CurrentPerson.Address; } set { CurrentPerson.Address = value; } } [StringLength(100)] public string Address2 { get { return CurrentPerson.Address2; } set { CurrentPerson.Address2 = value; } } [Required] [StringLength(50)] public string City { get { return CurrentPerson.City; } set { CurrentPerson.City = value; } } [Required] [StringLength(50)] public string State { get { return CurrentPerson.State; } set { CurrentPerson.State = value; } } [Required] [StringLength(50)] public string Zip { get { return CurrentPerson.Zip; } set { CurrentPerson.Zip = value; } } [DataType(DataType.Date)] [Required] public DateTime? DOB { get { return CurrentPerson.DOB; } set { CurrentPerson.DOB = value; } } [Required] public string Gender { get { return CurrentPerson.Gender; } set { CurrentPerson.Gender = value; } } #endregion #region Abstracted Contact Methods /// <summary> /// When adding someone, this represents the phone number contact record. /// </summary> [Display(Name = "Home Phone Number")] [DisplayName("Home Phone Number")] [USPhoneNumber] //[Required] public string HomePhoneNumber { get; set; } /// <summary> /// When adding someone, this represents the phone number contact record. /// </summary> [Display(Name = "Cell Phone Number")] [DisplayName("Cell Phone Number")] [USPhoneNumber] //[Required] public string CellPhoneNumber { get; set; } /// <summary> /// When adding someone, this represents the email address contact record. /// </summary> [Display(Name = "Email Address")] [DisplayName("Email Address")] [Required] [UniqueEmailAddress(ErrorMessage="The email address was already found in our system, please sign in or use another email.")] [Email(ErrorMessage="The email address specified isn't an email address.")] public string EmailAddress { get; set; } #endregion ////////////////////////////// /// <summary> /// Sets the picture to be uploaded. /// </summary> public byte[] PictureData { get; set; } /// <summary> /// One of 'keep', 'remove', 'replace'. /// </summary> public string PictureAction { get; set; } } </code></pre>
我有 2 个模型继承自该模型,AddPersonVM 和 EditPersonVM。每个实现他们处理提交更改的方式略有不同。
[UniqueEmailAddress] 是我的 RemoteAttribute,用于检查现有电子邮件地址以及我遇到的问题。
这在添加某人时工作正常,但在编辑现有人员时,已存储的电子邮件地址存在于成员(member)系统中,因此无法通过验证。我想做的是存储属性值的原始值,并将其从 IsValid 检查中排除。
我的代码:
<pre><code>/// <summary> /// Checks to be sure that an entered email address is unique. /// </summary> public class UniqueEmailAddressAttribute : RemoteAttribute { /// <summary> /// Returns true if the email address specified is currently in use. /// </summary> /// <param name="emailAddress"></param> /// <returns></returns> public static bool IsEmailAddressInUse(string emailAddress) { return (Membership.FindUsersByEmail(emailAddress).Count != 0); } /////////////////////////// public UniqueEmailAddressAttribute() : base("UniqueEmailAddress", "RemoteValidation", "emailAddress") { } /////////////////////////// public override bool IsValid(object value) { // If value is null, return true, since a [Required] attribute handles required values. if (value == null) return true; // Value must be a string. if (!(value is string)) return false; // We're not checking the validity of the email address here, // the [EmailAddress] attribute handles that for us. // Check the email's uniqueness. return !IsEmailAddressInUse((string)value); } } </code></pre>
我想要的东西:
/// /// Checks to be sure that an entered email address is unique. /// public class UniqueEmailAddressAttribute : RemoteAttribute {
<p>string OriginalValue = null;</p> <pre><code> /// <summary> /// Returns true if the email address specified is currently in use. /// </summary> /// <param name="emailAddress"></param> /// <returns></returns> public static bool IsEmailAddressInUse(string emailAddress) { return (Membership.FindUsersByEmail(emailAddress).Count != 0); } /////////////////////////// public UniqueEmailAddressAttribute() : base("UniqueEmailAddress", "RemoteValidation", "emailAddress") { OriginalValue = value Found using reflection or something; } /////////////////////////// public override bool IsValid(object value) { // If value is null, return true, since a [Required] attribute handles required values. if (value == null) return true; // Value must be a string. if (!(value is string)) return false; // We're not checking the validity of the email address here, // the [EmailAddress] attribute handles that for us. if ((string)value == OriginalValue) return true; // Check the email's uniqueness. return !IsEmailAddressInUse((string)value); } } </code></pre>
有任何想法吗?截至目前,我可以将 EmailAddress 属性分别添加到 AddPersonVM 和 EditPersonVM,将字段从我的用户控件 View 中取出并添加到两个 View ,然后删除 Edit 上的属性,但这不会阻止任何人编辑他们的帐户以拥有他们想要的任何电子邮件地址。我不在乎是否需要反射来读取原始值,这很酷。
提前致谢! - 井架
请您参考如下方法:
我想你想添加具有唯一电子邮件地址的人,如果任何用户试图更改他/她正在使用的电子邮件地址,你想在他更改时检查唯一性,但你也不想检查唯一性如果他没有更改他的电子邮件地址。
所以我的建议是向 IsEmailAddressInUse 添加一个属性(字符串电子邮件, bool IsEdit)。 如果 IsEdit 为真,则检查用户登录信息中的电子邮件地址。如果不检查唯一性,则返回 true。
