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;


}



Tuesday, August 16, 2011

Creating Database In CouchDB using LoveSeat (C#)

Getting Started with CouchDB using Loveseat C#
We all know that there is very limited resources to help Implementing CouchDB using c#. as far as i feel Love Seat is the best.

Here are i am going to discuss very basic thing.
How to create Database in CouchDB using Loveseat c#.net

First step:
we have to create a connection to Couchdb database.

CouchClient ccAdmin = new CouchClient("localhost", 5984, null, null);

In the above code i am passing username and password as null. if you have installed couch db recently then every user will be considered as admin user as long as you have created a new user.

If you have username and password with you the pass them while creating couch client instance.

Here in the following code i am checking for the database existence before creating it.
Note: CouchDB is case sensitive we should not user UpperCase (Capital Letters) while creating database. ("Database1" is wrong syntax! it has to be "database1")

string dbname = "database1";
if (!ccAdmin.HasDatabase(dbname))
{
ccAdmin.CreateDatabase(dbname);
}



Tuesday, August 9, 2011

WPF and Silverlight Validation using IDataErrorInfo

How to validate WPF or Silverlight Form or Page..?
Validations in wpf
There are several ways to validate a WPF or Silverlight form and IDataError Info is the one of the interesting way to do validations.

IDataErrorInfo is a part of System.dll Assembly.

this interface contains couple of properties which we have to override in our implementation.

1) string Error { get; }

2) string this[string columnName] { get; }

out of these two properties the second property is an Index.
(you can learn more about indexers here: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx)

Here is a sample which will give some information about the implementation of IDataErrorInfo.

Here I am creating a user Class which implements IDataErrorInfo.



public class User : ViewModelbase, IDataErrorInfo
{
private string firstName;

public string FirstName
{
get { return firstName; }
set { firstName = value;
OnPropertyChanged("FirstName");
}
}

private string lastName;

public string LastName
{
get { return lastName; }
set
{
lastName = value;
OnPropertyChanged("LastName");
}
}


#region IDataErrorInfo Members

public string Error
{
get { throw new NotImplementedException(); }
}

public string this[string columnName]
{
get
{
string result = null;
if (columnName == "FirstName")
{
if (string.IsNullOrEmpty(FirstName))
result = "Please enter a First Name";
}
if (columnName == "LastName")
{
if (string.IsNullOrEmpty(LastName))
result = "Please enter a Last Name";
}

return result;
}
}

#endregion

}


You can observe the public string this[string columnName] property which contains if condition for Firstname and lastname.. when ever we there is a property changed notification then this indexer will get initiated and checks for the valid value and the value it returned will appear as error message.

Implementing the following style will give error template to a text box whenever validation returns error message

Wednesday, July 27, 2011

What is Parallel keyword and how it works in c# 4

in this sample i am going to discuss what Parallel.ForEach will do...

Here i am creating a list of strings and using parallel foreach making a call to the method which is in server class.

and in our output you can observer the order of the elements. they are not in any particular order...

Because parallel foreach internally create a separate thread for each and every call. which will behave independently.. means each and every request will be handled asynchronously where Normal foreach is Synchronous behavior..

Note:
It is really tough to debug the calls that make in the Parallel.Foreach..

List list = new List();
for (int i = 0; i < 5; i++)
{
list.Add("list item" + i.ToString());
}
Server server = new Server();
Parallel.ForEach(list, (i) => { server.GetDetails(i); });
Console.Read();


public class Server
{
public void GetDetails(dynamic item)
{
for (int i = 0; i < 3; i++)
{
Console.WriteLine("Request :: " + i + " " + item.ToString());
}
}
}



OutPut
Request :: 0 list item4
Request :: 1 list item4
Request :: 2 list item4
Request :: 0 list item1
Request :: 1 list item1
Request :: 0 list item2
Request :: 1 list item2
Request :: 2 list item2
Request :: 0 list item3
Request :: 1 list item3
Request :: 2 list item3
Request :: 0 list item0
Request :: 1 list item0
Request :: 2 list item0
Request :: 2 list item1