Tôi tò mò muốn tìm hiểu xem có thể ghi đè thuộc tính [Bắt buộc] đã được đặt trên mô hình hay không. Tôi chắc chắn có hầu hết là một giải pháp đơn giản cho vấn đề này, bất kỳ thí sinh nào?Có thể ghi đè thuộc tính bắt buộc trên thuộc tính trong mô hình không?
Trả lời
Phụ thuộc vào chính xác những gì bạn đang làm. Nếu bạn đang làm việc với một phân lớp, sử dụng mô hình với thuộc tính Bắt buộc làm cơ sở, bạn có thể thực hiện việc này:
Xác định lại thuộc tính với từ khóa new
, thay vì ghi đè từ khóa đó.
public class BaseModel
{
[Required]
public string RequiredProperty { get; set; }
}
public class DerivativeModel : BaseModel
{
new public string RequiredProperty { get; set; }
}
Nếu bạn chỉ muốn để ràng buộc hoặc xác nhận một mô hình, nhưng bỏ qua thuộc tính bắt buộc trong điều khiển của bạn, bạn có thể làm điều gì đó như:
public ActionResult SomeAction()
{
var model = new BaseModel();
if (TryUpdateModel(model, null, null, new[] { "RequiredProperty" })) // fourth parameter is an array of properties (by name) that are excluded
{
// updated and validated correctly!
return View(model);
}
// failed validation
return View(model);
}
Hoàn hảo, cảm ơn! –
Bạn có thể muốn thiết lập và lấy từ 'base', nếu những người khác phụ thuộc vào trường lớp cha:' get {return base.RequiredProperty; } đặt {value = base.RequiredProperty;} ' – pauloya
Rất tiếc nhưng điều đó không hiệu quả đối với tôi. Tôi có một thuộc tính [Phạm vi (0,999999)] và lớp con có [Phạm vi (0,2000)] nhưng xác thực chọn phụ huynh thay vì con – Nick
Bạn có thể sử dụng một thuộc tính xác nhận tùy chỉnh (nó có thể được bắt nguồn từ RequiredAttribute):
public class RequiredExAttribute : RequiredAttribute
{
public bool UseRequiredAttribute { get; protected set; }
public RequiredExAttribute(bool IsRequired)
{
UseRequiredAttribute = IsRequired;
}
public override bool IsValid(object value)
{
if (UseRequiredAttribute)
return base.IsValid(value);
else
{
return true;
}
}
public override bool RequiresValidationContext
{
get
{
return UseRequiredAttribute;
}
}
}
public class RequiredExAttributeAdapter : RequiredAttributeAdapter
{
public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute)
: base(metadata, context, attribute) { }
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
if (((RequiredExAttribute)Attribute).UseRequiredAttribute)// required -> return normal required rules
return base.GetClientValidationRules();
else// not required -> return empty rules list
return new List<ModelClientValidationRule>();
}
}
và sau đó regester nó trong Application_Start
sử dụng dòng mã này:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter));
phương pháp @HackedByChinese là tốt, nhưng nó có chứa một vấn đề
public class BaseModel
{
[Required]
public string RequiredProperty { get; set; }
}
public class DerivativeModel : BaseModel
{
new public string RequiredProperty { get; set; }
}
Mã này cung cấp cho bạn một lỗi xác nhận trong ModelState
NGAY CẢ nếu bạn sử dụng DerivativeModel
trên biểu mẫu, override
không hoạt động hoặc, vì vậy bạn không thể xóa Required
thuộc tính bằng cách ghi đè hoặc renewin nó, vì vậy tôi đã đến một số loại của một workaround
public class BaseModel
{
public virtual string RequiredProperty { get; set; }
}
public class DerivativeModel : BaseModel
{
[Required]
public override string RequiredProperty { get; set; }
}
public class DerivativeModel2 : BaseModel
{
[Range(1, 10)]
public override string RequiredProperty { get; set; }
}
tôi có một mô hình cơ bản với không có thuộc tính validation và lớp được thừa kế es
cảm ơn bạn đã viết về lỗi xác thực ModelState, tôi nghĩ rằng tôi đang làm điều gì sai – RMazitov
Tôi đã thử câu trả lời của Mahmoud, nhưng nó không hiệu quả đối với tôi mà không có một vài thay đổi. Thêm câu trả lời này làm câu trả lời để tôi có thể cung cấp mã đã làm trong trường hợp nó giúp người khác, nhưng tín dụng đầy đủ cho Mahmoud Hboubati - Tôi đã upvoted câu trả lời của bạn.
Trong trường hợp của tôi, tôi đã có một lớp DTO cơ bản với thuộc tính DbGeography được yêu cầu cho một dự án MVC sử dụng một EditorTemplate tùy chỉnh và DisplayTemplate cho kiểu DbGeography. Nhưng để đăng một mô hình lên một bộ điều khiển Web API, tôi muốn có các trường vĩ độ/kinh độ được thêm vào một lớp con của DTO đó, nó sẽ được sử dụng để tạo và thiết lập một cá thể của lớp DbGeography để đặt giá trị trên thuộc tính DbGeography. Vấn đề là, tôi không thể làm cho thuộc tính DbGeography không bắt buộc chỉ trên lớp con.
Khi giá trị boolean được truyền trong hàm tạo bằng cách sử dụng cách tiếp cận của Mahmoud, nó dường như không bao giờ ghi đè giá trị mặc định cho tôi. Đó có thể là vì tôi đang sử dụng API Web và đăng ký thuộc tính bằng cách sử dụng phương pháp tiếp cận nhà máy, như dưới đây (trong Global.asax.cs Application_Start phương pháp):
DataAnnotationsModelValidationFactory factory = (p, a) => new DataAnnotationsModelValidator(
new List<ModelValidatorProvider>(), new RequiredExAttribute()
);
DataAnnotationsModelValidatorProvider provider = new DataAnnotationsModelValidatorProvider();
provider.RegisterAdapterFactory(typeof(RequiredExAttribute), factory);
tôi đã phải thay đổi các lớp thuộc tính này:
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Web.Mvc;
...
public class RequiredExAttribute : RequiredAttribute
{
public bool IsRequired { get; set; }
public override bool IsValid(object value)
{
if (IsRequired)
return base.IsValid(value);
else
{
return true;
}
}
public override bool RequiresValidationContext
{
get
{
return IsRequired;
}
}
}
public class RequiredExAttributeAdapter : RequiredAttributeAdapter
{
public RequiredExAttributeAdapter(ModelMetadata metadata, ControllerContext context, RequiredExAttribute attribute)
: base(metadata, context, attribute) { }
public override IEnumerable<ModelClientValidationRule> GetClientValidationRules()
{
if (((RequiredExAttribute)Attribute).IsRequired)// required -> return normal required rules
return base.GetClientValidationRules();
else// not required -> return empty rules list
return new List<ModelClientValidationRule>();
}
}
Base Class:
[RequiredEx(IsRequired = true)]
public virtual DbGeography Location { get; set; }
Subclass:
[RequiredEx(IsRequired = false)]
public override DbGeography Location { get; set; }
[Required]
public decimal Latitude { get; set; }
[Required]
public decimal Longitude { get; set; }
Note, Tôi đã sử dụng phương pháp giống như Mahmoud đã làm ở trên đăng ký các thuộc tính trong dự án MVC của tôi:
DataAnnotationsModelValidatorProvider.RegisterAdapter(typeof(RequiredExAttribute), typeof(RequiredExAttributeAdapter));
Vâng, nó có thể sử dụng MetadataType lớp, ví dụ:
[MetadataType(typeof(Base.Metadata))]
public class Base
{
public string RequiredProperty { get; set; }
public class Metadata
{
[Required]
public string RequiredProperty { get; set; }
}
}
[MetadataType(typeof(Derived.Metadata))]
public class Derived : Base
{
public new class Metadata
{
}
}
Và kiểm tra nó:
var type = typeof(Derived);
var metadataType = typeof(Derived.Metadata);
var provider = new AssociatedMetadataTypeTypeDescriptionProvider(type, metadataType);
TypeDescriptor.AddProviderTransparent(provider, type);
var instance = new Derived();
var results = new List<ValidationResult>();
Validator.TryValidateObject(instance,
new ValidationContext(instance),
results,
true);
Debug.Assert(results.Count == 0);
Xác định "ghi đè". Bạn có nghĩa là tạo ra một phân lớp của mô hình của bạn mà tài sản đó là không cần thiết, hoặc bạn có nghĩa là làm một hành động điều khiển cụ thể không quan tâm nếu một lĩnh vực yêu cầu không được cung cấp? Bạn có lo lắng về việc xác thực phía máy khách hay chỉ phía máy chủ không? – StriplingWarrior