Category Archives: Framework

.NET XML Serialization of CDATA ATTRIBUTE

Recently I needed to create a .NET class (C#) that when serialized should contain a CDATA attribute similar to this:

<?xml version="1.0" encoding="utf-8" ?>
<RootNode Type="zzzzz" Version="1" >    
    <CDataAttribute>
        <![CDATA[
         <?xml version="1.0" encoding="utf-8" ?>
        ]]>
    </CDataAttribute>    
</RootNode>

 

I started by creating a schema for validating this xml that can be (generated with xsd.exe and slightly altered):

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Example" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="RootNode">
    <xs:complexType>
      <xs:sequence>
        <xs:element name="CDataAttribute" type="xs:string" minOccurs="0"/>
      </xs:sequence>
      <xs:attribute name="Type" type="xs:string" />
      <xs:attribute name="Version" type="xs:string" />
    </xs:complexType>
  </xs:element>
  <xs:element name="Example">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="RootNode" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

Note that the CDataAttribute is specified as type string and I could not find any type for referring a CDATA.

Now if you take this schema and generate a class from it (again with xsd.exe) you will see that the CDataAttribute is, as expected, represented by a string.

private string cDataAttributeField;

If you use the generated class and serialize a object from it, the .NET serializer will not encode the CDataAttribute between a CDATA xml structure, but instead will escape all the special characters that you place inside the CDATA.

<?xml version="1.0"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RootNode Type="xxxx" Version="1">
    <CDataAttribute>&lt;?xml version="1.0" encoding="utf-8" ?&gt;</CDataAttribute>
  </RootNode>
</Example>

As I really needed it to be placed inside a CData section, I searched on the Internet but did found a satisfying solution for this “problem”, but using the idea behind some of the articles (use XmlNode for the class CDataAttribute member instead of string) my solution was the following.

 

First I generated my schema class without the CDataAttribute.

<?xml version="1.0" encoding="utf-8"?>
<xs:schema id="Example" xmlns:xs="http://www.w3.org/2001/XMLSchema">
  <xs:element name="RootNode">
    <xs:complexType>
      <xs:sequence>
        <!-- NOTE: We could not generate a CDATA directly from XSD.
             Generated by partial class -->
        <!--<xs:element name="CDataAttribute" type="xs:string" minOccurs="0"/>-->
      </xs:sequence>
      <xs:attribute name="Type" type="xs:string" />
      <xs:attribute name="Version" type="xs:string" />
    </xs:complexType>
  </xs:element>
  <xs:element name="Example">
    <xs:complexType>
      <xs:choice minOccurs="0" maxOccurs="unbounded">
        <xs:element ref="RootNode" />
      </xs:choice>
    </xs:complexType>
  </xs:element>
</xs:schema>

Then I extended the partial generated class with my own implementation of the CDataAttribute.

using System;
using System.Xml;
 
public partial class RootNode
{
    private XmlNode cDataAttributeField;
 
    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified)]
    public XmlNode CDataAttribute
    {
        get {return this.cDataAttributeField;}
        set {this.cDataAttributeField = value;}
    }
    
    /// <summary>
    /// Getter/Setter method for the CDATA document content field.
    /// Encapsulates the internal CDATA XmlNode
    /// </summary>
    [System.Xml.Serialization.XmlIgnore()]
    public String CDataAttributeByString
    {
        get 
        { // Retrieves the content of the encapsulated CDATA
          return cDataAttributeField.Value;
        }
 
        set
        { // Encapsulate in a CDATA XmlNode
          XmlDocument xmlDocument = new XmlDocument();
          this.cDataAttributeField = xmlDocument.CreateCDataSection(value);
        }
    }
}

Note that I used a XMLNode for representing the class member that will be serialized. For setting this XMLNode I created a property (CDataAttributeByString) that receives a string and places in the XmlNode a CDataSection containing the received string value.

As so I only work with the CDataAttributeByString property, that is excluded from the serialization, and I let the .NET serializer use the CDataAttribute property for properly creating my CDataAttribute.

 

Using the extended class, the serialized xml will now be:

<?xml version="1.0"?>
<Example xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <RootNode Type="xxxx" Version="1">
    <CDataAttribute>
        <![CDATA[<?xml version="1.0" encoding="utf-8" ?>]]>
    </CDataAttribute>
  </RootNode>
</Example>

 

I hope that this can help some of you, and if you know a better solution please tell me.

I leave a sample project here.

Developing a WCF Service – Fault Exceptions AND FAULT Contracts

This next post about WCF will show how to integrate Fault Exceptions and Fault Contracts in your service.

As written in MSDN Fault Exceptions are used for "… mapping managed exception objects to SOAP fault objects and SOAP fault objects to managed exception objects …". This means that if you are looking for interoperability in your service development then you definitely should use this, because no Java client will understand a .NET exception.

You can read some more about it in this link Specifying and Handling Faults in Contracts and Services.

So, when using Fault Exceptions (or SOAP Faults) you have two alternatives:

  • Normal typed (or "un-typed") – You throw a regular FaultException which only contains general information about the SOAP Fault
  • Strongly-typed – You define your own SOAP Fault object, which can contain any kind of information you want about the SOAP Fault

Strongly-typed SOAP Faults are then used when you wish to give to the client some more information and context about the cause of the exception. They also couldn’t be much easier to define in WCF, because they are no more, no less than another Contract in the service definition, which are semantically called Fault Contracts.

As such, you define a Fault Contract in your service definition in the following way:

/// <summary>

/// Strongly-typed fault.

/// </summary>

[DataContract]

public class ArgumentFault

{

    #region Get / Set

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Operation { get; set; }

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Argument { get; set; }

 

    /// <summary>

    /// 

    /// </summary>

    [DataMember]

    public String Message { get; set; }

 

    #endregion

}

You then define that an operation can throw this type of fault contract by appending the following to your operation:

[FaultContract(typeof(ArgumentFault))]

[OperationContract]

Customer GetCustomer(Int32 customerId);

Now in the service implementation when you want to throw the defined fault contract you do like this:

public Customer GetCustomer(int customerId)

{

    if (customerId <= 0)

    { // Not possible

        throw new FaultException<ArgumentFault>(new ArgumentFault()

        {

            Operation = MethodBase.GetCurrentMethod().Name,

            Argument = "customerId",

            Message = "Argument must be greater than zero."

        });

    }

 

    return Customers.First(customer => 

    {

        return customer.Id == customerId;

    });

}

This is better than just doing:

throw new FaultException(MethodBase.GetCurrentMethod().Name + 

               ": customerId - Argument must be greater than zero.");

 

In the client application for catching this Fault Exception, you code should be:

try

{    // Get customer

    Customer singleCustomer = proxy.GetCustomer(customers[0].Id);

    Console.WriteLine("SingleCustomer: Id - {0} / Name - {1}.",

                singleCustomer.Id, singleCustomer.Name);

 

    // Force fault

    singleCustomer = proxy.GetCustomer(0);

}

catch (FaultException<ArgumentFault> ex)

{

    Console.WriteLine("FaultException<ArgumentFault>: {0} - {1} - {2}",

            ex.Detail.Operation, ex.Detail.Argument, ex.Detail.Message);

}

catch (FaultException ex)

{

    Console.WriteLine("FaultException: {0}", ex.Message);

}

 

Again the full code is available here:

 

Related List of articles

Developing a WCF Service

Developing a WCF Service – Calling the hosted service

Developing a WCF Service – Calling the hosted service

In the first part of this topic, I showed you how to develop a WCF service. In this next part I will show how to implement a client application that calls the exposed service methods, and how to make some enhancements to your service hosting.

Ok, so he already have built and deployed our service (either self-hosted, or in IIS for example), and by using a web browser we can see the service welcome page. Now, to call the service methods we must create a client proxy, and to do this we can use the Visual Studio Add Web Reference, which automatically creates the proxy, or we can use the command line svcutil to manually create the proxy. I prefer to do it manually because I like to control things like the generated proxy class namespace.

For example purposes, I created a Console Application that I called Tests.SampleService. There I created a batch file for calling the svcutil with my own parameters, with something similar to this:

svcutil %SERVICE_URL% /namespace:*,%NAMESPACE% /d:%OUT_DIR% /out:%OUT_FILE%

With the service running, I executed the batch file and svcutil generated two files:

  • output.config – Contains the WCF runtime configurations for calling the service (<system.serviceModel>)
  • Sample.Service.Proxy.cs – Contains the service proxy class, and any other classes exposed by the service

The contents of the output.config should be placed in the console application App.Config (if you prefer you can just rename the file).

In your console application main file you can place code like the following:

static void Main(string[] args)

{

   Console.WriteLine("Press any key to start");

   Console.ReadLine();

 

   // Build the service proxy object

   ServiceClient proxy = new ServiceClient();

 

   // Call service methods

 

   // Get total number of customers

   Int32 totalCustomers = proxy.GetTotalNumberOfCustomers();

   Console.WriteLine("Total Customers: {0}", totalCustomers);

 

   // Get list of customers

   List<Customer> customers = new List<Customer>(proxy.GetCustomers());

   foreach (Customer customer in customers)

   {

       Console.WriteLine("Customers");

       Console.WriteLine("Customer: Id - {0} / Name - {1}.", customer.Id, customer.Name);

   }

            

   // Get customer

   Customer singleCustomer = proxy.GetCustomer(customers[0].Id);

   Console.WriteLine("SingleCustomer: Id - {0} / Name - {1}.", singleCustomer.Id, singleCustomer.Name);

 

   Console.WriteLine("Press any key to exit");

   Console.ReadLine();

}

You are know ready to start your service and use your client application to call the service methods.

 

Service Host Enhancements

Regarding the self service hosting there are some steps that you can do to make it more robust to errors and faults. Two of these changes are:

  • Subscribe the service host Faulted event
  • Subscribe the service host Unknown Message Received event

This should be done before opening our service hosting, and the new StartServiceHost method should look like this:

/// <summary>

/// Creates the service host

/// </summary>

private void StartServiceHost()

{

    Logger.Info("StartServiceHost: Starting service hosting...");

 

    // Create service host

    _serviceHost = new ServiceHost(typeof(SampleService.Service));

 

    // Subscribe to the Faulted event of the service host

    _serviceHost.Faulted += new EventHandler(FaultHandler);

 

    // Subscribe to the Unknown message received event of the service host

    _serviceHost.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(UnknownMessageHandler);

    

    try

    { // Open service host

        _serviceHost.Open();

 

        Logger.Info("StartServiceHost: Service hosting success.");

    }

    catch (Exception ex)

    {

        Logger.Fatal("StartServiceHost: Could not start service hosting.", ex);

    }            

}

 

The event handler’s code can be:

/// <summary>

/// Fault error event handler

/// </summary>

private void FaultHandler(Object sender, EventArgs e)

{

    // Examine the properties of the service host

 

    // Log reason for fault

    Logger.Error("FaultHandler: Host Fault occured. Aborting and restarting the hosting");

 

    // Abort the service (Could use Close, but a service in this state does not responde to requests, and Close takes more time)

    _serviceHost.Abort();

 

    // Re-start service host

    StartServiceHost();

}

 

/// <summary>

/// Unknown message event handler

/// </summary>

private void UnknownMessageHandler(Object sender, UnknownMessageReceivedEventArgs e)

{

    // Log the unknown message

    Logger.Warn("UnknownMessageHandler: Unknown Message Received");

}

 

Take into attention that when the service host goes into a Faulted state, it stops servicing requests. This is why in the FaultHandler we abort the service host and open it again.

You can make a quick test of the event handlers by introducing in your web browser the following address: http://localhost:8080/SampleService/Service.svc.

This makes the service receive an unknown message and the corresponding event handler is called.

I leave here the complete Visual Studio solution.

 

Related list of articles:

Developing a WCF Service

Developing a WCF Service

It is typical to have projects based on a client-server architecture where the server publishes a number of services. These services are normally Web-Services, and as so are available through the SOAP protocol.

The "traditional" way of implementing these services is by using ASMX, but nowadays you have another great alternative – Windows Communication Foundation (WCF) in .NET 3.5.

This, being my first WCF post, intends to demonstrate that developing a simple WCF service is as easy as doing it in ASMX, while allowing us to make future evolutions on our service architecture to support everything that WCF makes available.

 

Well, as always you start out by creating a new Visual Studio project. I chose to use the existent project template ‘WCF Service Library’ (but some of you may want to start by an empty project 😀 ).

This creates a project with the following list of files (I changed the service name to ‘Service’, and I only list the WCF most important files:

  • IService.cs – Describes the exposed service interface. This is where we will namely define the [ServiceContract] (The service itself) and the [OperationContract]‘s (The operations exposed by the service). More information in Designing and Implementing Services.
  • Service.cs – The service interface implementation class. This is where the actual code of the service operations will be contained. More information in Implementing Service Contracts.

There is another important file, App.Config, that contains the service configuration (e.g. service listening url), but I will refer to this file later when talking about the service hosting (creates the service and controls its context and lifetime). More information in Hosting Services.

So a simple service contract could be:

[ServiceContract]
public interface IService
{
    [OperationContract]
    Int32 GetTotalNumberOfCustomers();
 
    [OperationContract]
    Customer GetCustomer(Int32 customerId);
 
    [OperationContract]
    List<Customer> GetCustomers();        
}

This code defines a service contract (IService) that exposes three operations (operation functionality is self explanatory):

  • GetTotalNumberOfCustomers
  • GetCustomer
  • GetCustomers

You will notice that in the code we are referring a custom class that is not contained anywhere in the service contract, that is the Customer class. This class must be described in WCF like a [DataContract] because it is a new, complex data type that WCF does not know how to serialize. More information in Using Data Contracts.

Our data contract is defined like this:

[DataContract]

public class Customer

{

    [DataMember]

    public Int32 Id { get; set; }

 

    [DataMember]

    public String Name { get; set; }

 

    public Customer()

    {

        Id = 0;

        Name = String.Empty;

    }

}

One important aspect of data contracts are the [DataMember] properties, that are properties to be exposed by the data contract.

 

At this point we are ready to implement our service contract, that for this example is very simple, and obviously not production code:

public class Service : IService

{

    private List<Customer> Customers = new List<Customer>()

    {

        new Customer() {Id = 1, Name = "Customer1" },

        new Customer() {Id = 2, Name = "Customer2" },

        new Customer() {Id = 3, Name = "Customer3" }

    };

 

    public int GetTotalNumberOfCustomers()

    {

        return Customers.Count;

    }

 

    public Customer GetCustomer(int customerId)

    {

        return Customers.First(customer => 

        {

            return customer.Id == customerId;

        });

    }

 

    public List<Customer> GetCustomers()

    {

        return Customers;

    }

}

 

Our service is now ready to be hosted and this is one of the beauties of WCF in the sense that the hosting environment can be a:

  • Windows/WPF Application
  • Console application
  • Windows Service
  • IIS/WAS

Each of them has advantages and disadvantages an again I refer you to Hosting Services (look at the Choosing a Hosting Environment table). Take into attention that the Service Library that you develop is always the same regardless of the hosting environment that you choose, and even if you choose one hosting environment now, you can choose another later and easily change between them.

For developing/debugging purposes I normally choose for hosting a simple WPF application with just two buttons (Start and Stop), where I place the following code (the Logger object is of log4net ILog type):

private void StartServiceHost()

{

    Logger.Info("StartServiceHost: Starting service hosting...");

 

    // Create service host

    _serviceHost = new ServiceHost(typeof(SampleService.Service));

    

    try

    { // Open service host

        _serviceHost.Open();

 

        Logger.Info("StartServiceHost: Service hosting success.");

    }

    catch (Exception ex)

    {

        Logger.Fatal("StartServiceHost: Could not start service hosting.", ex);

    }            

}

 
private void StopServiceHost()

{

    // Close service host

    _serviceHost.Close();

}

Now, you just have to properly configure the application configuration file (remember we talked about it earlier), and you are ready to test your service. Note that I configured the service hosting all thru the App.Config file and as simple and compatible as possible with a ASMX (e.g. Basic HTTP binding).

Note: I will differ binding’s and other configuration explanations to another time. Right now I just want you to see how you can get started with WCF.

<configuration>

    <system.serviceModel>

        <services>

        <service behaviorConfiguration="SampleService.Service.Behavior" name="SampleService.Service">

            <host>

                <baseAddresses>

                    <add baseAddress="http://localhost:8080/SampleService"/>

                </baseAddresses>

            </host>

            <endpoint    address="/Service.svc"

                        binding="basicHttpBinding"

                        name="IService_BasicHttpEndpoint"

                        contract="SampleService.IService"

                        bindingConfiguration="IService_BasicHttpBindingConfiguration">

            </endpoint>

        </service>

    </services>

 

    <behaviors>

        <serviceBehaviors>

            <behavior name="SampleService.Service.Behavior">

                <!-- To avoid disclosing metadata information, 

      set the value below to false and remove the metadata endpoint above before deployment -->

                <serviceMetadata httpGetEnabled="True"/>

                <!-- To receive exception details in faults for debugging purposes, 

      set the value below to true.  Set to false before deployment 

      to avoid disclosing exception information -->

                <serviceDebug includeExceptionDetailInFaults="True" />                

            </behavior>

        </serviceBehaviors>

    </behaviors>

 

    <bindings>

        <basicHttpBinding>

            <!-- Service host binding configuration -->

            <binding name="IService_BasicHttpBindingConfiguration"

                             maxBufferSize="65536" maxBufferPoolSize="52428"

                             maxReceivedMessageSize="65536" transferMode="Buffered">            

                <readerQuotas maxDepth="32" maxArrayLength="16384"

                                            maxBytesPerRead="4096" maxNameTableCharCount="16384"

                                            maxStringContentLength="8192"/>

            </binding>

        </basicHttpBinding>

    </bindings>

    

</system.serviceModel>

 

<configuration>

If you now run the WPF application and point your browser to http://localhost:8080/SampleService you should see a welcome page telling you that you have created a service.

You are now ready to start writing a client application that will call your service operation contracts (my next post will be about this part, but you have everything you need in the service welcome page).

To end, I just want to show you how easy it is to change the hosting environment to IIS for example. For hosting in IIS you just have to follow these steps:

  • Create a new web application in IIS
  • Place the presented App.Config <system.serviceModel> tag in a Web.Config file
  • Deploy the service library assembly to the web application bin directory
  • Create a special file, in my example called Service.svc, with the following content:
<%@ServiceHost language="C#" Debug="true"

                             Service="SampleService.Service"%>

<%@Assembly Name="SampleService" %>

The only different part in hosting in IIS is just the need to create the .svc file that tells IIS which service should be instantiated.

Again, if you point your browser to http://localhost:8080/SampleService/Service.svc you should see the same page as before.

I hope that this can get you started in WCF more easily and I will try to show what other capabilities WCF provides in some next posts.

Log4net Initialization/Configuration alternatives

In a previous post where I talked about using log4net I used one of the alternative ways to initialize and configure the logging services.

This post will summarize these alternatives.

 

1. Programmatic initialization

The programmatic initialization should be done somewhere in your code.

This was the type of initialization used on the first post and its code is something like this.

using log4net;

using log4net.Config;

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));

            log.Info("Entering application.");

    }

}

2. Assembly attribute initialization

The assembly attribute initialization does not imply the inclusion of any code in your application. Instead, you just have to place an assembly level attribute in some file of your assembly. This way your code could be:

using log4net;

[assembly: log4net.Config.XmlConfigurator()]

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        log.Info("Entering application.");
    }
}

 

The assembly level attribute by itself does not mean a instruction to initialize the logging framework. Instead, the logging framework is initialized by the first call that is made to log4net (in the example the log.Info) initialized. This means that when using assembly attributes you should make a logging call as soon as possible and before calling any other external assembly.

 

Finally, if you are using logger objects defined per-class, a simple way to define a logger object that enables it to be copy-pasted in a very simple way is to do:

private static readonly ILog log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

 

This instruction uses reflection for determining the class type name that will be used in the logging messages.

For more information please refer to the log4net homepage.

Using log4net logging services

Whenever you have the need for debugging some application that by whatever reason cannot be properly debugged in Visual Studio, or even because your application requires some kind of logging/auditing functionality, instead of developing your own tool you have the option to use some existent logging frameworks.

One that I have tried and enjoyed its features and ease of use is log4net – http://logging.apache.org/log4net/.

Like they say on their webpage, "log4net is a tool to help the programmer output log statements to a variety
of output targets. log4net is a port of the excellent log4j framework to the
.NET runtime
". Its features are present here: http://logging.apache.org/log4net/release/features.html.

One of its great features is the ability to control and configure the logging framework entirely by an XML file. This allows the building and deployment of applications that at run-time can dynamically change its logging configuration. For this you should initialize to log in the following manner (in the example the XML configuration file is received in the application arguments):

// Import log4net classes.
using log4net;
using log4net.Config;

public class MyApp
{
    private static readonly ILog log = LogManager.GetLogger(typeof(MyApp));

    static void Main(string[] args)
    {
        // BasicConfigurator replaced with XmlConfigurator.
        XmlConfigurator.Configure(new System.IO.FileInfo(args[0]));      
    }
}

After this, you can check if the initialization went ok by testing the value of: _log.Logger.Repository.Configured .

Now it is real easy to start logging things. You just have to do:

            log.Info("Entering application.");

        log.Debug("Entering application.");

and the framework takes care of the rest, logging acording to the configuration that you provided. Note that in the above code I am already logging into two different log levels, just as an example for showing you, that while developing I can have the level configured at DEBUG, and at production I can reduce the level to INFO, or even NONE, if I dont want any logging at all. If a problem occurs in production, I can just as easily change the log level to DEBUG again, and without having to change anything in the application, the logs start being generated. 

As a final example of the capabilities of the framework, I just want to show here a possible XML configuration file:

<?xml version="1.0" encoding="utf-8" ?>
<log4net>   
    <!– Rolling File Appender –>
    <appender name="RollingFileAppender" type="log4net.Appender.RollingFileAppender">
        <file value="log-file.txt" />
        <appendToFile value="true" />
        <maximumFileSize value="1KB" />
        <maxSizeRollBackups value="0" />
        <staticLogFileName value="true" />           
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%date [%thread] %-5level %logger – %message%newline" />
        </layout>
    </appender>

    <!– Console appender –>
    <appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
        <target value="Console.Error" />
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%message%newline" />
        </layout>
    </appender>
   
    <root>
        <level value="DEBUG" />
        <appender-ref ref="RollingFileAppender" />
        <appender-ref ref="ConsoleAppender" />
    </root>   
</log4net> 

In this configuration, I define two different appenders (RollingFile and Console), each with its own configuration. At the root level, I define the logging level at DEBUG (so I want to see everything until this level), and that the logging should be done to the two defined appenders. So, when I log something with this configuration, the log is done to a file and to the application's console.

So, you see that it is easy to add logging capabilities to your application.