다음을 통해 공유


Enterprise Apps의 유효성 검사

참고 항목

이 전자책은 2017년 봄에 게시되었으며 그 이후로 업데이트되지 않았습니다. 이 책에는 귀중한 기본 많이 있지만 일부 자료는 구식입니다.

사용자의 입력을 수락하는 모든 앱은 입력이 유효한지 확인해야 합니다. 예를 들어 앱은 특정 범위의 문자만 포함하거나, 특정 길이이거나, 특정 형식과 일치하는 입력을 확인할 수 있습니다. 사용자는 유효성 검사 없이 앱 실패를 야기하는 데이터를 제공할 수 있습니다. 유효성 검사는 비즈니스 규칙을 적용하고 공격자가 악의적인 데이터를 삽입하지 못하도록 합니다.

MVVM(Model-View-ViewModel) 패턴의 컨텍스트에서 뷰 모델 또는 모델은 종종 데이터 유효성 검사를 수행하고 사용자가 오류를 수정할 수 있도록 뷰에 유효성 검사 오류 신호를 보내야 합니다. eShopOnContainers 모바일 앱은 뷰 모델 속성의 동기 클라이언트 쪽 유효성 검사를 수행하고 잘못된 데이터가 포함된 컨트롤을 강조 표시하고 데이터가 잘못된 이유를 사용자에게 알리는 오류 메시지를 표시하여 유효성 검사 오류를 사용자에게 알릴 수 있습니다. 그림 6-1은 eShopOnContainers 모바일 앱에서 유효성 검사를 수행하는 데 관련된 클래스를 보여 줍니다.

Validation classes in the eShopOnContainers mobile app

그림 6-1: eShopOnContainers 모바일 앱의 유효성 검사 클래스

유효성 검사가 필요한 뷰 모델 속성은 ValidatableObject<T> 형식이며, 각 ValidatableObject<T> 인스턴스에는 해당 Validations 속성에 유효성 검사 규칙이 추가됩니다. 유효성 검사는 유효성 검사 규칙을 검색하고 ValidatableObject<T>Value 속성에 대해 해당 규칙을 실행하는 ValidatableObject<T> 인스턴스의 Validate 메서드를 호출하여 뷰 모델에서 호출됩니다. 유효성 검사 오류는 인스턴스의 ValidatableObject<T> 속성에 Errors 배치되고 IsValid 인스턴스의 ValidatableObject<T> 속성은 유효성 검사 성공 또는 실패 여부를 나타내도록 업데이트됩니다.

속성 변경 알림은 ExtendedBindableObject 클래스에서 제공되므로 Entry 컨트롤이 뷰 모델 클래스에 있는 ValidatableObject<T> 인스턴스의 IsValid 속성에 바인딩되어 입력한 데이터가 유효한지 여부에 대해 알림을 받을 수 있습니다.

유효성 검사 규칙 지정

유효성 검사 규칙은 다음 코드 예제에 표시된 IValidationRule<T> 인터페이스에서 파생되는 클래스를 만들어 지정합니다.

public interface IValidationRule<T>  
{  
    string ValidationMessage { get; set; }  
    bool Check(T value);  
}

이 인터페이스는 유효성 검사 규칙 클래스가 필요한 유효성 검사를 수행하는 데 사용되는 메서드와 ValidationMessage 유효성 검사에 실패할 경우 표시될 유효성 검사 오류 메시지 값인 속성을 제공해야 booleanCheck 한다고 지정합니다.

다음 코드 예제에서는 eShopOnContainers 모바일 앱에서 모의 서비스를 사용할 때 사용자가 LoginView 입력한 사용자 이름 및 암호의 유효성 검사를 수행하는 데 사용되는 유효성 검사 규칙을 보여 IsNotNullOrEmptyRule<T> 줍니다.

public class IsNotNullOrEmptyRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        return !string.IsNullOrWhiteSpace(str);  
    }  
}

이 메서드는 Check 값 인수null가 비어 있는지, 공백 문자로만 구성되는지 여부를 나타내는 값을 반환 boolean 합니다.

eShopOnContainers 모바일 앱에서는 사용되지 않지만 다음 코드 예제에서는 전자 메일 주소의 유효성을 검사하기 위한 유효성 검사 규칙을 보여 줍니다.

public class EmailRule<T> : IValidationRule<T>  
{  
    public string ValidationMessage { get; set; }  

    public bool Check(T value)  
    {  
        if (value == null)  
        {  
            return false;  
        }  

        var str = value as string;  
        Regex regex = new Regex(@"^([\w\.\-]+)@([\w\-]+)((\.(\w){2,3})+)$");  
        Match match = regex.Match(str);  

        return match.Success;  
    }  
}

이 메서드는 Check 값 인수가 유효한 전자 메일 주소인지 여부를 나타내는 값을 반환 boolean 합니다. 이 작업은 Regex 생성자에 지정된 정규식 패턴이 처음 나오는 경우에 대한 값 인수를 검색하여 수행됩니다. 입력 문자열에서 정규식 패턴이 발견되었는지 여부는 개체 Success 의 속성 값을 Match 검사 확인할 수 있습니다.

참고 항목

속성 유효성 검사에는 종속 속성이 포함되는 경우가 있습니다. 종속 속성의 예는 속성 A의 유효한 값 집합이 속성 B에 설정된 특정 값에 따라 달라지는 경우입니다. 속성 A의 값이 허용되는 값 중 하나인지 확인하기 위해 속성 B의 값을 검색하게 됩니다. 또한 속성 B의 값이 변경되면 속성 A의 유효성을 다시 검사해야 합니다.

속성에 유효성 검사 규칙 추가

eShopOnContainers 모바일 앱에서 유효성 검사가 필요한 보기 모델 속성은 유효성을 검사할 데이터의 형식인 형식 ValidatableObject<T>T 으로 선언됩니다. 다음 코드 예제에서는 이러한 두 속성의 예를 보여 줍니다.

public ValidatableObject<string> UserName  
{  
    get  
    {  
        return _userName;  
    }  
    set  
    {  
        _userName = value;  
        RaisePropertyChanged(() => UserName);  
    }  
}  

public ValidatableObject<string> Password  
{  
    get  
    {  
        return _password;  
    }  
    set  
    {  
        _password = value;  
        RaisePropertyChanged(() => Password);  
    }  
}

유효성 검사를 수행하려면 다음 코드 예제와 같이 각 ValidatableObject<T> 인스턴스의 컬렉션에 유효성 검사 규칙을 추가 Validations 해야 합니다.

private void AddValidations()  
{  
    _userName.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A username is required."   
    });  
    _password.Validations.Add(new IsNotNullOrEmptyRule<string>   
    {   
        ValidationMessage = "A password is required."   
    });  
}

이 메서드는 IsNotNullOrEmptyRule<T> 유효성 검사 규칙을 각 ValidatableObject<T> 인스턴스의 Validations 컬렉션에 추가하고, 유효성 검사가 실패할 경우 표시될 유효성 검사 오류 메시지를 지정하는 유효성 검사 규칙의 ValidationMessage 속성 값을 지정합니다.

유효성 검사 트리거

eShopOnContainers 모바일 앱에 사용되는 유효성 검사 방법은 속성의 유효성 검사를 수동으로 트리거하고 속성이 변경되면 유효성 검사를 자동으로 트리거할 수 있습니다.

수동으로 유효성 검사 트리거

뷰 모델 속성에 대해 유효성 검사를 수동으로 트리거할 수 있습니다. 예를 들어 이는 사용자가 모의 서비스를 사용할 때 eShopOnContainers 모바일 앱에서 LoginView로그인 단추를 탭할 때 발생합니다. 명령 대리자는 LoginViewModel에서 MockSignInAsync 메서드를 호출합니다. 그러면 다음 코드 예제에 표시된 Validate 메서드를 실행하여 유효성 검사가 호출됩니다.

private bool Validate()  
{  
    bool isValidUser = ValidateUserName();  
    bool isValidPassword = ValidatePassword();  
    return isValidUser && isValidPassword;  
}  

private bool ValidateUserName()  
{  
    return _userName.Validate();  
}  

private bool ValidatePassword()  
{  
    return _password.Validate();  
}

이 메서드는 ValidateValidatableObject<T> 인스턴스에서 Validate 메서드를 호출하여 사용자가 입력한 사용자 LoginView이름 및 암호의 유효성 검사를 수행합니다. 다음 코드 예제에서는 클래스의 Validate 메서드를 ValidatableObject<T> 보여줍니다.

public bool Validate()  
{  
    Errors.Clear();  

    IEnumerable<string> errors = _validations  
        .Where(v => !v.Check(Value))  
        .Select(v => v.ValidationMessage);  

    Errors = errors.ToList();  
    IsValid = !Errors.Any();  

    return this.IsValid;  
}

이 메서드는 Errors 컬렉션을 지우고 개체의 Validations 컬렉션에 추가된 유효성 검사 규칙을 검색합니다. 검색된 각 유효성 검사 규칙에 대한 Check 메서드가 실행되고, 데이터의 유효성 검사가 실패한 모든 유효성 검사 규칙에 대한 ValidationMessage 속성 값이 ValidatableObject<T> 인스턴스의 Errors 컬렉션에 추가됩니다. 마지막으로 IsValid 속성이 설정되고 해당 값이 호출 메서드로 반환되어 유효성 검사의 성공 여부를 나타냅니다.

속성이 변경되면 유효성 검사 트리거

바인딩된 속성이 변경될 때마다 유효성 검사를 트리거할 수도 있습니다. 예를 들어 LoginView의 양방향 바인딩이 UserName 또는 Password 속성을 설정하면 유효성 검사가 트리거됩니다. 다음 코드 예제에서는 이 작업이 발생하는 방법을 보여 줍니다.

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    <Entry.Behaviors>  
        <behaviors:EventToCommandBehavior  
            EventName="TextChanged"  
            Command="{Binding ValidateUserNameCommand}" />  
    </Entry.Behaviors>  
    ...  
</Entry>

Entry 컨트롤은 ValidatableObject<T> 인스턴스의 UserName.Value 속성에 바인딩되고 컨트롤의 Behaviors 컬렉션에는 EventToCommandBehavior 인스턴스가 추가됩니다. 이 동작은 텍스트가 ValidateUserNameCommand 변경될 때 Entry 발생하는 [TextChanged] 이벤트에 대한 Entry응답으로 실행됩니다. 차례로 ValidateUserNameCommand 대리자는 ValidatableObject<T> 인스턴스에 대해 Validate 메서드를 실행하는 ValidateUserName 메서드를 실행합니다. 따라서 사용자가 사용자 이름에 대한 Entry 컨트롤에 문자를 입력할 때마다 입력한 데이터의 유효성 검사가 수행됩니다.

동작에 대한 자세한 내용은 동작 구현을 참조 하세요.

유효성 검사 오류 표시

eShopOnContainers 모바일 앱은 빨간색 선이 있는 잘못된 데이터가 포함된 컨트롤을 강조 표시하고 잘못된 데이터가 포함된 컨트롤 아래에 데이터가 잘못된 이유를 사용자에게 알리는 오류 메시지를 표시하여 유효성 검사 오류를 사용자에게 알릴 수 있습니다. 잘못된 데이터가 수정되면 줄이 검은색으로 변경되고 오류 메시지가 제거됩니다. 그림 6-2에서는 유효성 검사 오류가 있을 때 eShopOnContainers 모바일 앱의 LoginView를 보여 집니다.

Displaying validation errors during login

그림 6-2: 로그인하는 동안 유효성 검사 오류 표시

잘못된 데이터가 포함된 컨트롤 강조 표시

LineColorBehavior 연결된 동작은 유효성 검사 오류가 발생한 컨트롤을 강조 표시하는 Entry 데 사용됩니다. 다음 코드 예제에서는 연결된 동작이 LineColorBehavior 컨트롤에 Entry 연결되는 방법을 보여줍니다.

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">
    <Entry.Style>
        <OnPlatform x:TypeArguments="Style">
            <On Platform="iOS, Android" Value="{StaticResource EntryStyle}" />
            <On Platform="UWP" Value="{StaticResource UwpEntryStyle}" />
        </OnPlatform>
    </Entry.Style>
    ...
</Entry>

이 컨트롤은 Entry 다음 코드 예제에 표시된 명시적 스타일을 사용합니다.

<Style x:Key="EntryStyle"  
       TargetType="{x:Type Entry}">  
    ...  
    <Setter Property="behaviors:LineColorBehavior.ApplyLineColor"  
            Value="True" />  
    <Setter Property="behaviors:LineColorBehavior.LineColor"  
            Value="{StaticResource BlackColor}" />  
    ...  
</Style>

이 스타일은 컨트롤에 ApplyLineColorLineColor 연결된 동작 EntryLineColorBehavior 연결된 속성을 설정합니다. 스타일에 대한 자세한 내용은 스타일을 참조하세요.

연결된 속성의 ApplyLineColor 값이 설정되거나 변경 LineColorBehavior 되면 연결된 동작은 다음 코드 예제에 표시된 메서드를 실행합니다 OnApplyLineColorChanged .

public static class LineColorBehavior  
{  
    ...  
    private static void OnApplyLineColorChanged(  
                BindableObject bindable, object oldValue, object newValue)  
    {  
        var view = bindable as View;  
        if (view == null)  
        {  
            return;  
        }  

        bool hasLine = (bool)newValue;  
        if (hasLine)  
        {  
            view.Effects.Add(new EntryLineColorEffect());  
        }  
        else  
        {  
            var entryLineColorEffectToRemove =   
                    view.Effects.FirstOrDefault(e => e is EntryLineColorEffect);  
            if (entryLineColorEffectToRemove != null)  
            {  
                view.Effects.Remove(entryLineColorEffectToRemove);  
            }  
        }  
    }  
}

이 메서드의 매개 변수는 동작이 연결된 컨트롤의 인스턴스와 연결된 속성의 ApplyLineColor 이전 값과 새 값을 제공합니다. EntryLineColorEffect 연결된 속성이 있으면 클래스가 컨트롤의 Effects 컬렉션에 ApplyLineColor 추가되고true, 그렇지 않으면 컨트롤의 Effects 컬렉션에서 제거됩니다. 동작에 대한 자세한 내용은 동작 구현을 참조 하세요.

클래스 EntryLineColorEffectRoutingEffect 서브클래싱하고 다음 코드 예제에 나와 있습니다.

public class EntryLineColorEffect : RoutingEffect  
{  
    public EntryLineColorEffect() : base("eShopOnContainers.EntryLineColorEffect")  
    {  
    }  
}

클래스는 RoutingEffect 플랫폼별 내부 효과를 래핑하는 플랫폼 독립적 효과를 나타냅니다. 이는 플랫폼별 효과에 대한 형식 정보에 컴파일 시간 액세스가 없으므로 효과 제거 프로세스를 간소화합니다. 기본 EntryLineColorEffect 클래스 생성자를 호출하여 확인 그룹 이름의 연결 및 각 플랫폼별 효과 클래스에 지정된 고유 ID로 구성된 매개 변수를 전달합니다.

다음 코드 예제에서는 iOS에 대한 구현을 eShopOnContainers.EntryLineColorEffect 보여줍니다.

[assembly: ResolutionGroupName("eShopOnContainers")]  
[assembly: ExportEffect(typeof(EntryLineColorEffect), "EntryLineColorEffect")]  
namespace eShopOnContainers.iOS.Effects  
{  
    public class EntryLineColorEffect : PlatformEffect  
    {  
        UITextField control;  

        protected override void OnAttached()  
        {  
            try  
            {  
                control = Control as UITextField;  
                UpdateLineColor();  
            }  
            catch (Exception ex)  
            {  
                Console.WriteLine("Can't set property on attached control. Error: ", ex.Message);  
            }  
        }  

        protected override void OnDetached()  
        {  
            control = null;  
        }  

        protected override void OnElementPropertyChanged(PropertyChangedEventArgs args)  
        {  
            base.OnElementPropertyChanged(args);  

            if (args.PropertyName == LineColorBehavior.LineColorProperty.PropertyName ||  
                args.PropertyName == "Height")  
            {  
                Initialize();  
                UpdateLineColor();  
            }  
        }  

        private void Initialize()  
        {  
            var entry = Element as Entry;  
            if (entry != null)  
            {  
                Control.Bounds = new CGRect(0, 0, entry.Width, entry.Height);  
            }  
        }  

        private void UpdateLineColor()  
        {  
            BorderLineLayer lineLayer = control.Layer.Sublayers.OfType<BorderLineLayer>()  
                                                             .FirstOrDefault();  

            if (lineLayer == null)  
            {  
                lineLayer = new BorderLineLayer();  
                lineLayer.MasksToBounds = true;  
                lineLayer.BorderWidth = 1.0f;  
                control.Layer.AddSublayer(lineLayer);  
                control.BorderStyle = UITextBorderStyle.None;  
            }  

            lineLayer.Frame = new CGRect(0f, Control.Frame.Height-1f, Control.Bounds.Width, 1f);  
            lineLayer.BorderColor = LineColorBehavior.GetLineColor(Element).ToCGColor();  
            control.TintColor = control.TextColor;  
        }  

        private class BorderLineLayer : CALayer  
        {  
        }  
    }  
}

메서드는 OnAttached 컨트롤의 네이티브 컨트롤을 Xamarin.FormsEntry 검색하고 메서드를 호출하여 선 색을 UpdateLineColor 업데이트합니다. 재정의는 OnElementPropertyChanged 연결된 LineColor 속성이 변경되는 경우 선 색을 업데이트하거나 Height 변경 Entry 내용의 속성을 업데이트하여 컨트롤의 Entry 바인딩 가능한 속성 변경에 응답합니다. 효과에 대한 자세한 내용은 효과를 참조하세요.

유효한 데이터를 컨트롤에 Entry 입력하면 유효성 검사 오류가 없음을 나타내기 위해 컨트롤 아래쪽에 검은색 선이 적용됩니다. 그림 6-3에서는 이 예제를 보여 있습니다.

Black line indicating no validation error

그림 6-3: 유효성 검사 오류가 없음을 나타내는 검은색 선

Entry 컨트롤에 DataTrigger 컬렉션에 추가된 항목도 있습니다Triggers. 다음 코드 예제에서는 다음을 보여줍니다.DataTrigger

<Entry Text="{Binding UserName.Value, Mode=TwoWay}">  
    ...  
    <Entry.Triggers>  
        <DataTrigger   
            TargetType="Entry"  
            Binding="{Binding UserName.IsValid}"  
            Value="False">  
            <Setter Property="behaviors:LineColorBehavior.LineColor"   
                    Value="{StaticResource ErrorColor}" />  
        </DataTrigger>  
    </Entry.Triggers>  
</Entry>

이렇게 하면 DataTrigger 속성이 UserName.IsValid 모니터링되고 값이 되면 false연결된 동작의 연결된 속성 LineColorBehavior 이 빨간색으로 변경 LineColor 되는 값을 실행합니다Setter. 그림 6-4에서는 이 예제를 보여 있습니다.

Red line indicating validation error

그림 6-4: 유효성 검사 오류를 나타내는 빨간색 선

입력한 데이터가 유효하지 않은 동안 컨트롤의 Entry 줄이 다시 빨간색으로 기본, 그렇지 않으면 입력한 데이터가 유효함을 나타내기 위해 검은색으로 변경됩니다.

트리거에 대한 자세한 내용은 트리거를 참조 하세요.

오류 메시지 표시

UI는 데이터 유효성 검사가 실패한 각 컨트롤 아래에 Label 컨트롤의 유효성 검사 오류 메시지를 표시합니다. 다음 코드 예제에서는 사용자가 유효한 사용자 이름을 입력하지 않은 경우 유효성 검사 오류 메시지를 표시하는 방법을 보여 Label 줍니다.

<Label Text="{Binding UserName.Errors, Converter={StaticResource FirstValidationErrorConverter}}"  
       Style="{StaticResource ValidationErrorLabelStyle}" />

각각 Label 은 유효성을 Errors 검사하는 뷰 모델 개체의 속성에 바인딩됩니다. Errors 속성은 ValidatableObject<T> 클래스에서 제공되며 List<string> 형식입니다. Errors 속성에는 여러 유효성 검사 오류가 포함될 수 있으므로 FirstValidationErrorConverter 인스턴스를 사용하여 표시를 위해 컬렉션에서 첫 번째 오류를 검색합니다.

요약

eShopOnContainers 모바일 앱은 뷰 모델 속성의 동기 클라이언트 쪽 유효성 검사를 수행하고 잘못된 데이터가 포함된 컨트롤을 강조 표시하고 데이터가 잘못된 이유를 사용자에게 알리는 오류 메시지를 표시하여 유효성 검사 오류를 사용자에게 알릴 수 있습니다.

유효성 검사가 필요한 뷰 모델 속성은 ValidatableObject<T> 형식이며, 각 ValidatableObject<T> 인스턴스에는 해당 Validations 속성에 유효성 검사 규칙이 추가됩니다. 유효성 검사는 유효성 검사 규칙을 검색하고 ValidatableObject<T>Value 속성에 대해 해당 규칙을 실행하는 ValidatableObject<T> 인스턴스의 Validate 메서드를 호출하여 뷰 모델에서 호출됩니다. 유효성 검사 오류는 인스턴스의 ValidatableObject<T>속성에 Errors 배치되고 IsValid 인스턴스의 ValidatableObject<T> 속성은 유효성 검사 성공 또는 실패 여부를 나타내도록 업데이트됩니다.