Rohit
Rohit

Reputation: 300

Validate interface properties

I have made a interface IRequest:

public interface IRequest
{
    [DataMember(IsRequired = true)]
    string EndUserIp { get; set; }

    [DataMember(IsRequired = true)]
    string TokenId { get; set; }

    [DataMember(IsRequired = true)]
    string ClientId { get; set; }

    [DataMember(IsRequired = true)]
    int TokenAgencyId { get; set; }

    [DataMember(IsRequired = true)]
    int TokenMemberId { get; set; }
}

and I've implemented this in multiple classes; now I need to validate all the properties:

 public static bool ValidateCommon(IRequest request)
    {
        if (string.IsNullOrWhiteSpace(request.ClientId))
            throw new BusinessServiceException(ErrorType.InvalidRequest, "ClientId can not be null or Empty");
        if (string.IsNullOrWhiteSpace(request.TokenId))
            throw new BusinessServiceException(ErrorType.InValidSession, "TokenID should not be Null or Empty");
        if (!IsValidTokenId(request.TokenId))
            throw new BusinessServiceException(ErrorType.InValidSession, "TokenID is not in correct Format");
        if (string.IsNullOrWhiteSpace(request.EndUserIp))
            throw new BusinessServiceException(ErrorType.InValidIpAddress, "IP Address should not be Null or Empty");
        if (!IsValidIp(request.EndUserIp))
            throw new BusinessServiceException(ErrorType.InValidIpAddress, "IP Address is not in correct Format");
        if (request.TokenAgencyId < 0)
            throw new BusinessServiceException(ErrorType.InvalidRequest, "TokenAgencyId should be positive Integer");
        if (request.TokenMemberId <= 0)
            throw new BusinessServiceException(ErrorType.InvalidRequest, "TokenMemberId should be positive Integer");
        return true;
    }

But I don't want to write this method again and again. So what is the right approach to do the same?

Upvotes: 4

Views: 735

Answers (2)

NeddySpaghetti
NeddySpaghetti

Reputation: 13495

You can use Code Contracts to define some pre-conditions, post-conditions and invariants for your interface. I am not an expert but should be able to do something like this:

[ContractClass(typeof(IRequestContract))]
public interface IRequest
{
    [DataMember(IsRequired = true)]
    string EndUserIp { get; set; }

    [DataMember(IsRequired = true)]
    string TokenId { get; set; }

    [DataMember(IsRequired = true)]
    string ClientId { get; set; }

    [DataMember(IsRequired = true)]
    int TokenAgencyId { get; set; }

    [DataMember(IsRequired = true)]
    int TokenMemberId { get; set; }
}


[ContractClassFor(typeof(IRequest))]
internal abstract class IRequestContract : IRequest
{
    string EndUserIp
    { 
        get
        {
            return null;
        }
        set
        {
            Contract.Requires<BusinessServiceException>(!string.IsNullOrWhiteSpace(value), "IP Address should not be Null or Empty");
            Contract.Requires<BusinessServiceException>(!IsValidIp(request.EndUserIp, "IP Address is not in correct Format");
        }
    }

    string TokenId 
    { 
        get
        {
            return null;
        }
        set
        {
            Contract.Requires<BusinessServiceException>(!string.IsNullOrWhiteSpace(value), "TokenID should not be Null or Empty");
            Contract.Requires<BusinessServiceException>(!IsValidTokenId(request.TokenId), "TokenID is not in correct Format");
        }
    }

    string ClientId 
    { 
        get
        {
            return null;
        }

        set
        {
            Contract.Requires<BusinessServiceException>(!string.IsNullOrWhiteSpace(value), "ClientId can not be null or Empty");
        }
    }

    int TokenAgencyId 
    { 
        get
        {
            return default(int);
        }
        set
        {
            Contract.Requires<BusinessServiceException>(value < 0, "TokenAgencyId should be positive Integer");
        }
    }

    int TokenMemberId 
    { 
        get
        {
            return null;
        }
        set
        {
             Contract.Requires<BusinessServiceException>(value < 0, "TokenMemberId should be positive Integer");
        }
    }
}

Will just need to find a way to pass the error code to the BusinessServiceEXception somehow.

Upvotes: 0

samy
samy

Reputation: 14962

Create an interface called IRequestValidator with a function called Validate taking a IRequest. Implement the interface and instantiate / inject the component when you need to validate your IRequest.

This way you get the validation system in one place AND a way to swap it easily at a later time (if you inject your component; if not please use a factory pattern to avoid hardcoding the new call to your component in your code).

public interface IRequestValidator {
    bool Validate(IRequest req);
}

// at first you have one way of validating elements

public class AllWelcomeValidator: IRequestValidator {
    public bool Validate(IRequest req) {return true; // no validation atm }
}

// later...

public class NowWeGotRulesValidator: IRequestValidator {
    public bool Validate(IRequest req) {
        if (string.IsNullOrWhiteSpace(request.ClientId))
            throw new BusinessServiceException(ErrorType.InvalidRequest, "ClientId can not be null or Empty");
        // etc...
    }
}

Upvotes: 2

Related Questions