Wednesday, September 14, 2011

Custom Validation Attributes


while using data annotation we face difficulty for adding validation for Min and max value or for Start date and End Date. 
Validation attributes for min and Max, Startdate and Enddate
i have created Custom validation attributes which will deal with min and max values and datetime as well.

Lessthan validation attribtue 

[AttributeUsage(AttributeTargets.Property)]
  public class Lessthan : ValidationAttribute
    {
        private readonly string _dependentFieldName;
        private readonly bool _considerEqualValue;
        private PropertyType _propertyType;

        #region Constructors
        public Lessthan(string propertyName)
            : this(PropertyType.Numeric)
        {
            _dependentFieldName = propertyName;
        }

        public Lessthan(string propertyName, bool considerEqualValue)
            : this(propertyName, PropertyType.Numeric)
        {
            _considerEqualValue = considerEqualValue;
        }

        public Lessthan(string propertyName, PropertyType propertyType)
            : this(propertyType)
        {
            _dependentFieldName = propertyName;
        }

        public Lessthan(string propertyName, bool considerEqualValue, PropertyType propertyType)
            : this(propertyName, propertyType)
        {
            _considerEqualValue = considerEqualValue;
        }

        private Lessthan(PropertyType propertyType)
        {
            _propertyType = propertyType;
        }
        #endregion

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return new ValidationResult(base.ErrorMessage);
            PropertyInfo dependentProperty = validationContext.ObjectType.GetProperty(_dependentFieldName);
            if (dependentProperty == null)
                throw new ValidationException("No property found " + _dependentFieldName);
            switch (_propertyType)
            {
                case PropertyType.Numeric:

                    double currentAttributeValue;
                    if (!double.TryParse(value.ToString(), out currentAttributeValue))
                    {
                        throw new ValidationException("Numeric Value Expected");
                    }
                    double _dependentFieldValue;
                    var dval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!double.TryParse(dval.ToString(), out _dependentFieldValue))
                    {
                        throw new ValidationException("Numeric Value Expected for" + _dependentFieldName);
                    }

                    if (currentAttributeValue < _dependentFieldValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentAttributeValue <= _dependentFieldValue)
                        return ValidationResult.Success;
                    return new ValidationResult(base.ErrorMessage);

                case PropertyType.DateTime:

                    DateTime currentValue;
                    if (!DateTime.TryParse(value.ToString(), out currentValue))
                    {
                        throw new ValidationException("DateTime type Expected");
                    }
                    DateTime _dependentFieldDTValue;
                    var dtval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dtval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!DateTime.TryParse(dtval.ToString(), out _dependentFieldDTValue))
                    {
                        throw new ValidationException("DateTime type Expected" + _dependentFieldName);
                    }

                    if (currentValue < _dependentFieldDTValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentValue <= _dependentFieldDTValue)
                        return ValidationResult.Success;
                    return new ValidationResult(base.ErrorMessage);
                default:
                    return ValidationResult.Success;
            }

        }
    }




Greater than validation attribute

[AttributeUsage(AttributeTargets.Property)]
    public class Greaterthan : ValidationAttribute
    {
        private readonly string _dependentFieldName;
        private readonly bool _considerEqualValue;
        private PropertyType _propertyType;

        public Greaterthan(string propertyName)
            : this(PropertyType.Numeric)
        {
            _dependentFieldName = propertyName;
        }

        public Greaterthan(string propertyName, PropertyType propertyType)
            : this(propertyType)
        {
            _dependentFieldName = propertyName;
        }

        public Greaterthan(string propertyName, bool considerEqualValue)
            : this(propertyName)
        {
            _considerEqualValue = considerEqualValue;
        }

        public Greaterthan(string propertyName, bool considerEqualValue, PropertyType propertyType)
            : this(propertyName, propertyType)
        {
            _considerEqualValue = considerEqualValue;
        }

        private Greaterthan(PropertyType propertyType)
        {
            _propertyType = propertyType;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            if (value == null)
                return new ValidationResult(base.ErrorMessage);
            PropertyInfo dependentProperty = validationContext.ObjectType.GetProperty(_dependentFieldName);
            if (dependentProperty == null)
                throw new ValidationException("No property found " + _dependentFieldName);

            switch (_propertyType)
            {
                case PropertyType.Numeric:
                    double currentAttributeValue;
                    if (!double.TryParse(value.ToString(), out currentAttributeValue))
                        throw new ValidationException("Numeric Value Expected");

                    double _dependentFieldValue;
                    var dval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!double.TryParse(dval.ToString(), out _dependentFieldValue))
                    {
                        throw new ValidationException("Numeric Value Expected for" + _dependentFieldName);
                    }

                    if (currentAttributeValue > _dependentFieldValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentAttributeValue >= _dependentFieldValue)
                        return ValidationResult.Success;

                    return new ValidationResult(base.ErrorMessage);
                case PropertyType.DateTime:
                    DateTime currentValue;
                    if (!DateTime.TryParse(value.ToString(), out currentValue))
                        throw new ValidationException("DateTime Type Expected");

                    DateTime _dependentValue;
                    var dtval = dependentProperty.GetValue(validationContext.ObjectInstance, null);
                    if (dtval == null)
                        return new ValidationResult(base.ErrorMessage);
                    if (!DateTime.TryParse(dtval.ToString(), out _dependentValue))
                    {
                        throw new ValidationException("DateTime Type Expected for" + _dependentFieldName);
                    }

                    if (currentValue > _dependentValue)
                        return ValidationResult.Success;

                    if (_considerEqualValue && currentValue == _dependentValue)
                        return ValidationResult.Success;

                    return new ValidationResult(base.ErrorMessage);
                default:
                    return ValidationResult.Success;
            }

        }
    }

Monday, September 12, 2011

Named and Optional Parameters C# 4.0 Feature

Optional parameter and name parameters are 2 different features in c# 4.0.

let us first discuss optional parameters.
let us consider we have write few method to add 2,3 and 4 numbers.

what we used to this is writing overload method with same name and different parameters.

some thing like this
public int Add(int a, int b)
{
//logic
}
public int Add(int a, int b, int c)
{
//logic
}
public int Add(int a, int b, int c, int d)
{
//logic
}

Now with optional parameters we can simple write one single method to handle this method over loading situation


public int Add(int a, int b, int c = 0, int d = 0)
{
}


in the above code we have given default values to c and d means while calling this method if we don't pas parameter for c and d then 0 will be consider as default value so here C and D are optional parameters.

Add(1, 2); //c and d are optional
Add(1, 2, 3); // d is optional
Add(1, 2, 3, 4);

Coming to named parameters

let us consider we are creating employee details

public void CreateEmployee(string name, int age = 22,string address = "Not specified");

with named parameters we call call this method irrespective of order of the parametes

CreateEmployee("Venkatesh", age: 28);
CreateEmployee(address: "Hyderabad", name: "Venkatesh");

Friday, September 2, 2011

Fix for Loveseat CouchDB Login Session Issue

There is a bug in CouchDB (love seat) regarding maintaining user session..

In CouchBase.cs class the method GetSession is not returning the value it has created in cookie. it is simply returning "cookie" from that method... which is always null.. it leads to user expiry immediatly after login though that use session is ready in cookie...

delete that method from you couchbase and use the following method

protected Cookie GetSession()
{
var cookie = cookiestore["authcookie"];

if (cookie != null)
return cookie;

if (string.IsNullOrEmpty(username)) return null;
var request = new CouchRequest(baseUri + "_session");
var response = request.Post()
.ContentType("application/x-www-form-urlencoded")
.Data("name=" + username + "&password=" + password)
.GetResponse();

var header = response.Headers.Get("Set-Cookie");
if (header != null)
{
var parts = header.Split(';')[0].Split('=');
var authCookie = new Cookie(parts[0], parts[1]);
authCookie.Domain = response.Server;
cookiestore.Add("authcookie", authCookie, TimeSpan.FromMinutes(9));
}
return cookiestore["authcookie"];
}

Creating Database admin user In CouchDB using LoveSeat (C#)


Here is a method for LoveSeat Api which will create a database admin used for Couch DB

Copy this method to CouchClient.cs in loveseat api and it is ready to use....

make sure to create couch DB connection with admin privileges to use this method




public JObject CreateDatabaseAdminUser(string username, string database)
{


var security = @"{""admins"":{""names"":[""%name%""],""roles"":[]},""readers"":{""names"":[""%name%""],""roles"":[]}}".Replace("%name%", username).Replace("\r\n", "");
var docResult = GetRequest(baseUri + "/" + database + "/_security")
.Put().Json().Data(security).GetResponse().GetJObject();
return docResult;


}