TopMenu

Using generic List as key in Dictionaries

Dictionaries in CSharp are datastructure which represents hash maps. You can store key value based data easily also it prevents to insert duplicate keys. But sometime it comes as requirement where you have a list of items which you want to use as a key in dictionary. The following wouldn’t be so common and only occur rare but it’s a possibility that you would also face the same situation so I came to share the same with you guys.

Problem: Now here the trouble starts. If you use generic list as key the default equality comparer checks for default has and simple object reference equality in Dictionary for keys. Now for two similar lists with similar underlying items would result in getting those two lists as different items. Which means you can add the two lists with similar items in Dictionary as a key with no objection. But what is benefit of using Dictionary then?

Solution: There’s an overload of constructor of Dictionary which accepts the custom Equality comparer for keys. So I’ve created custom equality comparer and it was also tricky to write that custom comparer.

So implementation of the custom equality comparer would look something like:

public class ListComparer<T> : IEqualityComparer<List<T>> where T:class 
{
    public bool Equals(List<T> x, List<T> y)
    {
        if (x.Count == y.Count)
        {
            for (int i = 0; i < x.Count; i++)
            {
                // Compare the objects based on values
                if (!(x[i] as T).PublicInstancePropertiesEqual(y[i] as T))
                {
                    return false;
                }
            }
        }
 
        return true;
    }
 
    public int GetHashCode(List<T> obj)
    {
        int hash = 19;
 
        foreach (T t in obj)
        {
            foreach (var objProperty in t.GetType().GetProperties())
            {
                if (objProperty.GetType().IsClass)
                {
                    hash ^= (hash * 31) + objProperty.SafeGetHashCode();
                }
                else
                {
                    hash ^= (hash * 31) + objProperty.GetHashCode();
                }
            }
        }
 
        return hash;
    }
}

Now why I have to write so much custom code in the Equals and GetHashCode method. If I use simple and direct solution then these list will always be different. So I have to XOR the hashcode of underlying items in both lists to get the hashcode based on the items rather than list reference. I found dealing with Hashcode from John Skeet’s post on stackoverlflow.


For equals method, I need to compare the values of the public properties of the list items as the reference would be different so again we felt into the same situation. But after comparing the values and hashcode individually for each item of list we can ensure if we’re not adding similar stuff again and again in the dictionary.


Here’s the Extension methods used in the custom Eqality comparer.



public static class EqualityExtension
{
    public static int SafeGetHashCode<T>(this T value) where T : class
    {
        return value == null ? 0 : value.GetHashCode();
    }
 
    public static bool PublicInstancePropertiesEqual<T>(this T self, T to, params string[] ignore) where T : class
    {
        if (self != null && to != null)
        {
            var type = typeof(T);
            var ignoreList = new List<string>(ignore);
            var unequalProperties =
                from pi in type.GetProperties(BindingFlags.Public | BindingFlags.Instance)
                where !ignoreList.Contains(pi.Name)
                let selfValue = type.GetProperty(pi.Name).GetValue(self, null)
                let toValue = type.GetProperty(pi.Name).GetValue(to, null)
                where selfValue != toValue && (selfValue == null || !selfValue.Equals(toValue))
                select selfValue;
            return !unequalProperties.Any();
        }
        return self == to;
    }
}

Hope you enjoyed the article.


For complete code sample download it form here.


References:

How to hard reset the Canvas 4 Android

I’ve been using the Micromax Canvas4 from few months. There was an update from Gmail app and I downloaded and installed it. Then It asked me to “AutoSyncOption” to set to “ON” and I clicked “OK”. Later the device was in a restart loop after every 3-4 second. It’s like a mess for me as I bought it recently. Later I had to hard reset the device to factory setting and wiped all the data. Then It worked like a charm. I’ll share the steps but do it at you own risk but it worked for me.

How to Hard Reset the Canvas 4 Android device:

1. Switch off the device and then Boot it with holding volume up + volume down + unlock key together.

image

2. Now it will start booting when I vibrates first time release the key and It’ll start in the boot mode.

3. Now select the RecoveryMode. You can navigate through the option via volume up & down key and select the option by “Option/Menu”  button.

image

4. It’ll further go to another option menu. Now navigate to select the Wipe user data/Factory Reset option and select ok by Menu key.

5. Now this will start restoring to it’s factory setting*(state of the device when you purchased it).

6. When the reset will finish it’ll go back to the menu again. Now navigate to the Restart the device by selecting Restart option and click ok.

Now your device will be restarted and will be running again.

Warning/Disclaimer: Do this at your own risk. It worked perfectly for me.

EF4 using TableValue type in Storeprocedure

The EF5 has been released with .Net framework 4.5 and now it’s supporting the user defined table valued types as parameter in stored procedure. In earlier versions of Entity framework it was not supported. For e.g. EF4 is widely being used with .net framework 4.0. And these types are not supported in that version. Even some people raise a User voice ticket for the same but none action has been taken and ticket was closed since this feature is shipped with .net 4.5.

For those who can not migrate to 4.5 and are looking for a work around how to work with these kinda stored procedures. I’ve created a work around solution for that. Let’s take some database test objects.

Table:

CREATE TABLE [dbo].[testTable](
[mID] [uniqueidentifier] NOT NULL,
[nID] [int] NOT NULL,
[Desc] [varchar](2000) NOT NULL,
PRIMARY KEY CLUSTERED
(
[mID] ASC,
[nID] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

User Defined Table Type:
CREATE TYPE [dbo].[tbltypeTestTable] AS TABLE(
[mID] [uniqueidentifier] NULL,
[nID] [int] NULL,
[Desc] [varchar](2000) NULL
)

Multi Row Insert stored procedure:

CREATE PROCEDURE [dbo].[Insert_TableValuedTypeData]
@Paramtable dbo.[tbltypeTestTable] READONLY

AS
begin

merge dbo.testTable as target
using ( select mID, nID, [Desc]
from @Paramtable) as source
on ( target.mID = source.mID and target.nID = source.nID)
when matched then
update set target.[Desc] = source.[Desc]
when not matched then
insert values (source.mID,source.nID,source.[Desc]);


return @@error
end

Now if you try to generate the model from database this StoredProcedure will not be listed even if you use FunctionImport to call the stored procedure. Now to workaround I’ve created a custom class that executes this stored procedure as a Sql statement from DBContext object.

 

Extension method:
public static class DbContextExtension
{
// Extension method of DbContext object
public static void ExecuteStoreProcedure(this DbContext @this, string storeProcName, params object[] parameters)
{
string command = "EXEC " + storeProcName + " @Paramtable";

@this.Database.ExecuteSqlCommand(command, parameters);
}
}

Now we’ll look at the class that will prepare the data and pass it to this extension method to execute.

 

Callee:
public class mnEntity
{
public bool AddMultipleRecords()
{

Test_Entities testEntities = new Test_Entities();

var dt = new DataTable();
dt.Columns.Add("mID");
dt.Columns.Add("nID");
dt.Columns.Add("Desc");

dt.Rows.Add(Guid.NewGuid(), 1, "Test2");
dt.Rows.Add(Guid.NewGuid(), 2, "Test2");
dt.Rows.Add(Guid.NewGuid(), 3, "Test2");
dt.Rows.Add(Guid.NewGuid(), 4, "Test2");
dt.Rows.Add(Guid.NewGuid(), 5, "Test2");

var items = new SqlParameter("Paramtable", SqlDbType.Structured);
items.Value = dt;
items.TypeName = "dbo.tbltypeTestTable";

testEntities.ExecuteStoreProcedure("Insert_TableValuedTypeData", items);

return true;
}

Now let’s test this method if it work’s and call the SP with multiple values insertion:

 

Main:
static void Main(string[] args)
{
mnEntity entity = new mnEntity();
try
{
entity.AddMultipleRecords();
Console.WriteLine("Success!!!");
}
catch (Exception exception)
{
Console.WriteLine(exception);
}

Console.Read();
}

Output:

 

image

image

Voila!!!!!! It worked like charm.


If you have any comments/suggestions please feel free to drop.

Working with flagged enumeration in Csharp

Flags enumerations are used for masking bit fields andimage doing bitwise comparisons. They are the correct design to use when multiple enumeration values can be specified at the same time. This was quite an official definition and if you are confused then let’s take an example.

For example, theFileShare enumeration contains the ReadWrite value to specify that a shared file can be opened for reading or writing. This shows developers that they can open a shared file for reading or writing, and eliminates the need for them to learn how to specify a combination of enumeration values as a single value.

Let’s take you to the world of Enums where you are allowed to use multiple values rather than using only single value for comparison/storing. To create an Flagged Enumeration you need an attribute [Flags] to be specified on the Enum.

Here are few guidelines while declaring an Enum as flagged.

  • Do apply the System.FlagsAttribute to flags enumerations. Do not apply this attribute to simple enumerations.
  • Do use powers of two for a flags enumeration's values so they can be freely combined using the bitwise OR operation.

Note: If you do not use powers of two or combinations of powers of two, bitwise operations will not work as expected.

for e.g. Let’s take an example of Identity cards type allowed to fill an application form before applying for a position. So we’ll create an Flagged Enum.

[Flags]
public enum IdentityProofType
{
Passport = 1,
DrivingLicense = 2,
PANCard = 4,
UID = 8,
EmployeeIDCard = 16
}


Now we’ll create a class that keep the information about the Form’s eligibility information. for e.g. AllowedIDs to fill the form:

private IdentityProofType AllowedIDs 
= IdentityProofType.Passport | IdentityProofType.UID | IdentityProofType.DrivingLicense;


This is the magic of flagged enumeration now the single field is holding multiple values of the Enumeration. So let’s create some methods in the class EntryForm:


public class EntryForm
{
private IdentityProofType AllowedIDs
= IdentityProofType.Passport | IdentityProofType.UID | IdentityProofType.DrivingLicense;
// Check for eligibility validation
private bool CanApply(IdentityProofType identityProofType)
{
if (AllowedIDs.HasFlag(identityProofType))
{
Console.WriteLine("valid identity provided: {0}", identityProofType);
return true;
}
else
{
return false;
}
}
// Apply check and fill the form if valid
public void FillForm(string username, IdentityProofType identityProofType)
{
if (this.CanApply(identityProofType))
{
Console.WriteLine("Ready to fill the form: {0}", username);
}
else
{
Console.WriteLine("Not a valid id provided by: {0}.", username);
}
}
}


Now Let’s create a test for this class:

 

EntryForm form1 = new EntryForm();
EntryForm form2 = new EntryForm();

form1.FillForm("Sunny", IdentityProofType.DrivingLicense | IdentityProofType.Passport);
Console.WriteLine("=============");
form2.FillForm("Amit", IdentityProofType.PANCard);


This will result in output:

image

So now you saw the magic of Flagged Enumerations but ask a question.

 


How it works??


This works because you previously used multiples of two in you enumeration. Under the covers your enumeration values looks like this (presented as bytes, which has 8 bits which can be 1's or 0's)

 Passport: 00000001
DrivingLicense: 00000010
UID: 00000100
PassPort: 00001000

Likewise, after you've set your property AllowedIDs to Passport, DrivingLicense and UId (which values where OR'ed by the pipe |), AllowedIDs looks like this

AllowedIDs: 00001110

So when you retreive the value you are actually bitwise AND'ing the values

myProperties.AllowedIDs: 00001110
IdentityProofType.DrivingLicense: 00000010
-----------------------
00000010 // this is the same as IdentityProofType.DrivingLicense!

Different forms of Flagged Enums

There are different ways you can define a Flagged  Enumeration. Since you know that it only allow values to the power of 2. So you can do something like this with your flagged enumeration in case you don’t want to count for the huge collection of Enum.

/// <summary>
/// Flagged with Enum with bitwise shifting
/// </summary>
[Flags]
public enum IdentityProofType : byte
{
None = 0,
Passport = 1 << 0, // 1
DrivingLicense = 1 << 1, // 2
PANCard = 1 << 2, // 4
UID = 1 << 3, // 8
EmployeeIDCard = 1 << 4, // 16
}


Or you can also write this as below:


[Flags]
public enum Options : byte
{
None = 0,
Passport = 1 << 0, // 1
// now that value 1 is available, start shifting from there
DrivingLicense = Passport << 1, // 2
PANCard = DrivingLicense << 1, // 4
UID = PANCard << 1, // 8
EmployeeIDCard = UID << 1 //16
}


Note: If you have notices than there’s a new name introduced in these called None having value 0. It is not allowed to have value starting with 0 in these enum types. But as per the MSDN:

Use None as the name of the flag enumerated constant whose value is zero. You cannot use the None enumerated constant in a bitwise AND operation to test for a flag because the result is always zero. However, you can perform a logical, not a bitwise, comparison between the numeric value and the None enumerated constant to determine whether any bits in the numeric value are set.

Hope you enjoyed reading this. Please leave comments or suggestions.








Deserialize list of json objects as list with JSON.Net

I’ve been a big fan of JSON.Net since past few years. Always helping me with less code and high performance conversion of JSON to C# objects. Thanks to James who made it possible as a fastest framework for manipulating JSON with a great documentation. In this post we will talk about a json format where a list of json objects presents with no root elements. This would be easy if you have root element you can use JObject of json.net. But in case you don’t then this would throw an exception.

Let say we have list of elements in the JSON data:

[
{
"major": 4,
"minor": 0,
"profile": "client",
"servicePack": null,
"url": "http://www.microsoft.com/downloads/details.aspx?displaylang=en&FamilyID=5765d7a8-7722-4888-a970-ac39b33fd8ab"
},
{
"major": 4,
"minor": 0,
"profile": "full",
"servicePack": null,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=9cfb2d51-5ff4-4491-b0e5-b386f32c0992&displaylang=en"
},
{
"major": 3,
"minor": 5,
"profile": "client",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=8CEA6CD1-15BC-4664-B27D-8CEBA808B28B&displaylang=en"
},
{
"major": 3,
"minor": 5,
"profile": "full",
"servicePack": 1,
"url": "http://go.microsoft.com/fwlink/?LinkId=124150"
},
{
"major": 3,
"minor": 0,
"profile": "full",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyId=10CC340B-F857-4A14-83F5-25634C3BF043&displaylang=en"
},
{
"major": 2,
"minor": 0,
"profile": "full",
"servicePack": 2,
"url": "http://www.microsoft.com/downloads/details.aspx?familyid=5B2C0358-915B-4EB5-9B1D-10E506DA9D0F&displaylang=en"
},
{
"major": 1AAA,
"minor": 1,
"profile": "full",
"servicePack": 1,
"url": "http://www.microsoft.com/downloads/details.aspx?FamilyID=a8f5654f-088e-40b2-bbdb-a83353618b38&DisplayLang=en"
}
]
// Sample taken from http://www.hanselman.com/blog/NuGetPackageOfTheWeek4DeserializingJSONWithJsonNET.aspx

You can use simple Jsonconvert.Deserialize<yourType>(jsonString) to get the typed object from a JSON. But his can throw an error if the items in Json have field with incorrect value. Let’s an int field have some alphabetic character. The exception will thrown for parsing and you’ll have very little details on error.

Now if you need to parse it as list and let’s say you want to find elements who have fields which are not of correct type as it should be then we can filter them out and log them somewhere. And so you will get a complete list of correct items and corrupted data.


We’ll use a JArray class from namespace Newtonsoft.Json.Linq to parse the data as list of array of object and then we’ll convert one by one each item to typed object and add it to list. Here’s the sample generic deserializer that can parse Json and get the valid and invalid elements.


Converter/Deserializer:


public static List<string> InvalidJsonElements;

public static IList<T> DeserializeToList<T>(string jsonString)
{
InvalidJsonElements = null;
var array = JArray.Parse(jsonString);
IList<T> objectsList = new List<T>();

foreach (var item in array)
{
try
{
// CorrectElements
objectsList.Add(item.ToObject<T>());
}
catch (Exception ex)
{
InvalidJsonElements = InvalidJsonElements ?? new List<string>();
InvalidJsonElements.Add(item.ToString());
}
}

return objectsList;
}


Usage:


Product productObj = new Product();
IList<Product> validProdcuts;
IList<string> invalidProductItemInJson;
string jsonString = "[{json specified above}]";

// Call the deserializer
validProdcuts = JsonHelper.DeserializeToList<Product>(jsonString);

// Check for errors
if (JsonHelper.InvalidJsonElements.Count != 0)
{
invalidProductItemInJson = InvalidJsonElements;

// Here we have invalid items of json now we are rectified with
// the problematic data from json
}


So here you can see that you’ll have valid items in list and invalid in errors. For e.g. in the above shown JSON data the last element have invalid value to int field major as ‘1AAA’


Enjoy Jsonifying.

Creating dynamic object with Dynamic feature in CSharp

There were new features introduced in .Net 4.0 and one of the awesome feature was addition of System.Dynamic in framework library. With this dynamic objects C# can provide dynamic language features like Python.

A short brief of Dynamic objects is, Dynamic objects expose members such as properties and methods at run time, instead of in at compile time. This enables you to create objects to work with structures that do not match a static type or format. For example, you can use a dynamic object to reference the HTML Document Object Model (DOM), which can contain any combination of valid HTML markup elements and attributes.

People still gets confused with Dynamic vs Anonymous types. Just to clarify Anonymous types cause the compile time errors. While Dynamic types work upon run time late binding for object properties. Let’s take an example:

var anonymousObject = new { Name=”Anonymous”, Value=”Foo” } ;

if you use anonymouseObject.Index then It’ll throw an compile time exception because it only know the Name and Value as it’s property. But using Dynamic you can use object.UnknownProperty will not cause compile time error.Let suppose you have requirement to create a object with properties which could be in any no. and of any type you don’t know. So how will you do this operation? I’ll introduce you with an exciting type of class called ExpandoObject with in System.Dynamic.


dynamic runTimeObject = new ExpandoObject();
runTimeObject.Name = "OnTheFlyFooObject";
runTimeObject.Value = "FooIsMoo";

This will automatically append these properties to the object. Now if you ask for runTimeObject.OtherUnknownProperty then it’ll not give any error during compilation but this will be check when you run the program. So you can also check if the object have this kind of property before using any runtime property. Behind the scene it’s storing these property as a Dictionary. So you can cast the runTimeObject to IDictionary<string,object> to get the list of late bound properties on the object.


var propertyCollection = (IDictionary<String, Object>)runTimeObject;
if (propertyCollection.ContainsKey("OtherUnknownProperty"))
{
Console.Write(runTimeObject.OtherUnknownProperty);
}

This is how you can be safe from getting any runtime exception. So you have seen how to use dynamic object with properties. Similarly you can also introduce run time methods to the dynamic object.


dynamic runTimeObject = new ExpandoObject();
runTimeObject.Name = "OnTheFlyFooObject";
runTimeObject.Value = "FooIsMoo";
runTimeObject.Print =
(Action)(() => { Console.Write("This a run time method for the dynamic on fly Foo"); });
//Now call the attached method
runTimeObject.Print();


Isn’t is cool? Yes it is. But beware before using it in your ordinary scenario can cost you some CPU time. These are runtime late binding operations which requires its own time to resolve the symbols and so are less optimized than normal early binding cases.


So choose wisely with your scenario. In some cases this is really an awesome feature provided in recent version of CSharp. I would say that CSharp is not just a Object Oriented language but it’s adapting features of Functional, Dynamic language. That’s why it’ll will long last than any language in the programming world.


If you enjoyed reading this then please leave a comment or suggestions.

Code coverage and Unit tests in VS2012

This post is about a question that people often asks when writing Unit tests and What troubles a developer is:

When should I stop writing Unit tests of something(Let say a simple Function)?

Lets talk about something known as Code coverage feature in visual studio(Premium/Ultimate editions). Most of the people don’t even know how it can help identifying unused code. Code coverage actually do the instrumenting of the assembly with special symbols putting over each statement and then analyse if that is being called when the code was getting executed. In visual studio this feature is added with Test manager. So you can run your unit tests via coverage tool and analyse the report how much production code is being covered by your unit tests.

Lets see how to run tests with coverage in simple steps:

1. In visual studio 2012 (Premium/Ultimate) you’ll find the option Test –> Analyze code coverage. Now there’s an option to run a single test coverage or all tests coverage.

image

Note: This option will be enabled only when your solution have UnitTests available. For unit tests written with Nunit you will need an Nuget package for Nunit Test Adapter. If you want then you can also download the Nunit VS Extension by searching into the VS Extension online.

2. Now select Run All Tests option and the magic will start. The coverage tool will be automatically launched and will run all Unit tests.

3. Once all the unit tests are done with running. You’ll see a coverage report in Code coverage Results window which will give you coverage in %.

image

In this report you’ll see in the Covered column the percentage of every function. And if this report says 100% then

Writing Unit tests at the moment.

Though as a standard testing strategy you can stop when coverage is >95%.

Using IOperationInvoker in WCF for Global exception handling and logging

There are several ways to implement the Global Exception handling in WCF for e.g. using a  IErrorHandler (The best way to handle the uncaught exceptions) or creating your own Façade for calling all service methods. In this article we’ll discuss about an Interceptor IOperationInvoker that can be used before and after activity when a service actually calls it’s operations. There are several things you can perform at this stage like Logging, Tracing or Handling the Exception(specially Unhandled Exceptions).

First we’ll start to look at high level of the picture where the Operation invoker actually stands when a client make a service method call. Below diagram is showing a picture of the same.

IOperationInvoker WCF cshandler.com

So lets create a WCF service project. (Learn how to create and consume WCF service). After adding the project, we need to add some operation in the service so for e.g. our service operation is GetParseData(). So it can look something like this(as generated from Project template).

IServiceContract:

[OperationContract]
string GetParseData(string value)


Service.cs


public string GetParseData(string value)
{
return string.Format("You entered: {0}", value);
}

To get some exceptions we’ll a custom logic in the Implementation of GetParseData(). So it can look something like this.

public string GetParseData(string value)
{
// check if value is alphabets/Numeric
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Method parameter value can not be null or empty");
}

// split the value if it contains spaces and return first two words
var stringArray = value.Split(' ');

// This will/may cause an Unhandled exception for OutOfIndex in case of single word is passed.
return string.Format("{0}_{1}_{2} ..", stringArray[0], stringArray[1], stringArray[2]);
}


Here in this method we have introduced some known and unhandled exception. To demonstrate the logging and Global exception handling we’ll now create a class that will Implement the IOperationInvoker interface.


/// <summary>
/// Global error handler of service operations using IOperationInvoker
/// </summary>
public class ErrorHandlingLoggingOperationInvoker : IOperationInvoker
{
private readonly ILog logger;

private IOperationInvoker invoker;

private string operationName;



public ErrorHandlingLoggingOperationInvoker(IOperationInvoker baseInvoker, DispatchOperation operation)
{
this.invoker = baseInvoker;
this.operationName = operation.Name;
XmlConfigurator.Configure();
logger = LogManager.GetLogger("serviceLogger");
}



public bool IsSynchronous
{
get
{
return true;
}
}



public object[] AllocateInputs()
{
return this.invoker.AllocateInputs();
}



//This is our intent method to intercept the request.
public object Invoke(object instance, object[] inputs, out object[] outputs)
{
logger.InfoFormat("Start command operation:{0}", this.operationName);

object result = null;

try
{
result = this.invoker.Invoke(instance, inputs, out outputs);
}
catch (Exception exception)
{
logger.Error("Unhandled Exception: ", exception);
outputs = new object[] { };

throw new FaultException(new FaultReason(exception.Message));
}

logger.InfoFormat("End command operation:{0}", this.operationName);

return result;
}



public IAsyncResult InvokeBegin(object instance, object[] inputs, AsyncCallback callback, object state)
{
throw new Exception("The operation invoker is not asynchronous.");
}



public object InvokeEnd(object instance, out object[] outputs, IAsyncResult result)
{
throw new Exception("The operation invoker is not asynchronous.");
}
}



In this implementation of IOperationInvoker we will only focus on the Invoke() method to log the request begin and request end also a Try Catch block is placed on the invoke statement so that we can capture any unhandled exception and log it in the first place with all details. And we’re not sending the complete exception to the client but a custom FaultException with less details or a message.



Now the invoker is ready but how to attached this Invoker/Dispatcher to our service. For this we’ll implement the IOperationBehavior first to attach the invoker with default operation behaviors.


/// <summary>
/// Bhavior defined for global exception handler
/// </summary>
public class GlobalExceptionHandlerBehavior : IOperationBehavior
{
public void Validate(OperationDescription operationDescription)
{
return;
}



public void ApplyDispatchBehavior(OperationDescription operationDescription, DispatchOperation dispatchOperation)
{// Here we have added our invoker to the dispatch operation dispatchOperation.Invoker = new ErrorHandlingLoggingOperationInvoker(dispatchOperation.Invoker, dispatchOperation);
}



public void ApplyClientBehavior(OperationDescription operationDescription, ClientOperation clientOperation)
{
return;
}



public void AddBindingParameters(OperationDescription operationDescription, BindingParameterCollection bindingParameters)
{
return;
}
}



Now we have our invoker as Operation behavior.  Now we need to implement the IServiceBehavior and we’re done. Then you can directly use this behavior via the binding configuration directly using extensions. See here How to add the extended behavior in the service from configuration file.


But here we’ll create our Custom Attribute class and will use it in the code directly as an Attribute on service class. To create an Attribute for service behavior we need to inherit the Attribute class in our CustomAttribute implmenetation with IServiceBehavior .


Here the code:


/// <summary>
/// Attribute class for applying custom service behavior on Service
/// </summary>
public class ExceptionHandlerLoggerBehaviorAttribute : Attribute, IServiceBehavior
{
public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
return;
}

public void AddBindingParameters(
ServiceDescription serviceDescription,
ServiceHostBase serviceHostBase,
Collection<ServiceEndpoint> endpoints,
BindingParameterCollection bindingParameters)
{
return;
}

public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
{
foreach (ServiceEndpoint endpoint in serviceDescription.Endpoints)
{
foreach (OperationDescription operation in endpoint.Contract.Operations)
{
IOperationBehavior behavior = new GlobalExceptionHandlerBehavior();
operation.Behaviors.Add(behavior);
}
}
}
}


Here we are actually applying the behavior to the end points. which in turn doing the same as we do apply behavior via the configuration file with each EndPoint. So our Attribute class is ready, we're going to tell the Service calls that you have a custom behavior to handle the global exception.


[ExceptionHandlerLoggerBehavior]
public class Service1 : IService1
{
public string GetParseData(string value)
{
// check if value is alphabets/Numeric
if (string.IsNullOrEmpty(value))
{
throw new ArgumentException("Method parameter value can not be null or empty");
}

// split the value if it contains spaces and return first two words
var stringArray = value.Split(' ');

// This will/may cause an Unhandled exception for OutOfIndex in case of single word is passed.
return string.Format("{0}_{1}_{2} ..", stringArray[0], stringArray[1], stringArray[2]);
}
}


Now we’ll create a client and call the service method. To create a client simple host the service in IIS express and find the service reference via service reference dialog box. We’ll simply use the Console application as a client.


public static void Main(string[] args)
{
ServiceReference1.Service1Client client = new Service1Client();
try
{
string value = client.GetParseData("somevalue");
Console.WriteLine(value);
}
catch (FaultException ex)
{
Console.WriteLine("========= Error ==========");
Console.WriteLine("{0}", ex.Message);
}

Console.Read();
}


so run the client with different values. For e.g. call the method GetParseData()


i) “some values are valid values” (will not throw exception)



ii) “somevalue” (will throw exception)


image


Let’s take a look at the log file. How the logs are getting produced from the our custom Interceptor.


2013-06-24 14:09:35,339 [6] INFO  serviceLogger - Start command operation:GetParseData
2013-06-24 14:09:35,353 [6] INFO serviceLogger - End command operation:GetParseData
2013-06-24 14:09:57,714 [6] INFO serviceLogger - Start command operation:GetParseData
2013-06-24 14:09:57,716 [6] ERROR serviceLogger - Unhandled Exception:
System.IndexOutOfRangeException: Index was outside the bounds of the array.
at CShandler.SampleWCFServiceApplication.Service1.GetParseData(String value) in c:\Users\achoudhary\Documents\Visual Studio 2012\Projects\WpfApplication1\CShandler.SampleWCFServiceApplication\Service1.svc.cs:line 26
at SyncInvokeGetParseData(Object , Object[] , Object[] )
at System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs)
at CShandler.SampleWCFServiceApplication.ErrorHandlingLoggingOperationInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) in c:\Users\achoudhary\Documents\Visual Studio 2012\Projects\WpfApplication1\CShandler.SampleWCFServiceApplication\ErrorHandlingLoggingOperationInvoker.cs:line 85


Hope you enjoyed the article. Please leave a comment or suggestion.