문제

설명

내 솔루션에는이 프로젝트가 있습니다.

  • = 수정 된 엔티티 프레임 워크
  • DTO = 스스로를 검증 할 수있는 데이터 전송 개체
  • Bl = 비즈니스 계층 서비스
  • 편물 = 프리젠 테이션 ASP.NET MVC 응용 프로그램

Dal, Bl 및 Web 모든 참조 DTO.
프로세스는 일반적으로 다음과 같은 방식으로 실행됩니다.

  1. 웹 요청이 웹에 이루어집니다
  2. Web은 DTOS를 게시합니다
    • DTOS는 사용자 정의 액션 필터를 통해 자동으로 검증됩니다
    • 유효성 검사 오류가 자동으로 수집됩니다
  3. (유효성이 괜찮아) 웹 호출 BL로 DTOS를 제공합니다.
  4. BL은 DTOS를 사용하여 DAL으로 전화를 걸어 (통과하거나 사용할 수 있음)

그런 다음 DTO 유효성 검사 문제 ...

내 DTO는 자신의 상태 (속성의 값)에 따라 스스로를 검증 할 수 있습니다. 그러나 지금 당장 나는 이것이 사실이 아닌 경우 문제를 제시하고 있습니다. BL (그리고 결과적으로 dal)을 사용하여 검증해야합니다.

내 실제 예: 사용자 등록 및 웹은 검증 된 사용자 DTO를 가져옵니다. 문제가있는 부분은입니다 username 확인. 독창성은 데이터 저장소에 대해 확인해야합니다.
어떻게해야합니까?

모든 DTO가 인터페이스를 구현한다는 추가 정보가 있습니다 (즉. User DTO 구현 IUser) IOC 목적 및 TDD 용. 둘 다의 일부입니다 DTO 프로젝트.

불가능한 시도

  1. 원형 참조를 얻을 수 있기 때문에 DTO에서 BL을 참조 할 수 없습니다.
    Compilation error
  2. 부분 DTO 클래스를 참조하고 그 유효성 검사를 구현하는 추가 DTO.VAL 프로젝트를 만들 수 없습니다 (BL + DTO 참조).
    Partial classes can't span assemblies.

가능한 시도

  1. 스페셜을 만듭니다 ActionFilter 이는 외부 조건에 대한 객체를 검증합니다. 이것은 내부에서 만들어 질 것입니다 웹 프로젝트 따라서 여기에 사용될 DTO와 BL을 보게됩니다.
  2. DTOS를 BL에 넣고 DTO 인터페이스를 다른 프로젝트에서 참조하는 실제 DTO로 유지하고 모든 코드를 콘크리트 클래스 대신 인터페이스를 사용하도록합니다.
  3. 외부 의존적 검증을 처리하지 말고 외부 종속성이 예외를 던지도록합니다. 최악의 이 문제에 대한 해결책

무엇을 제안 하시겠습니까?

도움이 되었습니까?

해결책 4

결과 솔루션

결국 객체 자체에서 얻을 수없는 외부 요인에 대해 객체를 검증 할 수있는 컨트롤러 동작 필터를 사용했습니다.

액션 매개 변수의 이름을 선택하여 해당 매개 변수를 검증 할 수있는 유효성 검사기 유형을 확인하는 필터를 만들었습니다. 물론이 유효성 검사기는 모든 인터페이스를 구현하여 모두 재사용 할 수 있도록해야합니다.

[ValidateExternalFactors("user", typeof(UserExternalValidator))]
public ActionResult Create(User user)

유효성 검사기는이 간단한 인터페이스를 구현해야합니다

public interface IExternalValidator<T>
{
    bool IsValid(T instance);
}

겉보기에 복잡한 문제에 대한 간단하고 효과적인 솔루션입니다.

다른 팁

나는 지난 주 정도만 시험을 치른 실험을 제안합니다.

기반 이 영감 나는 DataAnnotations 접근하다. 샘플 DTO :

public class Contact : DomainBase, IModelObject
{
    public int ID { get; set; }
    public string Name { get; set; }
    public LazyList<ContactDetail> Details { get; set; }
    public DateTime Updated { get; set; }


    protected override void ConfigureRules()
    {
        base.AddRule(new ValidationRule()
        {
            Properties = new string[] { "name" },
            Description = "A Name is required but must not exceed 300 characters in length and some special characters are not allowed",
            validator = () => this.Name.IsRequired300LenNoSpecial()
        });

        base.AddRule(new ValidationRule()
        {
            Properties = new string[] { "updated" },
            Description = "required",
            validator = () => this.Updated.IsRequired()
        });
    }
}

이것은보다 더 많은 일을 보일 수 있습니다 DataAnnotations 그리고 글쎄, 그것은 그게 코즈이지만 크지는 않습니다. 나는 그것이 수업에서 더 선물 할 수 있다고 생각합니다 (지금은 정말 못생긴 DTO 수업이 있습니다. DataAnnotations 속성 - 더 이상 속성을 볼 수 없습니다). 그리고이 응용 프로그램에서 익명 대표의 힘은 거의 책 가치가 있습니다 (그래서 나는 발견하고 있습니다).

기본 클래스 :

public partial class DomainBase : IDataErrorInfo
{
    private IList<ValidationRule> _rules = new List<ValidationRule>();

    public DomainBase()
    {
        // populate the _rules collection
        this.ConfigureRules();
    }

    protected virtual void ConfigureRules()
    {
        // no rules if not overridden
    }

    protected void AddRule(ValidationRule rule)
    {
        this._rules.Add(rule);
    }





    #region IDataErrorInfo Members

    public string Error
    {
        get { return String.Empty; }    // Validation should call the indexer so return "" here
    }                                   // ..we dont need to support this property.

    public string this[string columnName]
    {
        get
        {
            // get all the rules that apply to the property being validated
            var rulesThatApply = this._rules
                .Where(r => r.Properties.Contains(columnName));

            // get a list of error messages from the rules
            StringBuilder errorMessages = new StringBuilder();
            foreach (ValidationRule rule in rulesThatApply)
                if (!rule.validator.Invoke())   // if validator returns false then the rule is broken
                    if (errorMessages.ToString() == String.Empty)
                        errorMessages.Append(rule.Description);
                    else
                        errorMessages.AppendFormat("\r\n{0}", rule.Description);

            return errorMessages.ToString();
        }
    }

    #endregion
}

ValidationRule 그리고 내 검증 기능 :

public class ValidationRule
{
    public string[] Properties { get; set; }
    public string Description { get; set; }
    public Func<bool> validator { get; set; }
}


/// <summary>
/// These extention methods return true if the validation condition is met.
/// </summary>
public static class ValidationFunctions
{
    #region IsRequired

    public static bool IsRequired(this String str)
    {
        return !str.IsNullOrTrimEmpty();
    }

    public static bool IsRequired(this int num)
    {
        return num != 0;
    }

    public static bool IsRequired(this long num)
    {
        return num != 0;
    }

    public static bool IsRequired(this double num)
    {
        return num != 0;
    }

    public static bool IsRequired(this Decimal num)
    {
        return num != 0;
    }

    public static bool IsRequired(this DateTime date)
    {
        return date != DateTime.MinValue;
    }

    #endregion


    #region String Lengths

    public static bool IsLengthLessThanOrEqual(this String str, int length)
    {
        return str.Length <= length;
    }

    public static bool IsRequiredWithLengthLessThanOrEqual(this String str, int length)
    {
        return !str.IsNullOrTrimEmpty() && (str.Length <= length);
    }

    public static bool IsRequired300LenNoSpecial(this String str)
    {
        return !str.IsNullOrTrimEmpty() &&
            str.RegexMatch(@"^[- \r\n\\\.!:*,@$%&""?\(\)\w']{1,300}$",
                RegexOptions.Multiline) == str;
    }

    #endregion

}

내 코드가 지저분 해 보이면 지난 며칠 동안이 유효성 검사 방식 만 작업했기 때문입니다. 몇 가지 요구 사항을 충족하려면이 아이디어가 필요합니다.

  • 나는 그것을 지원해야한다 IDataErrorInfo 내 MVC 레이어가 자동으로 확인되도록 인터페이스
  • 복잡한 검증 시나리오를 지원할 수 있어야합니다 (질문의 요점) : 동일한 객체 (예 : startDate 및 finishDate)에서 여러 속성에 대해 검증 할 수 있기를 원합니다. 객체 그래프에있는 것처럼 다른/다중/관련 객체의 속성; 그리고 내가 아직 생각하지 않은 다른 것들조차도.
  • 둘 이상의 재산에 적용되는 오류에 대한 아이디어를 지원해야합니다.
  • 내 TDD 및 DDD 여정의 일환으로 도메인 개체가 서비스 계층 방법보다 내 '도메인'을 더 많이 설명하기를 원하므로 이러한 복잡한 조건을 모델 객체 (DTOS 아님)에 넣는 것 같습니다.

이 접근법은 내가 원하는 것을 얻을 것이라고 생각합니다.

당신이 나와 함께 우리와 함께 우리가 '우리 자신에 의해'될 것이라는 것이 나와 함께 탑승한다면 상상할 것입니다. 그러나 그것은 그만한 가치가있을 것입니다. 나는에 대해 읽고 있었다 MVC 2의 새로운 검증 기능 그러나 여전히 사용자 정의 수정없이 위의 위시리스트를 충족시키지 못합니다.

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

S#ARP 아키텍처에는 클래스 레벨 유효성 검사기 [hasuniquedomainsignature]와 함께 사용 된 [DomainsIgnature] 메소드 식별자가 작업을 수행 할 것입니다. 아래 샘플 코드를 참조하십시오.

[HasUniqueDomainSignature]
public class User : Entity
{
    public User()
    {
    }

    public User(string login, string email) : this()
    {
        Login = login;
        Email = email;
    }

    [DomainSignature]
    [NotNullNotEmpty]
    public virtual string Login { get; set; }

    [DomainSignature]
    public virtual string Email { get; set; }

}

자세히 살펴보십시오 http://www.sharparchitecture.net/

나는이 똑같은 문제를 겪었고 며칠과 며칠 동안 주변의 작업을 찾으려고 노력한 후 DTO, DAL 및 BL을 하나의 라이브러리로 통합했습니다. 프레젠테이션 레이어를 별도로 보관했습니다. 그것이 당신을위한 옵션인지 확실하지 않습니다. 저에게는 데이터 저장소를 변경할 수있는 기회가 매우 적으므로 별도의 계층이 실제로 필요하지 않았다고 생각했습니다.

또한 모든 DTO 유효성 검사에 대한 Microsoft Validation Application 블록도 구현했습니다. 그들은 복잡한 검증을 수행 할 수있는 "자체 검증"방법이 있습니다.

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