Vô hiệu hóa thuộc tính xác thực bắt buộc trong các trường hợp nhất định


138

Tôi đã tự hỏi nếu có thể vô hiệu hóa thuộc tính Yêu cầu xác thực trong các hành động điều khiển nhất định. Tôi tự hỏi điều này bởi vì trên một trong các hình thức chỉnh sửa của tôi, tôi không yêu cầu người dùng nhập giá trị cho các trường mà họ đã chỉ định trước đó. Tuy nhiên, sau đó tôi triển khai logic rằng khi họ nhập một giá trị, nó sử dụng một số logic đặc biệt để cập nhật mô hình, chẳng hạn như băm một giá trị, v.v.

Bất kỳ vấn đề nào về cách khắc phục vấn đề này?

EDIT:
Và có xác nhận khách hàng là một vấn đề ở đây, vì nó sẽ không cho phép họ gửi biểu mẫu mà không nhập giá trị.


3
+1 tốt Q. Sẽ tốt khi đề cập đến xác nhận của khách hàng ở đây. Một tùy chọn là loại bỏ RequiredAttrhoàn toàn và kiểm tra phía máy chủ khi bạn cần. Nhưng điều này sẽ gây khó khăn cho khách hàng
gideon

4
Điểm cho bất kỳ ai cũng bao gồm việc vô hiệu hóa một số trường nhất định khỏi xác thực ứng dụng khách (không xóa tham chiếu đến xác thực jquery)
gideon

Có thể tôi đang thiếu quan điểm của bạn, nhưng nếu người dùng đã chỉ định trước các giá trị, thì các giá trị đó đã có sẵn và do đó sẽ vượt qua Xác thực bắt buộc. Có phải ý của bạn là thứ khác?
Erik Funkenbusch

Vì các giá trị này đã được băm, chẳng hạn như mật khẩu và câu trả lời bảo mật, vì vậy nếu chúng nhập một giá trị mới trên biểu mẫu chỉnh sửa, tôi muốn băm lại giá trị mới trước khi chèn, nhưng tôi cũng muốn tùy chọn cho nó bị bỏ trống loại điều
Alex Hope O'Connor 21/03

1
@gideon: xem câu trả lời của Adrian Smith: stackoverflow.com/a/9781066/114029
Leniel Maccaferri

Câu trả lời:


76

Vấn đề này có thể được giải quyết dễ dàng bằng cách sử dụng các mô hình xem. Các mô hình xem là các lớp được thiết kế riêng cho nhu cầu của một khung nhìn cụ thể. Vì vậy, ví dụ trong trường hợp của bạn, bạn có thể có các mô hình xem sau:

public UpdateViewView
{
    [Required]
    public string Id { get; set; }

    ... some other properties
}

public class InsertViewModel
{
    public string Id { get; set; }

    ... some other properties
}

mà sẽ được sử dụng trong các hành động điều khiển tương ứng của họ:

[HttpPost]
public ActionResult Update(UpdateViewView model)
{
    ...
}

[HttpPost]
public ActionResult Insert(InsertViewModel model)
{
    ...
}

Không phải lúc nào cũng đúng nếu bạn có boolean / bit không thể rỗng. Nhưng thực sự không tạo ra sự khác biệt vì nó sẽ kết thúc đúng hay sai. Tôi đã có css để làm nổi bật các trường bắt buộc và nó làm nổi bật mục CheckBoxFor. Giải pháp của tôi: $ ("# IsValueTrue"). RemoveAttr ("data-val-required");
Robert Koch

Trong bản cập nhật, chúng tôi thường có (bộ sưu tập FormCollection). bạn có thể giải thích cách bạn đang sử dụng mô hình làm tham số không
Raj Kumar

4
Không, chúng tôi thường không có Update(FormCollection collection), ít nhất là tôi không bao giờ làm. Tôi luôn xác định và sử dụng một mô hình xem cụ thể : Update(UpdateViewView model).
Darin Dimitrov

Các phương thức quá tải với cùng một hành động HTTP không được phép, vì vậy với tôi có vẻ như điều này sẽ không hoạt động. Tui bỏ lỡ điều gì vậy?
e11

@edgi, không, bạn không thiếu thứ gì. Đó là một sai lầm trong bài viết của tôi. Phương thức hành động thứ hai rõ ràng nên được gọi Insert. Cảm ơn đã chỉ ra điều này.
Darin Dimitrov

55

Nếu bạn chỉ muốn tắt xác thực cho một trường ở phía máy khách thì bạn có thể ghi đè các thuộc tính xác thực như sau:

@Html.TexBoxFor(model => model.SomeValue, 
                new Dictionary<string, object> { { "data-val", false }})

20
Những gì đã làm việc cho tôi thông qua jQuery: $ ("# someValue"). RemoveAttr ("data-val-required");
Robert Koch

6
Tôi thích cách tiếp cận này nhưng tôi cần phân tích lại các thuộc tính xác thực mẫu bằng cách sử dụng: $ ('form'). RemoveData ('un phôrusiveValidation'); $ ('biểu mẫu'). removeData ('trình xác nhận'); $ .validator.unazedrusive.parse ('bộ chọn cho biểu mẫu của bạn');
Yannick Smits

15
@Html.TexBoxFor(model => model.SomeValue, new { data_val = false })- dễ đọc IMO hơn.
eth0

Tôi thích hầu hết cách tiếp cận này để cho tôi kiểm soát tốt từng trường, nhưng bạn có thể thêm để hủy ModelState.IsValid khi gửi dữ liệu để lưu bằng POST. Có thể gây ra một số rủi ro?
Felipe FMMobile

4
Nếu bạn muốn tắt nó thông qua jQuery:$(".search select").attr('data-val', false);
Leniel Maccaferri

40

Tôi biết câu hỏi này đã được trả lời từ lâu và câu trả lời được chấp nhận sẽ thực sự làm việc. Nhưng có một điều làm tôi bực mình: chỉ phải sao chép 2 mô hình để vô hiệu hóa xác nhận.

Đây là gợi ý của tôi:

public class InsertModel
{
    [Display(...)]
    public virtual string ID { get; set; }

    ...Other properties
}

public class UpdateModel : InsertModel
{
    [Required]
    public override string ID
    {
        get { return base.ID; }
        set { base.ID = value; }
    }
}

Bằng cách này, bạn không phải bận tâm đến xác nhận phía máy khách / máy chủ, khung sẽ hoạt động theo cách nó được yêu cầu. Ngoài ra, nếu bạn xác định một [Display]thuộc tính trên lớp cơ sở, bạn không phải xác định lại thuộc tính đó trong UpdateModel.

Và bạn vẫn có thể sử dụng các lớp này theo cùng một cách:

[HttpPost]
public ActionResult Update(UpdateModel model)
{
    ...
}

[HttpPost]
public ActionResult Insert(InsertModel model)
{
    ...
}

Tôi thích cách tiếp cận này tốt hơn, đặc biệt nếu bạn có một danh sách dài các thuộc tính xác nhận. Trong ví dụ của bạn, bạn có thể thêm nhiều thuộc tính trong lớp cơ sở để có lợi ích rõ ràng hơn. Nhược điểm duy nhất tôi có thể thấy là không có cách nào để kế thừa các thuộc tính để ghi đè các thuộc tính. Ví dụ, nếu bạn có thuộc tính [Bắt buộc] trên lớp cơ sở, thuộc tính kế thừa cũng bị buộc phải là [Bắt buộc], trừ khi bạn có thuộc tính [Tùy chọn] tùy chỉnh.
Yorro

Tôi cũng nghĩ về một cái gì đó giống như vậy, mặc dù tôi có viewModel có một đối tượng 'Project' có nhiều thuộc tính và tôi chỉ muốn một trong những thuộc tính này được xác thực trong một số trường hợp nhất định. Tôi không nghĩ rằng tôi chỉ có thể ghi đè một thuộc tính của một đối tượng phải không? Lời khuyên nào?
vincent de g

Bạn không thể ghi đè thuộc tính. Lớp cơ sở chỉ nên chứa các thuộc tính chung cho tất cả các lớp con. Sau đó, các lớp con của bạn sẽ xác định các thuộc tính họ cần.
PhilDulac

1
Thanh lịch nhất, tái sử dụng, giải pháp rõ ràng. Bản sao là xấu. Đa hình là cách. +1
T-moty

trong trường hợp của tôi, một lớp cơ sở có một thuộc tính bắt buộc và tôi muốn làm cho nó không bắt buộc trong lớp cha của tôi. Có thể mà không có hai bản sao của mô hình?
Alexey Strakh

27

Bạn có thể xóa tất cả xác thực khỏi một thuộc tính bằng hành động điều khiển sau đây.

ModelState.Remove<ViewModel>(x => x.SomeProperty);

@ Nhận xét của Ian về MVC5

Sau đây vẫn có thể

ModelState.Remove("PropertyNameInModel");

Hơi khó chịu khi bạn mất kiểu gõ tĩnh với API được cập nhật. Bạn có thể đạt được một cái gì đó tương tự như cách cũ bằng cách tạo một phiên bản của trình trợ giúp HTML và sử dụng Phương thức NameExtensions .


Ngoại trừ ... không có một phương pháp ModelStatenào phù hợp với chữ ký đó. Không phải trong MVC 5, ít nhất.
Ian Kemp

Câu hỏi không phải là làm thế nào để loại bỏ tất cả xác nhận. Đó là cách loại bỏ xác nhận trường bắt buộc. Bạn có thể muốn làm điều này trong khi để lại các quy tắc xác nhận khác.
Richard

15

Phía khách hàng Để vô hiệu hóa xác thực cho một biểu mẫu, nhiều tùy chọn dựa trên nghiên cứu của tôi được đưa ra dưới đây. Một trong số họ hy vọng sẽ làm việc cho bạn.

lựa chọn 1

Tôi thích điều này, và điều này làm việc hoàn hảo cho tôi.

(function ($) {
    $.fn.turnOffValidation = function (form) {
        var settings = form.validate().settings;

        for (var ruleIndex in settings.rules) {
            delete settings.rules[ruleIndex];
        }
    };
})(jQuery); 

và gọi nó như

$('#btn').click(function () {
    $(this).turnOffValidation(jQuery('#myForm'));
});

Lựa chọn 2

$('your selector here').data('val', false);
$("form").removeData("validator");
$("form").removeData("unobtrusiveValidation");
$.validator.unobtrusive.parse("form");

Lựa chọn 3

var settings = $.data($('#myForm').get(0), 'validator').settings;
settings.ignore = ".input";

Lựa chọn 4

 $("form").get(0).submit();
 jQuery('#createForm').unbind('submit').submit();

Lựa chọn 5

$('input selector').each(function () {
    $(this).rules('remove');
});

Phía máy chủ

Tạo một thuộc tính và đánh dấu phương thức hành động của bạn với thuộc tính đó. Tùy chỉnh này để thích ứng với nhu cầu cụ thể của bạn.

[AttributeUsage(AttributeTargets.All)]
public class IgnoreValidationAttribute : ActionFilterAttribute
{
    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        var modelState = filterContext.Controller.ViewData.ModelState;

        foreach (var modelValue in modelState.Values)
        {
            modelValue.Errors.Clear();
        }
    }
}

Một cách tiếp cận tốt hơn đã được mô tả ở đây Kích hoạt / Vô hiệu hóa xác thực phía máy chủ mvc


$ ('bộ chọn đầu vào'). Each (function () {$ (this) .rules ('remove');}); đã giúp tôi
Sachin Pakale

Câu hỏi cụ thể là về việc xóa xác thực trường bắt buộc, không phải về xóa tất cả xác thực. Câu trả lời của bạn là về việc loại bỏ tất cả xác nhận.
Richard

14

Cá nhân tôi sẽ có xu hướng sử dụng phương pháp mà Darin Dimitrov thể hiện trong giải pháp của mình. Điều này giải phóng bạn để có thể sử dụng phương pháp chú thích dữ liệu với xác thực VÀ có các thuộc tính dữ liệu riêng biệt trên mỗi ViewModel tương ứng với tác vụ trong tay. Để giảm thiểu khối lượng công việc sao chép giữa model và viewmodel, bạn nên xem AutoMapper hoặc ValueInjecter . Cả hai đều có điểm mạnh riêng, vì vậy hãy kiểm tra cả hai.

Một cách tiếp cận khả thi khác cho bạn sẽ là lấy mô hình hoặc mô hình của bạn từ IValiditableObject. Điều này cung cấp cho bạn tùy chọn để thực hiện chức năng Xác thực. Để xác thực, bạn có thể trả về Danh sách các phần tử Xác thực hoặc trả lại lợi tức cho mỗi vấn đề bạn phát hiện khi xác thực.

ValidationResult bao gồm một thông báo lỗi và một danh sách các chuỗi có tên trường. Các thông báo lỗi sẽ được hiển thị tại một vị trí gần (các) trường đầu vào.

public IEnumerable<ValidationResult> Validate(ValidationContext validationContext)
{
  if( NumberField < 0 )
  {
    yield return new ValidationResult( 
        "Don't input a negative number", 
        new[] { "NumberField" } );
  }

  if( NumberField > 100 )
  {
    yield return new ValidationResult( 
        "Don't input a number > 100", 
        new[] { "NumberField" } );
  }

  yield break;
}

chúng ta có thể móc cái này về phía khách hàng không?
Muhammad Adeel Zahid

Xác thực phía khách hàng thường chỉ được thực hiện cho các trường riêng lẻ, thực hiện phản hồi xác thực tương tác, theo trường, để thuận tiện cho người dùng. Do bước xác thực đối tượng thường liên quan đến xác thực phụ thuộc (nhiều trường và / hoặc điều kiện bên ngoài đối tượng) nên điều này không nhất thiết phải được thực hiện ở phía máy khách, ngay cả khi bạn có thể biên dịch mã thành JavaScript. Nếu xác thực phức tạp / phụ thuộc ở phía máy khách không thêm giá trị trong trường hợp của bạn, bạn sẽ cần sử dụng lệnh gọi lại onsubmit và sao chép logic xác thực ở phía máy khách.
mindplay.dk

7

Cách sạch nhất ở đây tôi tin là sẽ vô hiệu hóa xác thực phía máy khách của bạn và về phía máy chủ, bạn sẽ cần phải:

  1. ModelState ["someField"]. Error.Clear (trong bộ điều khiển của bạn hoặc tạo bộ lọc hành động để loại bỏ lỗi trước khi mã điều khiển được thực thi)
  2. Thêm ModelState.AddModelError từ mã điều khiển của bạn khi bạn phát hiện vi phạm các vấn đề được phát hiện của mình.

Dường như ngay cả một mô hình chế độ xem tùy chỉnh ở đây sẽ không giải quyết được vấn đề vì số lượng các trường 'trả lời trước' có thể khác nhau. Nếu họ không thì mô hình chế độ xem tùy chỉnh thực sự có thể là cách dễ nhất, nhưng sử dụng kỹ thuật trên, bạn có thể giải quyết các vấn đề về xác nhận của mình.


1
Đây chỉ là những gì tôi cần. Tôi đã có một chế độ xem và các hành động khác nhau xảy ra trong chế độ xem này, vì vậy tôi không thể thực hiện nó với ViewModels khác biệt. Điều này hoạt động như một sự quyến rũ
ggderas

6

đây là câu trả lời của người khác trong các bình luận ... nhưng nó phải là một câu trả lời thực sự:

$("#SomeValue").removeAttr("data-val-required")

đã thử nghiệm trên MVC 6 với một trường có [Required]thuộc tính

câu trả lời bị đánh cắp từ https://stackoverflow.com/users/73382/rob ở trên


1
Điều gì về xác nhận phía máy chủ?
T-moty

ModelState.Remove, phải không? Ở mức độ nào, đối với tôi, vấn đề là tôi đã có một thực thể thứ hai được đưa vào mô hình của mình ... chính tôi muốn xác thực, nhưng thứ cấp không cần xác thực trên trang đó ... vì vậy, theo kịch bản này , chỉ có JQuery là cần thiết.
Mike_Matthews_II

Tôi nghĩ rằng liên kết bị hỏng, vì vậy hãy chỉnh sửa. Đây là câu trả lời một phần
T-moty

Thật kỳ lạ khi bạn nói điều này hoạt động trong MVC6 (hiện tại tôi không có tùy chọn để kiểm tra trên MVC6) nhưng không hoạt động với tôi trên MVC4 mà tôi hiện đang sử dụng.
Eaglei22

Câu hỏi dành cho MVC / C # - không phải là JS, câu trả lời sẽ không hoạt động phía máy chủ
mtbennett

2

Tôi gặp vấn đề này khi tạo Chế độ xem Chỉnh sửa cho Mô hình của mình và tôi muốn cập nhật chỉ một trường.

Giải pháp của tôi cho cách đơn giản nhất là đặt hai trường bằng cách sử dụng:

 <%: Html.HiddenFor(model => model.ID) %>
 <%: Html.HiddenFor(model => model.Name)%>
 <%: Html.HiddenFor(model => model.Content)%>
 <%: Html.TextAreaFor(model => model.Comments)%>

Nhận xét là trường mà tôi chỉ cập nhật trong Chế độ xem Chỉnh sửa, không có Thuộc tính bắt buộc.

Thực thể ASP.NET MVC 3


1

AFAIK bạn không thể xóa thuộc tính trong thời gian chạy, mà chỉ thay đổi giá trị của chúng (ví dụ: readonly true / false) ở đây để tìm một cái gì đó tương tự . Như một cách khác để làm những gì bạn muốn mà không làm hỏng các thuộc tính, tôi sẽ sử dụng ViewModel cho hành động cụ thể của bạn để bạn có thể chèn tất cả logic mà không phá vỡ logic cần thiết của các bộ điều khiển khác. Nếu bạn cố gắng để có được một số loại trình hướng dẫn (một biểu mẫu nhiều bước), thay vào đó bạn có thể tuần tự hóa các trường đã được biên dịch và với TempData, hãy mang chúng theo các bước của bạn. (để được trợ giúp trong việc tuần tự hóa giải tuần tự hóa, bạn có thể sử dụng tương lai MVC )


1

Những gì @Darin nói là những gì tôi muốn giới thiệu là tốt. Tuy nhiên tôi sẽ thêm vào nó (và để đáp lại một trong những ý kiến) rằng trên thực tế bạn cũng có thể sử dụng phương thức này cho các kiểu nguyên thủy như bit, bool, thậm chí các cấu trúc như Guid bằng cách đơn giản biến chúng thành nullable. Một khi bạn làm điều này, các Requiredchức năng thuộc tính như mong đợi.

public UpdateViewView
{
    [Required]
    public Guid? Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Required]
    public int? Age { get; set; }
    [Required]
    public bool? IsApproved { get; set; }
    //... some other properties
}

1

Kể từ MVC 5, điều này có thể dễ dàng đạt được bằng cách thêm cái này vào global.asax.

DataAnnotationsModelValidatorProvider.AddImplicitRequiredAttributeForValueTypes = false;

1

Tôi đang tìm kiếm một giải pháp trong đó tôi có thể sử dụng cùng một mô hình để chèn và cập nhật trong api web. Trong tình huống của tôi là điều này luôn luôn là một nội dung cơ thể. Các [Requiered]thuộc tính phải được bỏ qua nếu nó là một phương thức cập nhật. Trong giải pháp của tôi, bạn đặt một thuộc tính [IgnoreRequiredValidations]trên phương thức. Điều này như sau:

public class WebServiceController : ApiController
{
    [HttpPost]
    public IHttpActionResult Insert(SameModel model)
    {
        ...
    }

    [HttpPut]
    [IgnoreRequiredValidations]
    public IHttpActionResult Update(SameModel model)
    {
        ...
    }

    ...

Những gì khác cần phải được thực hiện? Một BodyModelValidator riêng phải được tạo và thêm vào lúc khởi động. Đây là trong HTTPConfiguration và trông như thế này:config.Services.Replace(typeof(IBodyModelValidator), new IgnoreRequiredOrDefaultBodyModelValidator());

using Owin;
using your_namespace.Web.Http.Validation;

[assembly: OwinStartup(typeof(your_namespace.Startup))]

namespace your_namespace
{
    public class Startup
    {
        public void Configuration(IAppBuilder app)
        {
            Configuration(app, new HttpConfiguration());
        }

        public void Configuration(IAppBuilder app, HttpConfiguration config)
        {
            config.Services.Replace(typeof(IBodyModelValidator), new IgnoreRequiredOrDefaultBodyModelValidator());
        }

        ...

BodyModelValidator của riêng tôi có nguồn gốc từ DefaultBodyModelValidator. Và tôi nhận ra rằng tôi đã phải ghi đè lên phương thức 'ShallowValidate'. Trong phần ghi đè này, tôi lọc các trình xác nhận mô hình certierd. Và bây giờ, lớp IgnoreRequiredOrDefaultBodyModelValidator và lớp attributte IgnoreRequiredValidations:

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Web.Http.Controllers;
using System.Web.Http.Metadata;
using System.Web.Http.Validation;

namespace your_namespace.Web.Http.Validation
{
    public class IgnoreRequiredOrDefaultBodyModelValidator : DefaultBodyModelValidator
    {
        private static ConcurrentDictionary<HttpActionBinding, bool> _ignoreRequiredValidationByActionBindingCache;

        static IgnoreRequiredOrDefaultBodyModelValidator()
        {
            _ignoreRequiredValidationByActionBindingCache = new ConcurrentDictionary<HttpActionBinding, bool>();
        }

        protected override bool ShallowValidate(ModelMetadata metadata, BodyModelValidatorContext validationContext, object container, IEnumerable<ModelValidator> validators)
        {
            var actionContext = validationContext.ActionContext;

            if (RequiredValidationsIsIgnored(actionContext.ActionDescriptor.ActionBinding))
                validators = validators.Where(v => !v.IsRequired);          

            return base.ShallowValidate(metadata, validationContext, container, validators);
        }

        #region RequiredValidationsIsIgnored
        private bool RequiredValidationsIsIgnored(HttpActionBinding actionBinding)
        {
            bool ignore;

            if (!_ignoreRequiredValidationByActionBindingCache.TryGetValue(actionBinding, out ignore))
                _ignoreRequiredValidationByActionBindingCache.TryAdd(actionBinding, ignore = RequiredValidationsIsIgnored(actionBinding.ActionDescriptor as ReflectedHttpActionDescriptor));

            return ignore;
        }

        private bool RequiredValidationsIsIgnored(ReflectedHttpActionDescriptor actionDescriptor)
        {
            if (actionDescriptor == null)
                return false;

            return actionDescriptor.MethodInfo.GetCustomAttribute<IgnoreRequiredValidationsAttribute>(false) != null;
        } 
        #endregion
    }

    [AttributeUsage(AttributeTargets.Method, Inherited = true)]
    public class IgnoreRequiredValidationsAttribute : Attribute
    {

    }
}

Nguồn:


0

Nếu bạn không muốn sử dụng một ViewModel khác, bạn có thể vô hiệu hóa xác thực ứng dụng khách trên chế độ xem và cũng có thể xóa các xác thực trên máy chủ cho các thuộc tính mà bạn muốn bỏ qua. Vui lòng kiểm tra câu trả lời này để được giải thích sâu hơn https://stackoverflow.com/a/15248790/1128216


0

Trong trường hợp của tôi, cùng một Mô hình đã được sử dụng trong nhiều trang cho mục đích sử dụng lại. Vì vậy, những gì tôi đã làm là tôi đã tạo ra một thuộc tính tùy chỉnh để kiểm tra loại trừ

public class ValidateAttribute : ActionFilterAttribute
{
    public string Exclude { get; set; }
    public string Base { get; set; }
    public override void OnActionExecuting(HttpActionContext actionContext)
    {
        if (!string.IsNullOrWhiteSpace(this.Exclude))
        {
            string[] excludes = this.Exclude.Split(',');
            foreach (var exclude in excludes)
            {
                actionContext.ModelState.Remove(Base + "." + exclude);
            }
        }
        if (actionContext.ModelState.IsValid == false)
        {
            var mediaType = new MediaTypeHeaderValue("application/json");
            var error = actionContext.ModelState;

            actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.OK, error.Keys, mediaType);

        }
    }
}

và trong bộ điều khiển của bạn

[Validate(Base= "person",Exclude ="Age,Name")]
    public async Task<IHttpActionResult> Save(User person)
    {

            //do something           

    }

Nói mô hình là

public class User
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    [Range(18,99)]
    public string Age { get; set; }
    [MaxLength(250)]
    public string Address { get; set; }
}

-1

Có, có thể vô hiệu hóa thuộc tính cần thiết. Tạo thuộc tính lớp tùy chỉnh của riêng bạn (mã mẫu được gọi là ChangizableRequired) để mở rộng từ RequestAtribution và thêm Thuộc tính bị vô hiệu hóa và ghi đè phương thức IsValid để kiểm tra xem nó có bị mất cân bằng không. Sử dụng sự phản chiếu để thiết lập poperty bị vô hiệu hóa, như vậy:

Thuộc tính tùy chỉnh:

namespace System.ComponentModel.DataAnnotations
{
    public class ChangeableRequired : RequiredAttribute
    {
       public bool Disabled { get; set; }

       public override bool IsValid(object value)
       {
          if (Disabled)
          {
            return true;
          }

          return base.IsValid(value);
       }
    }
}

Cập nhật tài sản của bạn để sử dụng Thuộc tính tùy chỉnh mới của bạn:

 class Forex
 {
 ....
    [ChangeableRequired]
    public decimal? ExchangeRate {get;set;}
 ....
 }

nơi bạn cần vô hiệu hóa thuộc tính sử dụng sự phản chiếu để đặt nó:

Forex forex = new Forex();
// Get Property Descriptor from instance with the Property name
PropertyDescriptor descriptor = TypeDescriptor.GetProperties(forex.GetType())["ExchangeRate"];
//Search for Attribute
ChangeableRequired attrib =  (ChangeableRequired)descriptor.Attributes[typeof(ChangeableRequired)];

// Set Attribute to true to Disable
attrib.Disabled = true;

Điều này cảm thấy tốt đẹp và sạch sẽ?

NB: Xác thực ở trên sẽ bị vô hiệu hóa trong khi đối tượng của bạn còn sống \ active ...


Sau một vài cuộc tranh luận về vấn đề này, tôi muốn đề cập rằng tôi không khuyên bạn nên vô hiệu hóa xác nhận mà nên xem lại quy tắc. Nếu bạn tắt nó, bạn tạo một phụ thuộc để kích hoạt lại quy tắc và tôi sẽ đề nghị xem lại quy tắc.
Ernest Gunning

Thay đổi một giá trị tĩnh để vô hiệu hóa hoàn toàn tất cả xác thực của trường đó được thực thi trong cùng quy trình đó nghe có vẻ là một ý tưởng tồi tệ.
Jeremy Lakeman
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.