문제

IDataErrorInfo 인터페이스를 사용하려고 하는 간단한 주소 입력 앱이 있습니다. asp.net 사이트에 설명되어 있습니다..

독립적으로 유효성을 검사할 수 있는 항목에는 적합하지만 일부 항목이 다른 항목에 종속되는 경우에는 적합하지 않습니다.예를 들어 우편번호 확인은 국가에 따라 다릅니다.

    private string _PostalCode;
    public string PostalCode
    {
        get
        {
            return _PostalCode;
        }
        set
        {
            switch (_Country)
            {
                case Countries.USA:
                    if (!Regex.IsMatch(value, @"^[0-9]{5}$"))
                        _errors.Add("PostalCode", "Invalid Zip Code");
                    break;
                case Countries.Canada:
                    if (!Regex.IsMatch(value, @"^([a-z][0-9][a-z]) ?([0-9][a-z][0-9])$", RegexOptions.IgnoreCase))
                        _errors.Add("PostalCode", "Invalid postal Code");
                    break;
                default:
                    throw new ArgumentException("Unknown Country");
            }
            _PostalCode = value;
        }
    }

따라서 국가를 설정한 후에만 우편번호를 확인할 수 있지만 그 순서를 제어할 수 있는 방법은 없는 것 같습니다.

IDataErrorInfo의 오류 문자열을 사용할 수 있지만 필드 옆의 Html.ValidationMessage에는 표시되지 않습니다.

도움이 되었습니까?

해결책

보다 복잡한 비즈니스 규칙 검증의 경우 유형 검증보다는 서비스 계층과 같은 디자인 패턴을 구현하는 것이 더 나을 수 있습니다.ModelState를 확인하고 논리에 따라 오류를 추가할 수 있습니다.

여기에서 Rob Conroy의 패턴 예를 볼 수 있습니다.

http://www.asp.net/learn/mvc/tutorial-29-cs.aspx

데이터 주석에 관한 이 문서도 유용합니다.

http://www.asp.net/learn/mvc/tutorial-39-cs.aspx

도움이 되었기를 바랍니다.

다른 팁

단순한 데이터 주석 모델을 넘어 더욱 복잡한 검증을 위해 제가 찾은 최고의 솔루션은 다음과 같습니다.

구현하려는 노력이 나 혼자가 아닐 것이라고 확신합니다. IDataErrorInfo 구현해야 할 두 가지 방법만 생성되었음을 확인했습니다.잠깐만요. 이제 거기로 가서 모든 것에 대해 처음부터 나만의 맞춤 루틴을 작성해야 할까요?또한 모델 수준에서 검증할 사항이 있으면 어떻게 됩니까?뭔가 하고 싶지 않은 이상 사용하기로 결정하면 스스로 판단하는 것 같습니다. 이와 같이 또는 이것 IDataErrorInfo 구현 내에서.

질문자와 똑같은 문제가 발생했습니다.US Zip을 확인하고 싶었지만 국가가 US로 선택된 경우에만 가능했습니다.분명히 모델 수준 데이터 주석은 우편번호가 오류로 빨간색으로 강조 표시되지 않기 때문에 좋지 않습니다.[클래스 수준 데이터 주석의 좋은 예는 PropertiesMustMatchAttribute 클래스의 MVC 2 샘플 프로젝트에서 찾을 수 있습니다].

해결책은 매우 간단합니다.

먼저 global.asax에 모델바인더를 등록해야 합니다.원한다면 클래스 수준 [속성]으로 이 작업을 수행할 수 있지만 global.asax에 등록하는 것이 더 유연하다고 생각합니다.

private void RegisterModelBinders()
{
     ModelBinders.Binders[typeof(UI.Address)] = new AddressModelBinder();
}

그런 다음 modelbinder 클래스를 만들고 복잡한 유효성 검사를 작성합니다.개체의 모든 속성에 대한 전체 액세스 권한이 있습니다.이 실행됩니다 ~ 후에 모든 데이터 주석이 실행되었으므로 유효성 검사 속성의 기본 동작을 되돌리려는 경우 언제든지 모델 상태를 지울 수 있습니다.

public class AddressModelBinder : DefaultModelBinder
{
    protected override void OnModelUpdated(ControllerContext controllerContext, 
        ModelBindingContext bindingContext)
    {
        base.OnModelUpdated(controllerContext, bindingContext);

        // get the address to validate
        var address = (Address)bindingContext.Model;

        // validate US zipcode
        if (address.CountryCode == "US")
        {
            if (new Regex(@"^\d{5}([\-]\d{4})?$", RegexOptions.Compiled).
                Match(address.ZipOrPostal ?? "").Success == false)
            {
                // not a valid zipcode so highlight the zipcode field
                var ms = bindingContext.ModelState;                    
                ms.AddModelError(bindingContext.ModelName + ".ZipOrPostal", 
                "The value " + address.ZipOrPostal + " is not a valid zipcode");
            }
        }
        else {
            // we don't care about the rest of the world right now
            // so just rely on a [Required] attribute on ZipOrPostal
        }

        // all other modelbinding attributes such as [Required] 
        // will be processed as normal
    }
}

이것의 장점은 기존의 모든 유효성 검사 속성([필수], [EmailValidator], [MyCustomValidator])이 무엇이든 여전히 작동한다는 것입니다.

원하는 대로 모델 바인더에 추가 코드를 추가하고 필드를 설정하거나 모델 수준의 ModelState 오류를 설정할 수 있습니다.

저에게는 Address 메인 모델의 자식입니다 - 이 경우 CheckoutModel 이는 다음과 같습니다.

public class CheckoutModel
{
    // uses AddressModelBinder
    public Address BillingAddress { get; set; }
    public Address ShippingAddress { get; set; }

    // etc.
}

그렇기 때문에 내가 해야 할 일은 bindingContext.ModelName+ ".ZipOrPostal" 'BillingAddress.ZipOrPostal' 및 'ShippingAddress.ZipOrPostal'에 대해 모델 오류가 설정됩니다.

추신.'단위 테스트 유형'의 모든 의견에 감사드립니다.이것이 단위 테스트에 미치는 영향에 대해서는 잘 모르겠습니다.

오류 문자열, IDataErrorInfo 및 Html.ValidationMessage에 대한 설명과 관련하여 개체 수준과 개체 수준을 표시할 수 있습니다.다음을 사용하는 필드 수준 오류 메시지:

Html.ValidationMessage("address", "Error")

Html.ValidationMessage("address.PostalCode", "Error")

컨트롤러에서 [Bind(Prefix = "address")]를 사용하여 객체에 대한 게시 메서드 핸들러 매개변수를 장식합니다.HTML에서 입력 필드의 이름을 다음과 같이 지정하십시오.

<input id="address_PostalCode" name="address.PostalCode" ... />

나는 일반적으로 Html 도우미를 사용하지 않습니다.id와 name 사이의 명명 규칙에 유의하세요.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top