Search This Blog

Monday, December 21, 2009

Using Microsoft Enterprise Library VAB with WCF services – Part 2

In Part 1 we looked at a simple solution on how to do service side validation for a simple WCF service and pass the resulting validation result back to the client.  In this article we’ll look at some other types of validators provided by the Enterprise Library and also touch the topic of rulesets and how they help.

So far we have looked at RangeValidator; let us look at some of its properties.

Bounds
The LowerBound and UpperBound of the validator are self-explanatory and denote the minimum and maximum value the validator can accept.

BoundType
The BoundType is synonymous to the bounds you have, it tells you whether the bounds are included, excluded or simply ignored.

Negated
If negated is set then we basically negate the rule, therefore in our example where we had the rangevalidator to accept only positive integers, setting negated=true would mean we only allow negative integers.  Kind of a redundant property in my opinion and simply complicates things.

Tag
Allows the developer to replace the name of the property which caused the validation fault to a custom string.  Useful when your property name is something like “accessDate” and you want to return “Access Date”.  Keep in mind that the custom Tag is only read when you have a custom message template.

MessageTemplate
Each validator provided by the Enterprise Library comes with its own message which gets returned on a validation fault, this can be customised by the developer.  For e.g. for the Range Validator we know (looking at the MSDN documentation) token {2} is the Tag, therefore our message template could be “{2} is invalid.” and we would get “Access Date is invalid.”

MessageTemplateResourceName/MessageTemplateResouceType
The following items come in handy when you have declared your messages in a resource file.

Ruleset
Allows the developer to target different validation rules depending on different criteria.  E.g. different clients may have different validation rules depending on different business logic.  This can be done by simply changing the config file to tell the validation block which ruleset to use as shown below:







To be continued…

Thursday, December 10, 2009

De/Se-rializing C# objects to XML

I have come across many projects over the years which need some sort of serializing and deserializing of C# objects to XML.  I usually remember the general syntax but more than often end up searching for the exact syntax.  There are tonnes of articles on this by the way and this blog is merely to give me a consistent way of doing this rather than anything else.

Say you have a couple of C# classes such that one class contains a collection of the other class and you want to serialize this into XML.

image

The way I usually do it is simply by adding some attributes to my C# classes which represent the structure of the resulting XML and run an XML serializer against it.  So my C# classes would potentially look like:

[XmlRoot(ElementName = "Customer", IsNullable = false)]
public class Customer
{
[XmlElement(ElementName = "Name")]
public string Name { get; set; }

[XmlElement(ElementName = "IsExpired")]
public bool IsExpired { get; set; }

[XmlElement(ElementName = "DOB")]
public DateTime DOB { get; set; }

[XmlArray("Orders")]
[XmlArrayItem("Order", Type = typeof(Order))]
public List<order> Orders { get; set; }
}

public class Order
{
[XmlAttribute(AttributeName = "OrderID")]
public int OrderID { get; set; }
}

With the above class we get an XML output as shown in the figure below:

image

And the code which actually does the serialization:

class Program
{
static void Main(string[] args)
{
Customer c = new Customer()
{
Name = "Ruskin Dantra",
DOB = DateTime.Today,
IsExpired = false,
Orders = new List<order>()
{
new Order() { OrderID = 1},
new Order() { OrderID = 2},
new Order() { OrderID = 3}
}
};

System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(Customer));

XmlWriterSettings settings = new XmlWriterSettings();
settings.Indent = true;

XmlWriter writer = XmlWriter.Create(@"Customer.xml", settings);
s.Serialize(writer, c);
writer.Close();
}
}

If you want to deserialize the above created XML back into the object all you have to do is:

System.Xml.Serialization.XmlSerializer s = new System.Xml.Serialization.XmlSerializer(typeof(Customer));
XmlReader reader = XmlReader.Create(@"Customer.xml");
Customer deserializedCustomer = s.Deserialize(reader) as Customer;
reader.Close();

Its as easy as that :)

Wednesday, December 9, 2009

Using Microsoft Enterprise Library VAB with WCF services – Part 1

I am starting to write a series of blog articles, each varying in complexity, highlighting how we use can the Validation Application Blocks within the Microsoft Enterprise Library to do really neat validation.  Extremely flexible and configurable at runtime.  Although we will slowly build towards that.

In this first part let me just give a brief introduction to what the VAB actually is some simple ways of using it within a WCF service.

While writing WCF services we often cannot guarantee the data we get passed in, let it be simple data like integers or complex business objects such as Customers or even worse, process definitions.  Although, as developers we have to design some sort of clever program which can intelligently sorting out good data from bad data.  Good data is often derived from pages of use cases and business rules.  These rules tend to change often so it’s only advisable that we allow for this by allowing our program (in this case a WCF service) to read this rules at runtime.  This is our end goal.

In the early days I used to do simple checks on data to determine its validity.  Although strenuous and naive, it worked.  For e.g. if you have a service which finds the square root of a number then we know for a fact that it cannot accept a negative number.  So a developer has the following options:

  1. Don’t care about the erroneous input
  2. Cater for error scenarios (number being less than 0) and return a exception
  3. Cater for error scenarios (number being less than 0) and return a message
  4. Return an exception which has the message

Yes, the last option does look the most tempting but a bit harder to implement.  Let us try and work through the other options first, for all our scenarios we will have the same interface and client definition:

Interface:

namespace VABService
{
[ServiceContract]
public interface IMyService
{
[OperationContract]
double SquareRoot(double number);
}
}

Client:

namespace VABServiceClient
{
class Program
{
static void Main(string[] args)
{
service.MyServiceClient client = null;
try
{
client = new VABServiceClient.service.MyServiceClient();
double result = client.SquareRoot(4);
}
catch (Exception e)
{
}
finally
{
if (client != null && client.State != System.ServiceModel.CommunicationState.Faulted)
{
try
{
client.Close();
}
catch (Exception e)
{
// don't care
}
}
}
}
}
}


Don’t care about the erroneous input With this approach our implementation looks simple and we end up with:



namespace VABService
{
public class MyService : IMyService
{
#region IMyService Members
public double SquareRoot(double number)
{
return Math.Sqrt(number);
}
#endregion
}
}


This service implementation will allow for the correct square root to be returned but say instead of passing in a positive integer we pass in a negative integer: –4; can the service guarantee a deterministic result?  I don’t think so, the most the developer can say is that it will do whatever the .Net environment is set up to do.  Left as is the result coming back will be NaN.



image



If the client was a high risk financial application and the service returned this value, the result would be quite catastrophic unless both the client and the service came to some sort of prior agreement about this returned value.  Although wouldn’t it be nice if we raised an exception or an error of some kind sighting the problem?



Cater for error scenarios (with an Exception) To allow for an exception to be raised we have to slightly change the service implementation as shown below:



namespace VABService
{
public class MyService : IMyService
{
#region IMyService Members
public double SquareRoot(double number)
{
if (number < 0)
throw new ArgumentOutOfRangeException(string.Format("Square root of negative numbers cannot be determined:{0}.", number));
return Math.Sqrt(number);
}
#endregion
}
}


Now with the same client as before if we pass in a negative number we get a  exception although the client is nonetheless wiser than it was before:



image



You see the above exception because of an attempt to hide the implementation details of the service from the clients calling it.  Just as the exception states, if we set the flag IncludeExceptionDetailsInFaults to be true, we will actually see why the exception occurred:



image



Although this is opening up our service unnecessarily and clients can get a clear view of our implementation when things go wrong and lets face it, things always can go wrong!  So we want to avoid setting IncludeExceptionDetailsInFaults to true in a production environment.



Cater for error scenarios (with a message) To allow for this we have to add even more code to the implementation and also add another parameter to our interface which we can use to pass back the error message, which in this case is the exception text.  We all know how this is going to look, yes UGLY!  We don’t want to do that!!! This brings us to our last option and the most elegant solution.



Return an exception which has the message This is where Geers Blog comes in handy.  WCF exposes really neat things which can be used to do all sorts of validation but why do this when we can go one step further and use an already well thought and designed framework wrapper.  Yes, the VAB is exactly that.



The Meat

Yes so far all you have seen is bones and why, what…and blah blah, boring stuff.  The meat of the post is now here…let us use the VAB to do simple validation while finding the square root of a number.



First step would be to install the enterprise library and add a reference to (within your service project):





  • Microsoft.Practices.EnterpriseLibrary.Validation.integration.WCF




  • Microsoft.Practices.EnterpriseLibrary.Validation.dll




  • Microsoft.Practices.EnterpriseLibrary.Common.dll




After doing so we’ll need to make 3 changes…




  1. Service interface change

    Our service interface will now contain the following code.

    using System;
    using System.ServiceModel;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Integration.WCF;
    using Microsoft.Practices.EnterpriseLibrary.Validation.Validators;

    namespace VABService
    {
    [ServiceContract]
    public interface IMyService
    {
    [OperationContract]
    [FaultContract(typeof(ValidationFault))]
    double SquareRoot(
    [RangeValidator(0, RangeBoundaryType.Inclusive, Double.MaxValue, RangeBoundaryType.Inclusive)]
    double number);
    }
    }

    Note that we now have a rangevalidator for the parameter “number” and also declare that this particular interface method has a fault contract of type ValidationFault associated to it


  2. Config file
































    Note that we have only added new a endpoint behaviour, a behaviour extension and mapped our already existing endpoint to the newly added endpoint behaviour.


  3. Client change
    static void Main(string[] args)
    {
    service.MyServiceClient client = null;
    try
    {
    client = new VABServiceClient.service.MyServiceClient();
    double result = client.SquareRoot(-4);
    }
    catch (FaultException fe)
    {
    }
    catch (Exception e)
    {
    }
    finally
    {
    if (client != null && client.State != System.ServiceModel.CommunicationState.Faulted)
    {
    try
    {
    client.Close();
    }
    catch (Exception e)
    {
    // don't care
    }
    }
    }
    }

    With this change in the client, now instead of getting simply exceptions without any message we get a particular type of exception which we can catch and investigate as shown in the image below: 
    image



We’ll look at other validators in Part 2.

Debugging VB6 COM DLLs via .Net

I am sure there are other ways of doing this but this post is just a simple step by step guide on one of them.

More often than not we have to use legacy COM components while writing new applications, let it be for database access, business logic or to simply avoid duplicating code.  Every time I end up using a COM object in my .Net application I lose the ability to debug inside that COM object and mostly have to assume that whatever happens within that call is logically correct.  Sometimes I am not convinced so I need to see proof of it first hand, so what do I do, I debug the COM call.

Adding a COM object to .Net cannot be easier, simply add a reference to the COM object which is registered on your computer and .Net automatically creates what we call a CCW (COM Callable Wrapper).  This is widely documented here.

In order to demonstrate how to debug a COM call let us first create a very simple VB6 DLL called Project1.dll.  In this COM DLL I have a single class called Class1.cls which contains a very simple Add method as shown below:

Option Explicit

Public Sub Add(ByVal a As Integer, ByVal b As Integer, ByRef result As Integer)
result = a + b
Exit Sub
End Sub

After creating this method, I built the DLL to a location using the default build options within the VB6 IDE by going to File>Make Project1.dll.


After this was done I created a new ConsoleApplication solution in C# to reference this COM DLL.  Added a reference to Project1 which allowed me to do this:


Project1.Class1Class class1 = new Project1.Class1Class();
short res = 0;
class1.Add(1, 2, ref res);

Great, I can now use the add method which I wrote in the COM object, say if the COM method returns the wrong value and I want to step into that code, I simply go Debug>Step Into (F11).  But what happens is that the debugger simply steps over that code and gets the result.  What has happened is that none of the symbols for that Project1.dll were loaded into my IDE:

image


This can be achieved simply by building the VB6 DLL using symbolic information.  You can do this by right clicking on the VB6 project in your IDE and going to Properties>Compile and check the boxes which say “Create Symbolic Debug Info” and also select “No Optimization”.


image

After the above is done, rebuild the Project1.dll.  You’  Simply doing the above step will not allow you to step into the “Add” function because the .Net IDE still hasn’t loaded the symbols.  To allow for this we have to enabled “Unmanaged Debugging” for our project, this can be done by going into the Project Properties>Debug and checking the box “Enable unmanaged code debugging” as shown below.

image


Doing the above process will now load the symbols:

image


Doing the above steps will still not allow us to step into the VB6 code, for this we have to do a manual step.  Open up the code file which has the “Add” function defined and put a breakpoint at the desired line of code.  Now when you step into the “Add” method call you will hit the breakpoint on the VB6 side as shown below:


image


Voila! :)