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

Monday, July 25, 2011

How dynamic in c# 4.0 works

In this Post i will try to give an idea what "dynamic" keyword do.

Have a loot at the following Program class, in the constructor of the program class i am calling StartDeveloperWork and StartDynamicWork methods by passing similar objects in the order.



class Program
{

public Program()
{
//Case 1
StartDeveloperWork(new Developer());
StartDeveloperWork(new ASPNetDeveloper());
StartDeveloperWork(new WPFDeveloper());

//Case 2
StartDynamicWork(new Developer());
StartDynamicWork(new ASPNetDeveloper());
StartDynamicWork(new WPFDeveloper());
}

public void StartWork(Developer d)
{
d.Work();
}

public void StartWork(dynamic d)
{
d.Work();
}
}


class WPFDeveloper : Developer
{
public void Work()
{
Console.Write("WPFDeveloper ");
}
}

class ASPNetDeveloper : Developer
{
public void Work()
{
Console.Write("ASPNetDeveloper ");
}
}

class Developer
{
public void Work()
{
Console.Write("Developer ");
}
}


but the out put displayed for startdeveloperwork will be
Developer
Developer
Developer


and out put displayed for StartDynamicWork will be

Developer
ASPNetDeveloper
WPFDeveloper

.. because we in Developer class we have not marked work method as Virtual so when we are calling with base class reference the method in the base calls will be called.

in the StartDeveloperWork method we are using base class reference for calling work method.

coming to StartDynamicWork we are using dynamic keywork means the type of object will be decided at runtime. so method in the passed object will be called.
if the method is not there in the passed object then it will go to base class for the same method. if the method is not there in base class also then it will throw an target invocation exception.

So be care full and make yourself clear when to use and when not to use

WPF: Build Responsive UI (Threading)

I am going to explain how to build responsive user Interface. Implementing threading in WPF.. and this post may help the people who is getting "The calling thread cannot access this object because a different thread owns it" exception

The most frequent problem or situation wpf developers face is Blocked UI.
This solution also works for "calling thread cannot access this object because a different thread owns it" exception.
when we are pooling some data to/from the server wpf UI will get hangs which will question the capability of WPF.

here i will try to explain how to use thread to overcome this.

In the following code i am creating new instance for task factory and starting a new task.
so all the code we pass in the factory will run in the background..

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
});


After looking the above the first question comes in mind is Can i update UI from this task or thread.?
and the answer is NO You can't update UI from the background thread.
for updating UI you have to take the control to the Dispatcher thread.
some thing like this.

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UI Related stuff
});
});


We learned how to execute a task in background and how to update UI from that thread.

Now let us discuss about how to execute the task and some other code synchronously.

Consider this scenario.
we have to get some data from the server and after that we have play with data.
means our next action is completely dependent on the callback or completion of Task.

in this case we can use task factory ContinueWith method like following

TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
// DO YOUR SERVER CALLS or SOMETHING which you want to run in the background
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UI Related stuff
});
}).ContinueWith(t =>
{
if (t.IsFaulted)
{
throw t.Exception;
}
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// do some thig after task completion
});
});


Now i am putting all the three scenario in one place with simple example

ObservableCollection images = new ObservableCollection();
TaskFactory tFactory = new TaskFactory();
tFactory.StartNew(() =>
{
for (int i = 0; i < 50; i++)
{
//GET IMAGE Path FROM SERVER
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
// UPDATE PROGRESS BAR IN UI
});

images.Add(("");
}

}).ContinueWith(t =>
{
if (t.IsFaulted)
{
// EXCEPTION IF THREAD IS FAULT
throw t.Exception;
}
System.Windows.Application.Current.Dispatcher.BeginInvoke((Action)delegate()
{
//PROCESS IMAGES AND DISPLAY
});
});


AppDomain.CurrentDomain.SetData("SQLServerCompactEditionUnderWebHosting", true);