Implementing REST Web services Part 2

Mea Culpa

Yesterday’s post showed a rudimentary WCF Rest service and how we need to change the system.serviceModel tag to support a REST service rather than a SOAP based WCF service. The service returned a string. The reason I set that up was because an object must be serialized prior to being sent back. Originally I thought that had to be done by the developer.

Nope.

The serialization of the object is done by the WCF infrastructure prior to sending it back to the calling function. For this reason there is no need to serialize the object yourself.

The revised interface is as follows;

[ServiceContract]
public interface IUser
{
    [WebGet(UriTemplate = "Login?email={email}&password={password}")]
    [OperationContract]
    [XmlSerializerFormat]
    LoginResult Login(String Email, String Password);
}

and the implementation of the Login method is

public LoginResult Login(string Email, string Password)
{
    RegisteredUserDataSource ds = null;
    String sessionId            = String.Empty;
    LoginResult result          = null;

    try
    {
        result                   = new LoginResult();
        result.Error             = new Error();
        result.Error.ErrorNumber = 0;
        result.Error.Message     = "OK";
        ds                       = new RegisteredUserDataSource();
        sessionId                = ds.LoginUser(Email, ds.EncryptString(Password), HostAddress());

        if (sessionId == String.Empty)
        {
            result.Error.ErrorNumber = 1001;
            result.Error.Message     = "Unrecognised Email and Password combination";
        }
    }
    catch(System.Exception ex)
    {
        result.Error.Message     = ex.Message;
        result.Error.ErrorNumber = 1002;
    }
    finally
    {
        ds               = null;
        result.SessionId = sessionId;
    }

    return result;
}

There are two classes of note here. The first is the Error Object. This will allow us to transfer back to the client the details of any error. This class if defined as follows;

[DataContract]
public class Error
{

    [DataMember]
    public int ErrorNumber
    {
        get;
        set;
    }

    [DataMember]
    public String Message
    {
        get;
        set;
    }
}

At the moment this should be enough to let the caller know what went wrong. It consists of just an error number and a message.

The other object is the LoginResult object. This inherits from a third object called the BaseReturnObject – initially this will just have the Error object, but by doing this it gives us the option of adding more common properties should the need arise.

[DataContract]
public class BaseReturnObject
{
    [DataMember]
    public Error Error { get; set; }
}

and the LoginResult object itself.

[DataContract]
public class LoginResult : BaseReturnObject
{
    [DataMember]
    public String SessionId
    {
        get;
        set;
    }
}

So now we have the object for the method to return.

The Client End

There is not much point in a service if there is nothing to consume it! So now we have to write the code to consume the service that has just been written but before I do lets consider the object that is returned back from the service. I have split this out to a separate module in the project. The reason for this is to enable reuse. The last thing I want to do write two versions of every return object – eventually I can see this being 100’s of objects! By splitting it out I can set a relationship to the project from both the client and the service.

Essentially to call a REST service what we need to do is make a web call to the service and examine the string returned for the results of our call. To find out the format of the call we need to go back to the service code. Below is the declaration of the Login Service

[WebGet(UriTemplate = "Login?email={email}&password={password}")]
[OperationContract]
[XmlSerializerFormat]
LoginResult Login(String Email, String Password);

What we are interested here is the WebGet attribute. This tells us the format of service call for this method and we add the string to the baseUri of the service. Just temporarily I have set a variable to this baseUri but long term it would be better if this came from a configuration setting.

String baseUri = "http://127.0.0.1:8080/User.svc/";

And Later we add to this the address to the service.

url = baseUri + String.Format("Login?email={0}&password={1}", txtEmail.Text, txtPassword.Text);

Now the service is designed to use the QueryString parameter  to represetn the service parameters. I’ve used String.Format to add the required QueryString parameters to the Uri. You will also notice that the parameters denoted by {email}  and  {password} are matched by the calling parameters of the service.

Now we have the address we need to call we can make the call to the service and check the result.

HttpWebRequest request = WebRequest.Create(url) as HttpWebRequest;

using (HttpWebResponse response = request.GetResponse() as HttpWebResponse)
{
    reader           = new StreamReader(response.GetResponseStream());
    result           = reader.ReadToEnd();
    serializedResult = Server.HtmlDecode(result);
    resultObj        = (LoginResult)Toolbox.Deserialize(typeof(LoginResult), serializedResult);

    if (resultObj.Error.ErrorNumber != 0)
    {
        throw new Exception(resultObj.Error.Message);
    }

}

As this is currently being called from the Web Page it is a synchronous call. Silverlight when I come around to it will need a asynchronous call. First off is to make the request of the method which is what the WebRequest.Create call. Then what we do is check the response with the GetResponse method which returns back and an instance of HttpWebResponse. Because the HttpWebResponse object inherits from IDisposable we can use the ‘using’ construct – which will automatically dispose of the object when we have finished.

Now a response is sent back to the calling function as a stream. We make a call to GetResponseStream to return this stream and then we read the stream into a string.

Now before sending back the results certain characters are replaced with escape sequences – so what we need to do is replace these escape sequences with the correct charactrers – which is why we make a call to the Server.HttpDecode method.

Now we have a string which can be deserialized into a .Net class for easier manipulation.

I have written a static toolbox method to do this for me – just to avoid having to repeat it – making the class and method both static means there is no need to create an instance of the Toolbox class.

The code for the Deserialize method is as follows;

public static Object Deserialize ( Type type, String SerializedObject )
{
    Object resultObj = null;

    ASCIIEncoding encoder       = null;
    MemoryStream ms             = null;
    XmlSerializer serializer    = null;
    XmlTextWriter xmlTextWriter = null;

    encoder = new ASCIIEncoding();
    ms = new MemoryStream(encoder.GetBytes(SerializedObject));
    serializer = new XmlSerializer(type);
    xmlTextWriter = new XmlTextWriter(ms, Encoding.ASCII);
    resultObj = serializer.Deserialize(ms);

    return resultObj;
}

So there we have it – a client to call the REST service.

Implementing REST Web services Part 1

Introduction

I want my project to support numerous clients form factors. This is becoming even more important now the number of form factors has increased – what with servers, desktops, laptops, notebooks, net books, slates (of various sizes) and smart phones – that is before we get to OS such as Android, Windows Phone 7, iOS and that is just phones! . All have differing screen sizes but more importantly the quality of the connection to the internet differs greatly – the speed of a home or work based network is a lot faster than the wireless cell network.

Although using WCF is fairly easy because of things like the SOAP envelope the amount of information transferred over the wire is that much greater than just the data being transferred. The SOAP envelope makes connecting to a WCF service easier – because the service itself informs the client of the data format. REST allows for quicker transfer of data, but sacrifices some of the simplicity. On the other hand REST uses nothing more than HTTP and that is widely available. Anyway much of the extra complexity can be hidden behind a object class which can be implemented in any language that is appropriate.

So any way this prompted me to look at the practicalities of implementing the web services in my project in the REST format. This would then provide a light weight service that can be called from any service going.

As it happens when doing this I found another advantage. Back when I first did ASPX Web Services a page was created with a full test harness – I could test the service just by going to an address in my browser. This is particularly useful when wanting to test a rollout – I found this much more awkward with WCF – although there is a test client. In REST we get this option back – just by going to the web address associated with the call you want to test.

Getting Started

Starting the creation of a REST web service is exactly the same as with a WCF Service. Once the WCF Service is created we need to modify the setup to make it a REST service (OK possible are you NUTS moment altering a web.config. I have a User service and below is the ServiceModel tag from the web.config of the web service.

  <system.serviceModel>
      <behaviors>
          <endpointBehaviors>
              <behavior name="webBehavior">
                  <webHttp/>
              </behavior>
          </endpointBehaviors>
      </behaviors>
      <services>
          <service name="MyCompanyService.User">
              <endpoint address="" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="MyCompanyService.IUser" />
              <endpoint address="rest" behaviorConfiguration="webBehavior" binding="webHttpBinding" bindingConfiguration="" contract="MyCompanyService.IUser" />
          </service>
      </services>
  </system.serviceModel>

The principle change was the creation of a new behaviour (webBehavior) and changes to the binding to use webHttpBinding.

Now on to creating the initial service.

The first service has to do with Users. First up is the Login method so deleting the DoWork method from the interface I am going to replace it with a Login method that takes two parameters; email and password.

[ServiceContract]
public interface IUser
{
    [WebGet(UriTemplate = "Login?email={email}&password={password}",
            ResponseFormat=WebMessageFormat.Xml)]
    [OperationContract]
    String Login(String Email,String Password);
}

Couple of changes here from a traditional WCF service in that we give it a an extra attribute; the WebGet attribute. The first parameter here is the UriTemplate – this determines the web address that will be used to access this service. In this instance we will add ‘/login?email=myemail@mydomain.com&password=mypassword’ to the address of the service. I have also added the ResponseFormat and set it to Xml – this is because it allows me to use serialization to transfer any object to an Xml String from the service and the client.

[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class User : IUser
{

    public string Login(string Email, string Password)
    {
        return String.Format("Hello {0} your password is {1}",Email,Password);
    }
}

This is just for testing purposes so all it does is pass back a string containing the email and password. It is kind of a REST equivalent of ‘Hello World’. So if we now run our project.

When the project is running start a new instance of IE (or any browser) and type the following in the address bar;

 http://127.0.0.1:8080/User.svc/Login?email=myemail@mydomain.com&password=secretword

What you should get is something like the following;

image

This shows a browser and the string passed back from the service – thereby demonstrating it works!

Out of interest checking the source of the page gives the following XML

So that is the service setup. I’m going to add to this once I have implemented something a bit more interesting than yet another ‘Hello World’

2010 in review

The stats helper monkeys at WordPress.com mulled over how this blog did in 2010, and here’s a high level summary of its overall blog health:

Healthy blog!

The Blog-Health-o-Meter™ reads This blog is doing awesome!.

Crunchy numbers

Featured image

A Boeing 747-400 passenger jet can hold 416 passengers. This blog was viewed about 6,200 times in 2010. That’s about 15 full 747s.

In 2010, there were 9 new posts, not bad for the first year! There were 18 pictures uploaded, taking up a total of 2mb. That’s about 2 pictures per month.

The busiest day of the year was September 12th with 66 views. The most popular post that day was Using a Custom Membership Provider in an MVC Application.

Where did they come from?

The top referring sites in 2010 were digg.com, google.co.in, google.com, michael-jackson-secret-exposed.xpac.info, and android-vs-ipad.co.cc.

Some visitors came searching, mostly for mvc custom membership provider, custom membership provider mvc, mvc own membership, mvc custom membership, and custom membership provider.

Attractions in 2010

These are the posts and pages that got the most views in 2010.

1

Using a Custom Membership Provider in an MVC Application June 2010
3 comments

2

Sending a confirmation email after registration April 2010

3

Using the Companies House GovTalk Service to retrieve Company Details July 2010

4

Connecting a WCF Service to an Model View Controller Client June 2010
1 comment

5

About January 2010

Building a better mouse-trap – Improving the creation of XML Message Requests using Reflection, XML & XSLT

Introduction

The way I previously created messages to send to the GovTalk service I used the XMLDocument to create the request. While this worked it left a number of problems; not least that for every message a special function would need to created. This is OK for the short term but the biggest cost in any software project is maintenance and this would be a headache to maintain.

So the following is a somewhat better way of achieving the same thing. For the purposes of this article I am going to be using the CompanyNumberSearch request of the GovTalk service – although this technique would work for any service that accepted XML. The C# functions which send and receive the messages remain the same. The magic sauce in this is the XSLT which defines the structure of the request, and the use of objects in conjunction with reflection to provide the content. It is a bit like Sweet Chilli Sauce added to Chicken on a bed of rice. So on to the Sweet Chilli Sauce

The Sweet Chilli Sauce

The request to search for a company based on it’s number is as follows;

<GovTalkMessage xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd" xmlns="http://www.govtalk.gov.uk/CM/envelope" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <EnvelopeVersion>1.0</EnvelopeVersion>
    <Header>
         <MessageDetails>
              <Class>NumberSearch</Class>
                   <Qualifier>request</Qualifier>
                   <TransactionID>1</TransactionID>
         </MessageDetails>
         <SenderDetails>
              <IDAuthentication>
                   <SenderID>????????????????????????????????</SenderID>
                   <Authentication>
                        <Method>CHMD5</Method>
                        <Value>????????????????????????????????</Value&gt
                   </Authentication>
              </IDAuthentication>
         </SenderDetails>
  </Header>
  <GovTalkDetails>
       <Keys/>
  </GovTalkDetails>
  <Body>
       <NumberSearchRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/NumberSearch.xsd">
            <PartialCompanyNumber>99999999</PartialCompanyNumber><
            <DataSet>LIVE</DataSet>
            <SearchRows>1</SearchRows>
       </NumberSearchRequest>
  </Body>
</GovTalkMessage>

This is the XML that we send to the GovTalk Service and we get back a list of companies that match the criteria passed

A message is structured in two parts; The envelope which identifies the person sending the request, with the name of the request, and the body which gives the detail of the company we are looking for.

The Chilli

What makes it possible is the use of XSLT to define the message – and serialization to convert each request object into XML. To start we need to create an object which will represent the contents of the message we are sending. However there is a common properties in all the messages that we send to Companies House. These properties are as follows

  • SenderId – the id of the person sending the message
  • SenderPassword – the password associated with Id
  • TransactionId – Unique identifier for the message
  • AuthenticationValue – authenticates the request

Because these properties are unique to the Companies House message, and because they are shared with all messages they are perfect candidates for a base class.

The class is as follows;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.WindowsAzure.ServiceRuntime;

namespace CompanyHub.Services
{
    public class GovTalkRequest
    {
        public GovTalkRequest()
        {
            try
            {
                SenderID            = RoleEnvironment.GetConfigurationSettingValue("SenderId");
                SenderPassword      = RoleEnvironment.GetConfigurationSettingValue("SenderPassword");
                TransactionId       = DateTime.Now.Ticks.ToString();
                AuthenticationValue = EncodePassword(String.Format("{0}{1}{2}", SenderID, SenderPassword, TransactionId));
            }
            catch (System.Exception ex)
            {
                throw ex;
            }
        }

        /// <summary>
        /// returns the Sender ID to be used when communicating with the GovTalk Service
        /// </summary>
        public String SenderID
        {
            get;
            set;
        }

        /// <summary>
        /// return the password to be used when communicating with the GovTalk Service
        /// </summary>
        public String SenderPassword
        {
            get;
            set;
        }                           // end SenderPassword

        /// <summary>
        /// Transaction Id - uses the Time and Date converted to Ticks
        /// </summary>
        public String TransactionId
        {
            get;
            set;
        }                               // end TransactionId

        /// <summary>
        /// calculate the authentication value that will be used when
        /// communicating with
        /// </summary>
        public String AuthenticationValue
        {
            get;
            set;
        }                   // end AuthenticationValue property

        /// <summary>
        /// encodes password(s) using MD5
        /// </summary>
        /// <param name="clearPassword"></param>
        /// <returns></returns>
        public static String EncodePassword(String clearPassword)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] hashedBytes;

            UTF32Encoding encoder = new UTF32Encoding();
            hashedBytes = md5Hasher.ComputeHash(ASCIIEncoding.Default.GetBytes(clearPassword));

            String result = Regex.Replace(BitConverter.ToString(hashedBytes), "-", "").ToLower();

            return result;

        }
    }
}

There is nothing particularly clever here, except for the EncodePassword method which hashes the value made up of the SenderId, Password and Transaction id.

Each message inherits from this object. So for the Company Number Search in addition to the properties above we need a partial number, which dataset to search – for the purposes of the project we only need to search the LIVE set so this can be set in the constructor and the SearchRows. Again all are set as properties. With the SearchRows and DataSet initialized in the constructor.

public class CompanyNumberSearchRequest : GovTalkRequest, IDisposable
{
    /// <summary>
    ///
    /// </summary>
    public CompanyNumberSearchRequest() : base()
    {
        DataSet = "LIVE";
        SearchRows = 1;
    }

    /// <summary>
    /// Company Number to search against
    /// </summary>
    public String PartialCompanyNumber { get; set; }

    /// <summary>
    /// What DataSet should be searched for the company
    /// </summary>
    public String DataSet { get; set; }

    /// <summary>
    /// How many rows should be returned
    /// </summary>
    public int SearchRows { get; set; }

    public void Dispose()
    {
        DataSet              = String.Empty;
        PartialCompanyNumber = String.Empty;
        DataSet              = "LIVE";
        SearchRows           = 1;
    }
}

As well as inheriting from our base class, I have also inherited from IDisposable – not just because it is just plain good practice to dispose of objects when coding, but it gives also gives us more versatility when using the object.

There are four stages in making a request and this is reflected in the four methods we execute in making a call to the Companies House service;

  • Create a request
  • Send a request
  • Check the status
  • If OK then get the results of the request

I’ve implemented each of these stages within a static class called Toolbox – which also means I don’t need to create an instance of the class to use it.

When making a request there are three stages;

  • Get the template for the message
  • Serialize the object representing the message
  • Transform the serialized object using a predefined XSLT file.

Each of my templates I have defined as an embedded resource. When retrieving a resource of this kind we have to include the full namespace to the resource. In making the code re-usable as much as possible I defined the full ‘path’ within the GetRequest method.

requestFile = String.Format("CompanyHub.Services.Schemas.{0}", RequestFile);

So we now have the full path of the file within the assembly. Now all we need do is retrieve the assembly and get the resource.

asm         = Assembly.GetExecutingAssembly();
sr          = asm.GetManifestResourceStream(requestFile);

Once retrieved 

So this can be returned to the calling function and we now have a stream of XSLT to define the message. Time now to serialize the request to create the other side of this message.

// Serialize object containing Request, Load into XML Document
t             = Obj.GetType();
ms            = new MemoryStream();
serializer    = new XmlSerializer(t);
xmlTextWriter = new XmlTextWriter(ms, Encoding.ASCII);

serializer.Serialize(xmlTextWriter, Obj);
ms = (MemoryStream)xmlTextWriter.BaseStream;
GovTalkRequest = Toolbox.ConvertByteArrayToString(ms.ToArray());

First off we need the type of the object so we make a call to the GetType method of the object containing the Message properties.

Next we need a MemoryStream, XmlSerializer and an XMLTextWriter so these can be initialized.

The object is serialized by making the call to the Serialize method of the serializer object. The result of that is then converted into a MemoryStream. That MemoryStream is then converted into a string.

ConvertByteArrayToString

This is a fairly simple function which uses an ASCIIEncoding object found within the System.Text namespace to convert an array of bytes into a string.

public static String ConvertByteArrayToString(byte[] bytes)
{
    System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
    return enc.GetString(bytes);
}

I only put it into a function because I will be using this in various places.

The Sauce

When adding support for other messages outside of creating a new object to store the properties of the message, the C# components do not need to change. It is in the XSLT file that the versatility of the technique lies. The XSLT file determines the format of the message. For the CompanyNumberSearch the XSLT file is as follows;

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
    <xsl:template match="/">
        <GovTalkMessage xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd" xmlns="http://www.govtalk.gov.uk/CM/envelope" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
            <EnvelopeVersion>1.0</EnvelopeVersion>
            <Header>
                <MessageDetails>
                    <Class>NumberSearch</Class>
                    <Qualifier>request</Qualifier>
                    <TransactionID>
                        <xsl:value-of select="CompanyNumberSearchRequest/TransactionId"/>
                    </TransactionID>
                </MessageDetails>
                <SenderDetails>
                    <IDAuthentication>
                        <SenderID><xsl:value-of select="CompanyNumberSearchRequest/SenderID"/></SenderID>
                        <Authentication>
                            <Method>CHMD5</Method>
                            <Value>
                                <xsl:value-of select="CompanyNumberSearchRequest/AuthenticationValue"/>
                            </Value>
                        </Authentication>
                    </IDAuthentication>
                </SenderDetails>
            </Header>
            <GovTalkDetails>
                <Keys/>
            </GovTalkDetails>
            <Body>
                <NumberSearchRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/NumberSearch.xsd">
                    <PartialCompanyNumber>
                        <xsl:value-of select="CompanyNumberSearchRequest/PartialCompanyNumber"/>
                    </PartialCompanyNumber>
                    <DataSet>
                        <xsl:value-of select="CompanyNumberSearchRequest/DataSet"/>
                    </DataSet>
                    <SearchRows>
                        <xsl:value-of select="CompanyNumberSearchRequest/SearchRows"/>
                    </SearchRows>
                </NumberSearchRequest>
            </Body>
        </GovTalkMessage>

    </xsl:template>
</xsl:stylesheet>

The outer two tags define that this is a XSLT stylesheet and the root tag from which the nodes are searched for.

The GovTalkMessage is the format of the message that will be sent to Companies House.

We first set up the XslCompiledTransform object which will transform the XSLT template and the serialized object into the request to Companies House.

xslt            = new XslCompiledTransform();
resultStream    = new MemoryStream();
writer          = new XmlTextWriter(resultStream, Encoding.ASCII);
doc             = new XmlDocument();

The Serialize method require XmlTextWriter to write the XML (writer) and a stream to place the transferred object into (writer). The XML will be loaded into an XMLDocument object (doc) prior to the transformation.

// create XSLT Template
xslTemplate = Toolbox.GetRequest(Template);
xslTemplate.Seek(0, SeekOrigin.Begin);
templateReader = XmlReader.Create(xslTemplate);
xslt.Load(templateReader);

I have stored all the templates as a series of Embedded Resources and the GetRequestCall takes the name of the template and extracts the relevent XSLT file.

        /// <summary>
        /// Gets the framwork XML which makes the request
        /// </summary>
        /// <param name="RequestFile"></param>
        /// <returns></returns>
        public static Stream GetRequest(String RequestFile)
        {
            String requestFile = String.Empty;
            Stream sr          = null;
            Assembly asm       = null;

            try
            {
                requestFile = String.Format("CompanyHub.Services.Schemas.{0}", RequestFile);
                asm         = Assembly.GetExecutingAssembly();
                sr          = asm.GetManifestResourceStream(requestFile);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                asm = null;
            }

            return sr;
        }                           // end private static stream GetRequest

We first take the template name and expand it to include the full namespace to the Embedded Resource I like to keep all my schemas in the same directory and so the namespace reflects this. The rest is the default namespace for the project.

Then we get the currently executing assembly (which will contain the resources with the call to GetExecutingAssembly() )

Finally we get a stream which contains the XSLT file. We use this stream and then load an XmlReader with the contents of the template, and that is in turn loaded into the XslCompiledTransform object.

We convert the object containing the message properties into Xml by serializing it; calling the Serialize() method of the XmlSerializer object. To set up the object we do the following;

t             = Obj.GetType();
ms            = new MemoryStream();
serializer    = new XmlSerializer(t);
xmlTextWriter = new XmlTextWriter(ms, Encoding.ASCII);

We first determine the type of the object being transferred by calling GetType() We create an XmlSerializer object by passing the type of the object being serialized. The serializer writes to a memory stream and that is linked to an XmlTextWriter.

Next job is to serialize the object and load it into an XmlDocument.

serializer.Serialize(xmlTextWriter, Obj);
ms = (MemoryStream)xmlTextWriter.BaseStream;
xmlRequest = new XmlTextReader(ms);
GovTalkRequest = Toolbox.ConvertByteArrayToString(ms.ToArray());

doc.LoadXml(GovTalkRequest);

Time to transform the XML to construct the full request.

xslt.Transform(doc, writer);

resultStream.Seek(0, SeekOrigin.Begin);
request = Toolbox.ConvertByteArrayToString(resultStream.ToArray());

So that creates the full request to be sent  to Companies House.

Sending the request

So far we have a string with a request for the Companies House service. Now we need to send the request to the Companies House Service.

Configuration within an Azure project

There are entire blog entries written about configuration within an Azure project – most of this is out of scope for this article but the following is a summary.

Configuration is defined in two files within the parent project *.csdef which contains the definition of configuration setting.

<?xml version="1.0" encoding="utf-8"?>
<ServiceDefinition name="OnlineCompanyHub" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceDefinition">
  <WebRole name="CompanyHub.Host">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="80" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
      <Setting name="DataConnectionString" />
    </ConfigurationSettings>
  </WebRole>
  <WebRole name="CompanyHub.Services">
    <InputEndpoints>
      <InputEndpoint name="HttpIn" protocol="http" port="8080" />
    </InputEndpoints>
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
        <Setting name="SenderId"/>
        <Setting name="SenderPassword" />
        <Setting name="GovTalkUrl"/>
    </ConfigurationSettings>
  </WebRole>
  <WorkerRole name="CompanyHub.Worker">
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
    </ConfigurationSettings>
  </WorkerRole>
</ServiceDefinition>

 

Above is the configuration definition from the project. What we are interested in however is the ConfigurationSettings tag of the CompanyHub.Services WebRole.

There are four configuration settings here, but at the moment we are interested in the second to forth settings; SenderId, SenderPassword and GovTalkUrl

The value of these settings are defined in the ServiceDefinition.cscfg file;

<?xml version="1.0"?>
<ServiceConfiguration serviceName="OnlineCompanyHub" xmlns="http://schemas.microsoft.com/ServiceHosting/2008/10/ServiceConfiguration">
  <Role name="CompanyHub.Host">
    <Instances count="2" />
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="DataConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
  <Role name="CompanyHub.Services">
    <Instances count="2" />
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
        <Setting name="SenderId" value="UserID"/>
        <Setting name="SenderPassword" value="Password"/>
        <Setting name="GovTalkUrl" value="http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway"/>
    </ConfigurationSettings>
  </Role>
  <Role name="CompanyHub.Worker">
    <Instances count="2" />
    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>
  </Role>
</ServiceConfiguration>

 

Look for the Role tag that contains our project name (CompanyHub.Services).

Having configured the parameters we can now transmit the request. This is done by ‘POST’ing a stream of XML to the Companies House servers.

govTalkUrl          = RoleEnvironment.GetConfigurationSettingValue("GovTalkUrl");
request             = WebRequest.Create(govTalkUrl);
request.Method      = "POST";
request.ContentType = "text/xml";
writer              = new StreamWriter(request.GetRequestStream());

writer.WriteLine(RequestMessage);
writer.Close();

We use the WebRequest object to send the object. Set the method of sending to ‘POST’ and the type of data as text/xml. Once set up all we do is write the request to the writer – this sends the request to Companies House.

Did the Request Work Part I – Getting the response

Having sent a request – we now need the result of that request.

response = request.GetResponse();
reader   = response.GetResponseStream();
result   = Toolbox.ConvertByteArrayToString(Toolbox.ReadFully(reader));

 

The WebRequest object has a GetResponse() method which allows us to get the response sent back. Like many of these calls the results come in the form of a stream which we convert into a string.

Did the Request Work Part II – Translating the Response

Much like XSLT and XML were used to create the original request, so it can be used to extract the response and by deserializing the result we create an object that contains the response.

Did it work?

It would be really great if everything worked all the time. Of course if it did then I don’t suppose people would pay me and others the big bucks so that our programmes do not

a) Collapse in a heap (this is an area of memory)

b) Blow every fuse in the place in a shower of sparks (this will probably not happen this being real life and not a Hollywood movie, but it was possible to blow the sound system of a BBC Model B with a poorly coded setting)

c) Go nuts and trap everyone outside the airlock (this was from a movie, and unless NASA get a manned moon/mars mission set up unlikely to happen)

d) Go nuts and take over the world (this was also from a movie, but please note life has a habit of being of exceeding the wildest imaginations of Hollywood writers (note writers – Hollywood executives have no imagination and judging by recent output of that town have turned plagiarism into an art form).

e) Freeze in total confusion because the cleaner pulled the plug to the internet router (this has happened)

So anyway – we need to check to see if our request actually worked. Within the GovTalk response there is a section that details the status of the message and a description of what went wrong (if anything did). I have defined an XSLT template which will extract these into an XML document.

<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
                xmlns:ev="http://www.govtalk.gov.uk/CM/envelope"
                xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core"
                xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
    <xsl:template match="/">
        <GovTalkStatus xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                       xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <Status>
                <xsl:value-of select="ev:GovTalkMessage/ev:Header/ev:MessageDetails/ev:Qualifier"/>
            </Status>
            <Text>
                <xsl:value-of select="ev:GovTalkMessage/ev:GovTalkDetails/ev:GovTalkErrors/ev:Error/ev:Text"/>
            </Text>
            <Location>
                <xsl:value-of select="ev:GovTalkMessage/ev:GovTalkDetails/ev:GovTalkErrors/ev:Error/ev:Location"/>
            </Location>
            <Number>
                <xsl:value-of select="ev:GovTalkMessage/ev:GovTalkDetails/ev:GovTalkErrors/ev:Error/ev:Number"/>
            </Number>
            <Type>
                <xsl:value-of select="ev:GovTalkMessage/ev:GovTalkDetails/ev:GovTalkErrors/ev:Error/ev:Type"/>
            </Type>
        </GovTalkStatus>

    </xsl:template>
</xsl:stylesheet>

 

Only thing different about previous XSL files is the references to two namespaces ev & gt. These are defined in the GovTalk response at the top of the response;

xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd"
        xmlns="http://www.govtalk.gov.uk/CM/envelope"
        xmlns:dsig="http://www.w3.org/2000/09/xmldsig#"
        xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core"

If we do not put these references into the XSLT template then  the XslCompiledTransform object will not be able to find the relevant tags.

Deserialization is a fairly simple activity.

encoder = new ASCIIEncoding();
ms = new MemoryStream(encoder.GetBytes(statusXML));
serializer    = new XmlSerializer(typeof(GovTalkStatus));
xmlTextWriter = new XmlTextWriter(ms, Encoding.ASCII);
messageStatus = (GovTalkStatus)serializer.Deserialize(ms);

We set up a serialization object using the object type containing the error state and pass to it the results of a transformation between the XSLT above and the GovTalk response.

Now we have an object containing any error state, and the error message. All we need to do is check the status. If there is an error then we can flag an error. If not then  we extract the results and pass that as an object back to the calling function. We go this by guess what – defining an XSLT template for the result and using that to create an Xml Stream which can be deserialized into a .Net object. In this instance the XSLT to create the result of a Company Number Search is;

<?xml version="1.0" encoding="us-ascii"?>
<xsl:stylesheet version="1.0"
        xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
        xmlns:ev="http://www.govtalk.gov.uk/CM/envelope"
        xmlns:sch="http://xmlgw.companieshouse.gov.uk/v1-0/schema"
        exclude-result-prefixes="ev">
    <xsl:template match="/">
        <CompanySearchResult    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                                xmlns:xsd="http://www.w3.org/2001/XMLSchema">
            <CompanyNumber>
                <xsl:value-of select="ev:GovTalkMessage/ev:Body/sch:NumberSearch/sch:CoSearchItem/sch:CompanyNumber"/>
            </CompanyNumber>
            <CompanyName>
                <xsl:value-of select="ev:GovTalkMessage/ev:Body/sch:NumberSearch/sch:CoSearchItem/sch:CompanyName"/>
            </CompanyName>
        </CompanySearchResult>
    </xsl:template>
</xsl:stylesheet>

and the object definition is;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

namespace CompanyHub.Services
{
    public class CompanySearchResult
    {
        public CompanySearchResult()
        {
            CompanyNumber = String.Empty;
            CompanyName = String.Empty;
        }

        public String CompanyNumber { get; set; }
        public String CompanyName { get; set; }
    }
}

Our entire code to make calls to send a request, and interpret the results are;

String request  = String.Empty;
String response = String.Empty;
GovTalkStatus status = null;

fault = null;

try
{
    using (CompanyNumberSearchRequest requestObj = new CompanyNumberSearchRequest())
    {
        requestObj.PartialCompanyNumber = CompanyNumber;

        request  = Toolbox.CreateRequest(requestObj, "CompanyNumberSearch.xsl");
        response = Toolbox.SendGovTalkRequest(request);
        status   = Toolbox.GetMessageStatus(response);

        if (status.Status.ToLower() == "error")
        {
            fault = new HubFault()
            {
                Message = status.Text
            };
        }
        else
        {
            Object obj = Toolbox.GetGovTalkResponse(response, "CompanyNumberSearchResult.xsl", typeof(CompanySearchResult));
        }
    }
}
catch (FaultException<ArgumentException> ex)
{
    fault = new HubFault()
    {
        FaultType = ex.Detail.GetType().FullName,
        Message   = ex.Detail.Message
    };
}
catch (System.Exception ex)
{
    fault = new HubFault()
    {
        FaultType = ex.GetType().FullName,
        Message   = ex.Message
    };
}
finally
{

}

Wrap up

So there we have it – a reusable set of functions to send and interpret XML results from an internet based service. The code is reusable with a little change with any service which uses XML as a transport mechanism – and as for the Companies House GovTalk service all I need to do is create various objects for the result and message sent and the relevent XSLT files. I might need minor changes for other services but something like 70-90% will be exactly the same.

Using the Companies House GovTalk Service to retrieve Company Details

As we move into the 2nd decade of the 21st century government data, hitherto closed, is now being opened up with governments adopting standards such as XBRL (eXtended Business Reporting Language). One of the functions I wanted was to retrieve the details of a company from the Companies House service. It would make it really simple for users to create their company in the service if all they have to do is provide the Company Number and/or the Name and hit a button. Certainly easier than all that tedious typing in. Additionally we can send data the other way – and therefore provide a simple easy way to make returns to Companies House.

Now Government data is open, but it is not that open. You need to apply to Companies House for an account. Initially and while you are developing and testing the service it returns only one company – MILLENIUM STADIUM PLC. Below is an image of my test site showing (some) of the details of the company retrieved.

Company Details Page

Web page showing some of the details available from the Company Details Service

To use the service you must apply by sending an email to xml@companieshouse.gov.uk, providing your name, address and telephone details. There is an FAQ on using the service available from http://xmlgw.companieshouse.gov.uk/faq.shtml.

Creating the request for Company Details.

Requests are sent to Companies house over Http coded as an XML file. The Company Details Request can be seen below;

<GovTalkMessage xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd" xmlns="http://www.govtalk.gov.uk/CM/envelope" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
<EnvelopeVersion>1.0</EnvelopeVersion>
<Header>
<MessageDetails>
<Class>CompanyDetails</Class>
<Qualifier>request</Qualifier>
<TransactionID>5</TransactionID>
</MessageDetails>
<SenderDetails>
<IDAuthentication>
<SenderID>????????????????????????????????</SenderID>
<Authentication>
<Method>CHMD5</Method>
<Value>????????????????????????????????</Value>
</Authentication>
</IDAuthentication>
</SenderDetails>
</Header>
<GovTalkDetails>
<Keys/>
</GovTalkDetails>
<Body>
<CompanyDetailsRequest xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema/CompanyDetails.xsd">
<CompanyNumber>99999999</CompanyNumber>
<CompanyName>TEST COMPANY PLC</CompanyName>
<GiveMortTotals>1</GiveMortTotals>
</CompanyDetailsRequest>
</Body>
</GovTalkMessage>

At it’s highest level this consists of two upper levels; the top ‘Header’ details the type of message in the MessageDetails tag, the Class giving what kind of request is being made (in this case the ‘CompanyDetails’ ). A qualifier which in this case is a ‘request’ and finally a Transaction ID. The combination of your login details and the Transaction ID has to be unique; once this has been used – it cannot be used again (or you will get an error). You could use a simple counter, but in my case – and partly to avoid having to set up the counter I am using the Ticks method of the DateTime – which is not due to recycle again until 2035 if memory serves which means plenty of time before this is likely to recycle.

The second part of this top tag identifies you to the Companies House Server. The SenderID is self explanatory and is the id you got when applying to Companies House. Method refers to the encryption used on the final tag; the ‘Value’ tag. This is created by appending the UserID and Password you got from Companies House with the Transaction ID in the above section. This combined string is then encrypted using MD5.

Encryption is undertaken by the following function;

        /// <summary>
        /// Encodes the password with MD5
        /// </summary>
        /// <param name="clearPassword"></param>
        /// <returns></returns>
        private String EncodePassword(String clearPassword)
        {
            MD5CryptoServiceProvider md5Hasher = new MD5CryptoServiceProvider();
            byte[] hashedBytes;

            UTF32Encoding encoder = new UTF32Encoding();
            hashedBytes = md5Hasher.ComputeHash(ASCIIEncoding.Default.GetBytes(clearPassword));

            String result = Regex.Replace(BitConverter.ToString(hashedBytes), "-", "").ToLower();

            return result;

        }

Note: I remove any of the dashes (‘-‘) from the encrypted string. It seems from testing that the Companies House service does not like ’em.

The second part of this message is the message itself. We set the Company Number and Name  we are looking for in this section.

To create the request I could have written a C# function to create the message on the fly but this is not only wasteful, but is also a maintenance headache if Companies House modifies the structure of these messages. So to help this what I did was to Add a scheme/framework message and added it to my project as an ‘Embedded Resource’, in a folder called ‘Schemas’. The following code then reads this file and returns it’s contents as a stream.

       /// <summary>
        /// Gets the framwork XML which makes the request
        /// </summary>
        /// <param name="RequestFile"></param>
        /// <returns></returns>
        private Stream GetRequest(String RequestFile)
        {
            String requestFile              = String.Empty;
            Stream sr                       = null;
            System.Reflection.Assembly asm  = null;

            try
            {
                requestFile = String.Format("Simplicita.Data.Services.Schemas.{0}", RequestFile);
                asm         = Assembly.GetExecutingAssembly();
                sr          = asm.GetManifestResourceStream(requestFile);
            }
            catch (Exception)
            {
                throw;
            }
            finally
            {
                asm = null;
            }

            return sr;
        }

The Address of the XML file is worked out by taking the default namespace + any sub folder + the file name. So looking in the above code my XML file can be found in Simplicita.Data.Services.Schemas – Schemas being the folder I put it into. Next we get the Executing Assembly; since the XML is stored in the assembly – and finally we call GetManifestResourceStream to retrieve it.

The results are then passed back to the calling function which loads the XML stream into an XML document. Now there are a couple of namespaces that are defined in the XML and we have to set these in the XML Document. We do this by defining a Namespace Manager and it is done this way;

            nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("default", "http://www.govtalk.gov.uk/CM/envelope");

I will need to define another namespace when retrieving the answer from Companies House, but for the moment I only need the one.

Now I said earlier that the TransactionId is set by taking the Ticks value of the current DateTime. This is set by the following declaration;

            long transactionId = DateTime.Now.Ticks;

We now have everything needed to set up the Authentication tag.

            TransactionID = xmlDoc.SelectSingleNode("default:GovTalkMessage/default:Header/default:MessageDetails/default:TransactionID", nsmgr);

            if (TransactionID != null) TransactionID.InnerText = transactionId.ToString();

            IDAuthentication = xmlDoc.SelectSingleNode("default:GovTalkMessage/default:Header/default:SenderDetails/default:IDAuthentication", nsmgr);

            // if we have found the authentication tag set the security parameters
            if (IDAuthentication != null)
            {
                SenderId = IDAuthentication.SelectSingleNode("default:SenderID", nsmgr);
                AuthenticationValue = IDAuthentication.SelectSingleNode("default:Authentication/default:Value", nsmgr);
                digest = String.Format("{0}{1}{2}", "UserID", "Password", TransactionID.InnerText);

                SenderId.InnerText = "XMLGatewayTestUserID";
                AuthenticationValue.InnerText = EncodePassword(digest);

            }

First up is to retrieve the TransactionID node from the XML, because of the namespace this has to be defined in the XPath address and the namespace manager is passed as the second parameter. When I defined the namespace manager in the line repeated below

nsmgr.AddNamespace("default", "http://www.govtalk.gov.uk/CM/envelope");

I defined the word ‘default’ as the namespace identifier. This is why ‘default‘  occurs before each level of the XPath address. Assuming we find the IDAuthentication tag then we go on to set the authentication details.

I’ve used String.Format to set a string containing the three items which make up the identification; UserID, Password and the TransactionID. This is then passed to the EncodePassword function which is shown above.

That then completes the identification side of the message creation. Now it time to set the nodes that identify what company – you are looking for. Time for a little sidebar; whatever company you give – when testing your account Companies House will only send you details of one company – Company Number 03176906, Millenium Stadium PLC (currently).

We basically set the CompanyNumber tag to the Company Number – or an empty string if we do not know it, and the CompanyName Tag to the Company Name or an empty string. Note in the template shown above these two tags have text with in them – if they are not set to an empty string then these values will be passed on!

The Code that sets these two tags can be seen below.

                DetailRequest = Body.SelectSingleNode("default:CompanyDetailsRequest", nsmgr);
                companyNumber = DetailRequest.SelectSingleNode("default:CompanyNumber", nsmgr);
                companyName = DetailRequest.SelectSingleNode("default:CompanyName", nsmgr);

                companyNumber.InnerText = CompanyNumber;
                companyName.InnerText = CompanyName;

Sending the request to Companies House.

That now completes the creation of the request. To send the XML to Companies we use the WebRequest class (see http://msdn.microsoft.com/en-us/library/system.net.webrequest(VS.71).aspx) to set up the request and then a StreamWriter to actually write the XML. First thing to do is to Create the request by making a call to the Create Method  of the WebRequest class (note: Not by using the new keyword), by passing it the Uri of the Companies House Service (http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway) Then tell it what kind of request this is going to be (POST) and finally the format (text/xml). We then request a Stream from the WebRequest object by making a call to GetRequestStream().

Finally the StreamWriter is used to write it to the web.

            WebRequest req = null;
            StreamWriter writer = null;
            String uri = String.Empty;
            uri = "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway";
            req = WebRequest.Create(uri);
            req.Method = "POST";
            req.ContentType = "text/xml";

            writer = new StreamWriter(req.GetRequestStream());
            writer.WriteLine(xmlDoc.OuterXml);
            writer.Close();

Getting a response to the request

Just as we used a WebRequest when sending the request, we use the WebResponse object to get the response, and a stream to read that response. First off get the response from the original WebRequest object. Then get a stream from the WebResponse.

            WebResponse         res                 = null;
            Stream              reader              = null;
            res = req.GetResponse();
            reader = res.GetResponseStream();

To read a stream we basically copy the stream into a MemoryStream and then once it has all be read into the MemoryStream and then subsequently we convert that stream into an Array of Bytes. This is done by the following function;

        private static byte[] ReadFully(Stream stream)
        {
            byte[] buffer = new byte[32768];
            using (MemoryStream ms = new MemoryStream())
            {
                while (true)
                {
                    int read = stream.Read(buffer, 0, buffer.Length);
                    if (read <= 0)
                        return ms.ToArray();
                    ms.Write(buffer, 0, read);
                }
            }
        }

Because we cannot load this Byte Array into an XmlDocument it must be first converted into a string. Bit of a pain really; in that we started with a Stream, converted that to a MemoryStream and then to a Byte Array and finally into a string. The function which does this final conversion is as follows;

        private String ConvertByteArrayToString(byte[] bytes)
        {
            System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding();
            return enc.GetString(bytes);
        }

To read the response into a string it now takes just one line;

String GatewayResult = ConvertByteArrayToString(ReadFully(reader));

Once this line is executed GatewayResult will have the response from Companies House. A correct response will be something like the following XML;

<?xml version="1.0" encoding="UTF-8" ?>
<GovTalkMessage xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd" xmlns="http://www.govtalk.gov.uk/CM/envelope" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <EnvelopeVersion>1.0</EnvelopeVersion>
  <Header>
    <MessageDetails>
      <Class>CompanyDetails</Class>
      <Qualifier>response</Qualifier>
      <TransactionID>634141362546959689</TransactionID>
      <GatewayTimestamp>2010-07-07T21:51:04-00:00</GatewayTimestamp>
    </MessageDetails>
    <SenderDetails>
      <IDAuthentication>
        <SenderID>YourUserID</SenderID>
        <Authentication>
          <Method>CHMD5</Method>
          <Value></Value>
        </Authentication>
      </IDAuthentication>
    </SenderDetails>
  </Header>
  <GovTalkDetails>
    <Keys/>
  </GovTalkDetails>
  <Body>
    <CompanyDetails xmlns="http://xmlgw.companieshouse.gov.uk/v1-0/schema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://xmlgw.companieshouse.gov.uk/v1-0/schema http://xmlgw.companieshouse.gov.uk/v1-0/schema/CompanyDetails-v2-1.xsd">
	<CompanyName>MILLENNIUM STADIUM PLC</CompanyName>
	<CompanyNumber>03176906</CompanyNumber>
	<RegAddress>
		<AddressLine>MILLENNIUM STADIUM</AddressLine>
		<AddressLine>WESTGATE STREET</AddressLine>
		<AddressLine>CARDIFF</AddressLine>
		<AddressLine>CF10 1NS</AddressLine>
	</RegAddress>
	<CompanyCategory>Public Limited Company</CompanyCategory>
	<CompanyStatus>Active</CompanyStatus>
	<CountryOfOrigin>United Kingdom</CountryOfOrigin>
	<RegDateType>0</RegDateType>
	<IncorporationDate>1996-03-25</IncorporationDate>
	<Accounts>
		<AccountRefDate>30-06</AccountRefDate>
		<NextDueDate>2010-12-31</NextDueDate>
		<Overdue>NO</Overdue>
		<LastMadeUpDate>2009-05-31</LastMadeUpDate>
		<AccountCategory>FULL</AccountCategory>
		<DocumentAvailable>1</DocumentAvailable>
	</Accounts>
	<Returns>
		<NextDueDate>2011-04-22</NextDueDate>
		<Overdue>NO</Overdue>
		<LastMadeUpDate>2010-03-25</LastMadeUpDate>
		<DocumentAvailable>1</DocumentAvailable>
	</Returns>
	<Mortgages>
		<MortgageInd>LT300</MortgageInd>
		<NumMortCharges>9</NumMortCharges>
		<NumMortOutstanding>9</NumMortOutstanding>
		<NumMortPartSatisfied>0</NumMortPartSatisfied>
		<NumMortSatisfied>0</NumMortSatisfied>
	</Mortgages>
	<SICCodes>
        	<SicText>9261 - Operate sports arenas &amp; stadiums</SicText>
	</SICCodes>
	<LastFullMemDate>2010-03-25</LastFullMemDate>
	<HasUKestablishment>0</HasUKestablishment>
	<HasAppointments>1</HasAppointments>
	<InLiquidation>0</InLiquidation>
</CompanyDetails>
  </Body>
</GovTalkMessage>

Which shows the default Millenium PLC company.

Last thing to do is convert that to an XmlDocument – for manipulation how ever you want.

            xmlResult = new XmlDocument();
            xmlResult.LoadXml(GatewayResult);

            return xmlResult;

Dealing with Errors

With the best will in the world it would be really nice if everything worked, all the time and everytime but life likes to make things interesting. If there is a problem with the request the GovTalk service will return something like the following;

<?xml version="1.0" encoding="UTF-8" ?>
<GovTalkMessage xsi:schemaLocation="http://www.govtalk.gov.uk/CM/envelope http://xmlgw.companieshouse.gov.uk/v1-0/schema/Egov_ch-v2-0.xsd" xmlns="http://www.govtalk.gov.uk/CM/envelope" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:gt="http://www.govtalk.gov.uk/schemas/govtalk/core" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" >
  <EnvelopeVersion>1.0</EnvelopeVersion>
  <Header>
    <MessageDetails>
      <Class>CompanyDetails</Class>
      <Qualifier>error</Qualifier>
      <TransactionID>634141372294837235</TransactionID>
      <GatewayTimestamp>2010-07-07T22:07:22-00:00</GatewayTimestamp>
    </MessageDetails>
    <SenderDetails>
      <IDAuthentication>
        <SenderID>UserID</SenderID>
        <Authentication>
          <Method>CHMD5</Method>
          <Value>MD5EncryptedAuthenticationString</Value>
        </Authentication>
      </IDAuthentication>
    </SenderDetails>
  </Header>
  <GovTalkDetails>
    <Keys/>
	<GovTalkErrors>
	  <Error>
	    <RaisedBy>CompanyDetails</RaisedBy>
	    <Number>502</Number>
	    <Type>fatal</Type>
	    <Text>Authorisation Failure</Text>
	    <Location></Location>
	  </Error>
	</GovTalkErrors>
  </GovTalkDetails>
  <Body>
  </Body>
</GovTalkMessage>

In this instance the Qualifier tag will have the value error rather than response   which is returned when the request succeeds. The details of the error can be found in the GovTalkMessage/GovTalkDetails/GovTalkErrors tag. In the above I had altered the password so that it would not authenticate – hence the authorisation failure that can be seen in the Text tag that is contained in the Error tag.

Final Comments

That completes the requesting of Company Details from Companies House – they are now in an XmlDocument for manipulation in whatever way is required. The complete function for sending the request is shown below.

        private XmlDocument GovTalkCompanyDetailRequest(String CompanyNumber, String CompanyName)
        {
            long                transactionId       = DateTime.Now.Ticks;
            String              uri                 = String.Empty;
            String              digest              = String.Empty;
            XmlDocument         xmlDoc              = null;
            XmlDocument         xmlResult           = null;
            XmlNode             TransactionID       = null;
            XmlNode             IDAuthentication    = null;
            XmlNode             SenderId            = null;
            XmlNode             companyNumber       = null;
            XmlNode             companyName         = null;
            XmlNode             AuthenticationValue = null;
            XmlNode             Body                = null;
            XmlNode             DetailRequest       = null;
            XmlNamespaceManager nsmgr               = null;
            WebRequest          req                 = null;
            WebResponse         res                 = null;
            StreamWriter        writer              = null;
            Stream              str                 = null;
            Stream              reader              = null;

            uri = "http://xmlgw.companieshouse.gov.uk/v1-0/xmlgw/Gateway";

            xmlDoc = new XmlDocument();
            str = GetRequest("CompanyDetailRequest.xml");
            xmlDoc.Load(str);

            nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
            nsmgr.AddNamespace("default", "http://www.govtalk.gov.uk/CM/envelope");

            TransactionID = xmlDoc.SelectSingleNode("default:GovTalkMessage/default:Header/default:MessageDetails/default:TransactionID", nsmgr);

            if (TransactionID != null) TransactionID.InnerText = transactionId.ToString();

            IDAuthentication = xmlDoc.SelectSingleNode("default:GovTalkMessage/default:Header/default:SenderDetails/default:IDAuthentication", nsmgr);

            // if we have found the authentication tag set the security parameters
            if (IDAuthentication != null)
            {
                SenderId = IDAuthentication.SelectSingleNode("default:SenderID", nsmgr);
                AuthenticationValue = IDAuthentication.SelectSingleNode("default:Authentication/default:Value", nsmgr);
                digest = String.Format("{0}{1}{2}", "UserID", "Password", TransactionID.InnerText);

                SenderId.InnerText = "XMLGatewayTestUserID";
                AuthenticationValue.InnerText = EncodePassword(digest);

            }

            Body = xmlDoc.SelectSingleNode("default:GovTalkMessage/default:Body", nsmgr);

            if (Body != null)
            {
                DetailRequest = Body.SelectSingleNode("default:CompanyDetailsRequest", nsmgr);
                companyNumber = DetailRequest.SelectSingleNode("default:CompanyNumber", nsmgr);
                companyName = DetailRequest.SelectSingleNode("default:CompanyName", nsmgr);

                companyNumber.InnerText = CompanyNumber;
                companyName.InnerText = CompanyName;

            }

            req = WebRequest.Create(uri);
            req.Method = "POST";
            req.ContentType = "text/xml";

            writer = new StreamWriter(req.GetRequestStream());
            writer.WriteLine(xmlDoc.OuterXml);
            writer.Close();

            res = req.GetResponse();

            reader = res.GetResponseStream();

            String GatewayResult = ConvertByteArrayToString(ReadFully(reader));

            xmlResult = new XmlDocument();
            xmlResult.LoadXml(GatewayResult);

            return xmlResult;

        }

Using a Custom Membership Provider in an MVC Application

I prefer to have a full control of my database objects – which is one reason why I do not want to use the data structures available by default in the ASP.Net Membership controller. In addition because the site uses WCF to provide a publicly available library I do not want to constantly transmit someone’s actual login credentials.

What I am going to do is assign a one-time key each time someone successfully logins in. This key will then allow access to the library functionality until either the session times out or the user logs out.

The application will be multi-tier.

1. SQL Server database

2. Entity Model

3. WCF Layer

4. Client Layer

For the purposes of the prototype we have an MVC Client which provides two other layers

4a. Model Layer

4b Controller

4c View.

Layers 2 – 4 are implemented by four projects within the Visual Studio Solution.

2. Entity Model (MyApp.Data.Model)

3. WCF Layer (MyApp.Data.DataAccess & MyApp.Data.Services)

4. MVC Client (MyApp.Portal)

The Database layer

Membership Database Model

Membership Database Model

Above is the Entity Model which illustrates our database that sits behind the membership provider.  The RegisteredUser contains details of the user and has the following fields;

Id Primary Key
RequestHostAddress IP Address of the workstation used when the account was first registered
RequestDate The date of Registration
Name The name of the user
EmailAddress The email address of the user – this acts as a login as well as providing a means of communicating with a user
Password The password associated with the user – this will be stored in an encrypted form

When you use the entity modeler it provides a means of generating a script to create your database. Once the diagram has been created right click on the model

The Entity Model Context Menu

Select the Generate Database from Model option. This will then show ‘Summary and Settings’ window. Click Finish and then a script to create your database will be added to your project.

Below is the code that creates my database

-- --------------------------------------------------
-- Entity Designer DDL Script for SQL Server 2005, 2008, and Azure
-- --------------------------------------------------
-- Date Created: 06/19/2010 17:39:48
-- Generated from EDMX file: C:\Users\Paul\documents\visual studio 2010\Projects\Simplicita.Portal\Simplicita.Data.Model\SimplicitaModel.edmx
-- --------------------------------------------------
SET QUOTED_IDENTIFIER OFF;
GO
USE [Simplicita];
GO
IF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');
GO
-- --------------------------------------------------
-- Dropping existing FOREIGN KEY constraints
-- --------------------------------------------------
-- --------------------------------------------------
-- Dropping existing tables
-- --------------------------------------------------
IF OBJECT_ID(N'[Users].[LoginLog]', 'U') IS NOT NULL
DROP TABLE [Users].[LoginLog];
GO
IF OBJECT_ID(N'[Users].[RegisteredUsers]', 'U') IS NOT NULL
DROP TABLE [Users].[RegisteredUsers];
GO
-- --------------------------------------------------
-- Creating all tables
-- --------------------------------------------------
-- Creating table 'LoginLogs'
CREATE TABLE [dbo].[LoginLogs] (
[SessionId] varchar(60)  NOT NULL,
[UserId] bigint  NOT NULL,
[LoginDate] datetime  NOT NULL,
[HostAddress] varchar(30)  NOT NULL
);
GO
-- Creating table 'RegisteredUsers'
CREATE TABLE [dbo].[RegisteredUsers] (
[Id] bigint IDENTITY(1,1) NOT NULL,
[RequestHostAddress] varchar(20)  NOT NULL,
[RequestDate] datetime  NOT NULL,
[Name] varchar(60)  NOT NULL,
[EmailAddress] varchar(max)  NOT NULL,
[Password] varchar(60)  NOT NULL
);
GO
-- --------------------------------------------------
-- Creating all PRIMARY KEY constraints
-- --------------------------------------------------
-- Creating primary key on [SessionId], [LoginDate] in table 'LoginLogs'
ALTER TABLE [dbo].[LoginLogs]
ADD CONSTRAINT [PK_LoginLogs]
PRIMARY KEY CLUSTERED ([SessionId], [LoginDate] ASC);
GO
-- Creating primary key on [Id] in table 'RegisteredUsers'
ALTER TABLE [dbo].[RegisteredUsers]
ADD CONSTRAINT [PK_RegisteredUsers]
PRIMARY KEY CLUSTERED ([Id] ASC);
GO
-- --------------------------------------------------
-- Creating all FOREIGN KEY constraints
-- --------------------------------------------------
-- --------------------------------------------------
-- Script has ended
-- --------------------------------------------------
-- ---------------------------------------------------- Entity Designer DDL Script for SQL Server 2005, 2008, and Azure-- ---------------------------------------------------- Date Created: 06/19/2010 17:39:48-- Generated from EDMX file: C:\Users\Paul\documents\visual studio 2010\Projects\Simplicita.Portal\Simplicita.Data.Model\SimplicitaModel.edmx-- --------------------------------------------------
SET QUOTED_IDENTIFIER OFF;GOUSE [Simplicita];GOIF SCHEMA_ID(N'dbo') IS NULL EXECUTE(N'CREATE SCHEMA [dbo]');GO
-- ---------------------------------------------------- Dropping existing FOREIGN KEY constraints-- --------------------------------------------------

-- ---------------------------------------------------- Dropping existing tables-- --------------------------------------------------
IF OBJECT_ID(N'[Users].[LoginLog]', 'U') IS NOT NULL    DROP TABLE [Users].[LoginLog];GOIF OBJECT_ID(N'[Users].[RegisteredUsers]', 'U') IS NOT NULL    DROP TABLE [Users].[RegisteredUsers];GO
-- ---------------------------------------------------- Creating all tables-- --------------------------------------------------
-- Creating table 'LoginLogs'CREATE TABLE [dbo].[LoginLogs] (    [SessionId] varchar(60)  NOT NULL,    [UserId] bigint  NOT NULL,    [LoginDate] datetime  NOT NULL,    [HostAddress] varchar(30)  NOT NULL);GO
-- Creating table 'RegisteredUsers'CREATE TABLE [dbo].[RegisteredUsers] (    [Id] bigint IDENTITY(1,1) NOT NULL,    [RequestHostAddress] varchar(20)  NOT NULL,    [RequestDate] datetime  NOT NULL,    [Name] varchar(60)  NOT NULL,    [EmailAddress] varchar(max)  NOT NULL,    [Password] varchar(60)  NOT NULL);GO
-- ---------------------------------------------------- Creating all PRIMARY KEY constraints-- --------------------------------------------------
-- Creating primary key on [SessionId], [LoginDate] in table 'LoginLogs'ALTER TABLE [dbo].[LoginLogs]ADD CONSTRAINT [PK_LoginLogs]    PRIMARY KEY CLUSTERED ([SessionId], [LoginDate] ASC);GO
-- Creating primary key on [Id] in table 'RegisteredUsers'ALTER TABLE [dbo].[RegisteredUsers]ADD CONSTRAINT [PK_RegisteredUsers]    PRIMARY KEY CLUSTERED ([Id] ASC);GO
-- ---------------------------------------------------- Creating all FOREIGN KEY constraints-- --------------------------------------------------
-- ---------------------------------------------------- Script has ended-- --------------------------------------------------

Stored Procedures

All my database manipulation occurs behind stored procedures; the script above which is created by the data modeler concerns itself only with objects – it does not create the stored procedures; For the Membership Provider we have two procedures; one for Registering the user, and one for validating their login when they logon.

The Registration Stored Procedure is as follows;

/****** Object:  StoredProcedure [Users].[RegisterUser]    Script Date: 06/19/2010 18:17:52 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER Procedure [Users].[RegisterUser]
	@RequestHostAddress	VarChar(20),
	@Name VarChar(60),
	@EmailAddress VarChar(MAX),
	@Password VarChar(60)
As
	Declare @LastRec BigInt

	Insert Into Users.RegisteredUsers
                (RequestHostAddress, RequestDate, Name, EmailAddress, Password)
	Values		(@RequestHostAddress, GETDATE(),@Name,@EmailAddress,@Password)

	Set @LastRec = SCOPE_IDENTITY()

	Select		Id,
			RequestHostAddress,
			RequestDate,
			Name,
			EmailAddress,
			Password
	From            Users.RegisteredUsers
	Where		Id = @LastRec

It is fairly simple – the details provided by the user, plus their current IP Address and the date are inserted into the database. The record added is then returned to the calling application. This is in part due to a weakness in the Entity Model used with .Net 3.5 that only seems to execute stored procedures if an entity is returned. I’m not sure why this was the case, but the functionality is much improved under .Net 4 which not only allows stored procedures which return nothing, but also complex types which are not the same as existing database.

The Login is a little more complex

/****** Object:  StoredProcedure [Users].[Login]    Script Date: 06/19/2010 18:24:01 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER Procedure [Users].[Login]
	@Email	VarChar(MAX),
	@Password VarChar(60),
	@SessionId VarChar(60),
	@HostAddress VarChar(30)
As
Begin

	Declare @UserId BigInt
	Declare @LogId BigInt

	Set NoCount On;

	If Exists(Select * From Users.RegisteredUsers As RU Where (EmailAddress = @Email) AND (Password = @Password))
	Begin
		Set @UserId = (Select Id From Users.RegisteredUsers Where (EmailAddress = @Email) And (Password = @Password))

		INSERT INTO Users.LoginLog
                    (SessionId, UserId, LoginDate, HostAddress)
		VALUES      (@SessionId,@UserId, GETDATE(),@HostAddress)	

	End 

	Select	SessionId,
			UserId,
			LoginDate,
			HostAddress
	From Users.LoginLog
	Where SessionId = @SessionId
END

Basically we first look for a record that matches the logon criteria given by the user – note: passwords are stored encrypted, this procedure expects an encrypted password and checks this against the database. This is done in part to prevent someone from knowing a users password if they gain access to the database. Also if someone does sniff the line to get the login details they are only transmitted once and not unencrypted.

If the record exists then an entry is inserted into LoginLog – this will be used later in the project when accessing a users data. Basically when they SessionId is passed this is checked against this table and hence to link to the users data. When we want to signoff this entry is flagged so it will not be picked up again.

This model has the added advantage that we now have a record of when a user logs in, where they logged in from and when.

Setting up the Data Model to use the Stored Procedures

Select the Data Model in your project and view the Model Browser.

Taking each Stored Procedure in turn

1. Right click and select ‘Add Function Import’

2.

Add Function Import

Add Function Import

Select the Entities option and pick the relevent entity from the pulldown.

3. Click on the Get Column Information and then  click OK.

That now sets up our Stored Procedures up and completes the database setup. Now it is time to move to the WCF Layer

The WCF Layer

There are a couple of references we need to set up. Right click on Web Service Project and select Add Reference

Add Reference

Add Reference

From the .Net Libraries select the System.Data.Entities library – this is needed by projects which themselves access a separate library with an Entity Model in it. From the Projects Library select the MyApp.Data.AccessObjects and the MyApp.Data.Model projects.

That is the references set-up.

Now we need to copy the database connection string from the Entity project to the Web Service. This can be found in the App.Config

<add name="MyEntities" connectionString="metadata=res://*/MyModel.csdl|res://*/MyModel.ssdl|res://*/MyModel.msl;provider=System.Data.SqlClient;provider connection string=&quot;Data Source=MYSERVER\SQLEXPRESS;Initial Catalog=Simplicita;Integrated Security=True;MultipleActiveResultSets=True&quot;" providerName="System.Data.EntityClient" />

This needs to be copied to the Web.Config of the Web Service.

Well that is the setting up. Now we need to create the objects that will be sent back from the Webservice. These need to be setup so that they will be serialised when sent over the internet.

I’ve created two objects for the Membership Provider (so far – I reserve the right to create loads more)

User.cs – The User Data Access Object

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace MyApp.Data.AccessObjects.UserAccount
{
    [DataContract]
    public class User
    {
        [DataMember]
        public String Name { get; set; }

        [DataMember]
        public String Email { get; set; }

        [DataMember]
        public String Password { get; set; }

        [DataMember]
        public String CurrentSessionId { get; set; }

        [DataMember]
        public String HostAddress { get; set; }

    }
}

We use the DataContract and the DataMember Attributes so that the WCF class can serialize the object. These attributes are defined in the System.Runtime.Serialization namespace and there is a using command for this at the top of the class.

Really nifty tip

If you are anything like me then you can never remember what namespace any given object or class is in. However in VS 2010 there is a really nifty little facility which tells you what namespace, and even inserts it into the code for you!. Right click on the class or object. Select ‘Resolve’ from the context menu and then  select the required namespace.

Why create seperate objects?

Now of course the Data Entity Library creates it’s own classes, but these are tied very closely to the structure of the database. This is something we do not want, since changes in the database will be reflected within other layers. By creating these data access objects we also create an extra layer of abstraction between the database and the middle tier. We create them in a seperate project so that they can be used (if ever required) without having to create a reference to the Web Service.

LoginEntry.cs – the Login results

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;

namespace Simplicita.Data.AccessObjects.UserAccount
{
    [DataContract]
    public class LoginEntry
    {
        [DataMember]
        public String SessionId { get; set; }

        [DataMember]
        public long UserId { get; set; }

        [DataMember]
        public DateTime LoginDate { get; set; }

        [DataMember]
        public String HostAddress { get; set; }
    }
}

The Login entry returns the results of the login. This will be a duplicate the entry placed in the Login Log created in the database.

Finally to the WebService

OK, so the objects have been created, references set up – now is the time to write the service which will log our user on. Because the interface will be available over the wen I am seperating each service into smaller chunks. So for the Membership Provider we have a UserAccount Service.

A webservice exposes it’s messages via an interface. So the first thing to do is implement the interface. For this article I am concentrating on the actual login process. So this interface would need to implement other parts such as the registration, password reminder and all that. So this only shows the Login Process or ValidateAccount;

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using MyApp.Data.AccessObjects.UserAccount;

namespace MyApp.Data.Services
{
    [ServiceContract]
    public interface IUserAccount
    {
        [OperationContract]
        String ValidateAccount(String UserName, String Password); 

    }
}
The interface is given the ServiceContract attribute since this is the contract between the service and the client. Each Operation then has it’s own Contract. The attribute is available from the System.ServiceModel attribute. We also refer to the Data.AccessObjects.UserAccount namespace which contains the Data Access Objects. The UserAccount namespace is created because I created a folder called UserAccount in the project. Visual Studio then adds the Folder name to the namespace – it is a good way of organising a project, not least because it separates objects and allows us to use the same object name more than once.
The Service itself is where it gets interesting;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using Simplicita.Data.AccessObjects.UserAccount;
using Simplicita.Data.Model;
using System.ServiceModel.Channels;
using System.Security.Cryptography;

namespace Simplicita.Data.Services
{
    public class UserAccount : IUserAccount
    {
        private const string ENCRYPTION_KEY = "MyKey";

        private String GetIPAddress()
        {
            OperationContext context = OperationContext.Current;
            MessageProperties prop = context.IncomingMessageProperties;
            RemoteEndpointMessageProperty endpoint = prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            string ip = endpoint.Address;

            return ip;

        }

        private string EncryptString(string Message, string Passphrase)
        {
            byte[] Results;
            System.Text.UTF8Encoding UTF8 = new System.Text.UTF8Encoding();

            // Step 1. We hash the passphrase using MD5
            // We use the MD5 hash generator as the result is a 128 bit byte array
            // which is a valid length for the TripleDES encoder we use below

            MD5CryptoServiceProvider HashProvider = new MD5CryptoServiceProvider();
            byte[] TDESKey = HashProvider.ComputeHash(UTF8.GetBytes(Passphrase));

            // Step 2. Create a new TripleDESCryptoServiceProvider object
            TripleDESCryptoServiceProvider TDESAlgorithm = new TripleDESCryptoServiceProvider();

            // Step 3. Setup the encoder
            TDESAlgorithm.Key = TDESKey;
            TDESAlgorithm.Mode = CipherMode.ECB;
            TDESAlgorithm.Padding = PaddingMode.PKCS7;

            // Step 4. Convert the input string to a byte[]
            byte[] DataToEncrypt = UTF8.GetBytes(Message);

            // Step 5. Attempt to encrypt the string
            try
            {
                ICryptoTransform Encryptor = TDESAlgorithm.CreateEncryptor();
                Results = Encryptor.TransformFinalBlock(DataToEncrypt, 0, DataToEncrypt.Length);
            }
            finally
            {
                // Clear the TripleDes and Hashprovider services of any sensitive information
                TDESAlgorithm.Clear();
                HashProvider.Clear();
            }

            // Step 6. Return the encrypted string as a base64 encoded string
            return Convert.ToBase64String(Results);
        }

        public String ValidateAccount(string UserName, string Password)
        {
            MyAppEntities       ctx                 = null;
            LoginEntry          LoginResult         = null;
            Guid                SessionId           = Guid.NewGuid();
            String              sSessionId          = String.Empty;
            String              encryptedPassword   = String.Empty;
            String              result              = String.Empty;

            try
            {
                sSessionId = SessionId.ToString();
                encryptedPassword = EncryptString(Password, ENCRYPTION_KEY);

                ctx = new SimplicitaEntities();

                LoginResult = (LoginEntry)((from r in ctx.Login(UserName, encryptedPassword, sSessionId, GetIPAddress())
                                       select new LoginEntry {
                                           SessionId = r.SessionId,
                                           UserId = r.UserId,
                                           LoginDate = r.LoginDate,
                                           HostAddress = r.HostAddress
                                       }).First());

                if (LoginResult != null)
                {
                    result = LoginResult.SessionId;
                }

            }
            catch (System.Exception ex)
            {
                result = String.Empty;
            }

            return result;
        }
    }
}

The first function (GetIPAddress) gets the IP address – this is part of the security setup. Basically it records the IP address that a login attempt comes from, and allows tracking logins. Next a function to encrypt the password. I’m not interested in de-encrypting the password  – if we always encrypt the password then they are not stored in the clear. I do question where the encryption should be. This design means the password is passed to the service in the clear. All very well. The reason it is not done by the calling client is because it leaves the encryption (except the ‘millions’ who read this – I can live in hope 😉 ) behind the service. As any developer will be able to use the service, if the encryption was in the client I would have to give the encryption process to any calling developer.

These are both private and do not need to be exposed to the wider internet – they are helper functions for the last function – ValidateAccount.

First off we set the sessionId – this is a GUID. We put it here, because we do not want anyone to spoof the site, by calling with a GUID. This GUID is returned by the function which the user will subsequently use in the header of messages to achieve the results they want, or get their data.

Next we encrypt the password, calling our helper function to do so.

The ctx holds an instance of our Database entity. We use this to call our Stored Procedure we created earlier. I’ll split this line up from the inside to the outside;

select new LoginEntry {
                           SessionId = r.SessionId,
                           UserId = r.UserId,
                           LoginDate = r.LoginDate,
                           HostAddress = r.HostAddress
                      }).First()

Here is a LINQ query which creates an instance of the LoginEntry class – this was the Data Access Object we created earlier. We want the First instance. The function returns only two possible number of records. Zero for an invalid login and 1 if it is valid.

(LoginEntry)((from r in ctx.Login(UserName, encryptedPassword, sSessionId, GetIPAddress())
                                       select new LoginEntry {
                                           SessionId = r.SessionId,
                                           UserId = r.UserId,
                                           LoginDate = r.LoginDate,
                                           HostAddress = r.HostAddress
                                       }).First());

Here we cast the result to an instance of the LoginEntry object. If there is no entry this causes an exception. When an exception is thrown the result is set to an empty string. If there is a row then the login was successful and the result is set to the SessionId and returned to the calling application.

The MVC Client.

So we now have a service, which makes a call to a database – validates the login criteria and returns a SessionId to identify the user in subsequent calls to the service. Now it comes time to create the MVC Client which will call this service.
I used the empty MVC Service – this meant the new client did not create a MembershipProvider. On the downside it also does not create a MasterPage. This is out of scope for this article, but creating the MasterPage is not that difficult.
MVC stands for Model, View Controller and in line with the rest of this entry I am moving from the back to the front – which means the first thing is the ‘Model’, but before then we need to set up a service reference to the WCF service. I covered how to do this in an earlier article here;

https://developingmycloudapp.wordpress.com/2010/06/19/connecting-a-wcf-service-to-an-model-view-controller-client/

The Model

To implement a Custom Membership Provider you inherit from the MembershipProvider. This has a number of abstract methods which implement all the functionality required to manage the Membership of the site. Once the class has been created right click on the class name and select the implement abstract class. This will create stub entries for every method that needs to be implemented. You don’t need to write all of them, just ensure the stubs are there. For this article I am only concentrating one one method – the ValidateUser one – and here we are going to see why layering an application and doing all this work provides dividends.
        public override bool ValidateUser(string username, string password)
        {
            UserAccountClient ctx = null;

            try
            {
                ctx = new UserAccountClient();
                SessionId = ctx.ValidateAccount(username, password);

            }
            catch
            {
                return false;
            }
            return !String.IsNullOrEmpty(this.SessionId);
        }

The main body of this is actually only one line – when we create a reference to a webservice it creates a proxy class which handles all the messy communication between the service and the client. We just call the method created in that proxy class. The actual body of this function is just one line. The rest is just initializing the various instances.

There is however one other function used here, which was not created when we implemented the required Abstract Class methods. The SessionId will hold the session id created by the call to the login service. This function is below;

public String SessionId { get; set; }

That’s it – a whole method in one line of C#. This takes advantage of a facility that was introduced into C# 3. Basically instead of all that tedious mucking about creating fields and then the property, C# sharp can do it for us. This is then available to the next stage up to get the SessionId

‘C’ is for Controller

Nearly at the home stretch now, and time to implement the controller.

    public class AccountController : Controller
    {

        MyMembershipProvider provider = (MyMembershipProvider)Membership.Provider;
        .
     }

Above is the stub of a controller. All Controllers inherit from the Controller class. We also have a class wide instance of our provider.

        public ActionResult Logon()
        {

            return View();
        }

        [AcceptVerbs(HttpVerbs.Post)]
        public ActionResult Logon(string username, string password, string returnUrl)
        {
            if (!ValidateLogin(username, password))
            {

                return View();
            }

            FormsAuthentication.SetAuthCookie(provider.SessionId, false);

            if (String.IsNullOrEmpty(returnUrl))
                return Redirect(returnUrl);
            else
                // TODO: Set the redirect to the company list when we are ready
                return RedirectToAction("Index","Home");
        }

Each model has a verb and this implements one such verb – this is the logon verb and will be called when ever a user has to login to the application. It consists of two functions; one when the user goes to the login page, the other when they have given their login criteria and it needs validating.

When a user is validating this action verb makes a reference to the ValidateLogin function

        private bool ValidateLogin(string UserName, string Password)
        {
            if (String.IsNullOrEmpty(UserName))
            {
                ModelState.AddModelError("UserName","You must provide a User Name");
            }

            if (String.IsNullOrEmpty(Password))
            {
                ModelState.AddModelError("Password", "You must provide a Password");
            }

            if (!provider.ValidateUser(UserName, Password))
            {
                ModelState.AddModelError("_FORM", "Unknown username and/or password");
            }

            return ModelState.IsValid;
        }

Basically this validates the inputs and finally makes a call to the ValidateUser method of the provider we created earlier. Back to Post version of our Action Verb if the input is valid and we recognise the user then we use a call to the SetAuthCookie method of the FormsAuthentication static class – which sets the authentication cookie that can be used to later identify the user.

‘V’ is for View

Last 20o yrds now – and how the user is going to implement the interface that the user sees when they use the application. Right click on the first function (Login) and select AddView

Add View Window

Add View Window

We don’t need to create a strongly viewed type so we can just click ‘OK and this will create our client page.

This will create a web page – with two asp:Content controls; The first is the title content, the next is the body where we put the following code;

    <h2>Logon</h2>
    <% using (Html.BeginForm())
    { %>
    <table>
        <tr>
            <td><asp:Label ID="Label1" runat="server" Text="Username:" CssClass="FormLabel"></asp:Label></td>
            <td><%= Html.TextBox("username", null, new { @class = "userbox" })%></td>
        </tr>
        <tr>
            <td>
                <asp:Label ID="Label2" runat="server" Text="Password:"></asp:Label></td>
            <td><%= Html.TextBox("password", null, new { @class = "input-box" })%></td>
        </tr>
        <tr>
            <td><input class="button" name="Login" type="submit" value="Login" /></td>
            <td align="right" valign="bottom" />
        </tr>
    </table>
<% }  %>

This creates two labels and two fields to take our Username and Password plus a button. The Page looks something like this (depends on your site master)

Login Page

Wiring up Forms Authentication

That is most of the code, and now we are down to the last 100 yrds. The Provider has been written, the login screen created but the site is still not secure. Remaining is to wire up the Web.config of the client site to tell it which pages anyone can visit – and which ones will force a visit to the login page.

The wiring up occurs in the <system.web> tag of the web.config.

First off alter the <authentication> tag so that mode is set to “Forms”, and in the <forms> tag has the login url set to your login page. It should look something like this.

    <authentication mode="Forms">
      <forms loginUrl="~/Account/Logon" timeout="2880" />
    </authentication>

Following this we then block access to all pages in the website with an authorization, before granting access to just those we want to make public.

	  <authorization>
		  <deny users="?"/>
	  </authorization>

Now we need to tell it not to use the default membership provider, but to use our own provider. Just below the authorization tag place the following;

   <membership defaultProvider="SimplicitaMembershipProvider">
      <providers>
        <clear/>
		  <add name="SimplicitaMembershipProvider" type="Simplicita.Portal.Models.SimplicitaMembershipProvider, Simplicita.Portal"/>
      </providers>
    </membership>

Now when the application is run – it will start with the login page – however it will look terrible because amongst those things that were blocked by the authentication was the CSS and images folders where all the CSS and images for the site are kept – to grant access to these folders we now need to revoke the authentication block, for these areas only.

Just after the <system.web> tag place the following

	<location path="Content">
		<system.web>
			<authorization>
				<allow users="*" />
			</authorization>
		</system.web>
	</location>

	<location path="Content/images">
		<system.web>
			<authorization>
				<allow users="*" />
			</authorization>
		</system.web>
	</location>
	<location path="Content/Helpers">
		<system.web>
			<authorization>
				<allow users="*" />
			</authorization>
		</system.web>
	</location>

So that’s it – a secure MVC site, that uses our own Membership Provider.

Connecting a WCF Service to an Model View Controller Client

Although MVC goes someway to separating the database layer, the business rules layer and the presentation layer – I need the first two to be available to a variety of client types (smartphone, slate, Desktop, Silverlight, Adobe Air) – As I am working on a prototype, using an MVC client that means connecting it to the WCF library.

Anyway I have written the Membership Provider and attempted to connect it to the WCF library.

1. Right click on the MVC Client Application

2. Select ‘Add Service Reference’

3. click on the ‘Discover’ button

4. Select the Service you want to connect (mine was called UserAccount.svc)

5. Change the namespace to something a little more descriptive than the default ‘ServiceReference1’

6. Click on the ‘OK’ button.

And this is where the problem started – I got the following error

The configuration for the service reference could not be added due to the following issue: An error occured creating the configuration handler for the system.serviceModel/behaviours: Extension element ‘enableWebScript’ cannot be added to this element. Verify that the extension is registered in the extension collection at system.serviceModel/extensions/behaviourExtensions. Parameter Nme: element (C:\Users\…..\web.config line 213)

Looking in the web.config I can see the following has been added

<behaviors>
   <endpointBehaviors>
     <behavior name="Simplicita.Portal.Models.AccountModelsAspNetAjaxBehavior">
     <enableWebScript />
     </behavior>
   </endpointBehaviors>
</behaviors>

The problem seems to lie in the <enableWebScript> tag.

Basically you need to comment out the behaviour containing the enableWebScript Tag and try adding the service reference again, then remove the comment around the behaviour.  Not sure if this is a bug – it is a pain in the gluteus maximus. However once I did this then tried to add the service reference then it worked successfully. Once the service is added then remove the comment around the behaviour that was added earlier and the job is done.

The following is the ServiceModel tag from my client web.config once I had done the above;

 <system.serviceModel>
    <bindings>
      <basicHttpBinding>
        <binding name="BasicHttpBinding_IUserAccount" closeTimeout="00:01:00"
          openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
          allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard"
          maxBufferSize="65536" maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
          messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered"
          useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="8192" maxArrayLength="16384"
            maxBytesPerRead="4096" maxNameTableCharCount="16384" />
          <security mode="None">
            <transport clientCredentialType="None" proxyCredentialType="None"
              realm="" />
            <message clientCredentialType="UserName" algorithmSuite="Default" />
          </security>
        </binding>
      </basicHttpBinding>
    </bindings>
    <client>
      <endpoint address="http://localhost:49333/UserAccount.svc" binding="basicHttpBinding"
        bindingConfiguration="BasicHttpBinding_IUserAccount" contract="UserService.IUserAccount"
        name="BasicHttpBinding_IUserAccount" />
    </client>
    <behaviors>
      <endpointBehaviors>
         <behavior name="Simplicita.Portal.Models.AccountModelsAspNetAjaxBehavior">
          <enableWebScript />
        </behavior>
      </endpointBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" />
    <services>
      <service name="Simplicita.Portal.Models.AccountModels">
        <endpoint address="" behaviorConfiguration="Simplicita.Portal.Models.AccountModelsAspNetAjaxBehavior"
          binding="webHttpBinding" contract="Simplicita.Portal.Models.AccountModels" />
      </service>
    </services>
  </system.serviceModel>

Credit due to Ladislav Mrnka who gave me this solution on the MSDN forums.

Using queues in Microsoft Azure for a scalable application

Any website will start with a handful of users and grow (hopefully) to many thousands. Azure allows you to control the amount of server resources your application will use, and hence the cost of hosting – with low use at the start and growing as the site requirements change.

One aspect that needs to work harder is in writing to your database. Your database access code needs to react to varying levels of usage. By using a combination of Azures queue storage and worker roles we can increase or decrease the resources allocated to database writes depending on demand.

Essentially what we need to do is pipe all database access requests through a queue and let the worker role do the actual database writes.

Initialising the queue storage.

To setup queue storage we need to set the configuration within the Azure startup solution. Expand the Startup project of your solution and look for two files;

ServiceConfiguration.csdef
ServiceConfiguration.cscfg

Starting with the csdef file open it in Visual Studio and look for the ConfigurationSettings tag

    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" />
      <Setting name="MessageConnectionString" />
    </ConfigurationSettings>

The above tag shows two setup. There needs to be one each for the Roles(s) in your Azure application. These entries are then echoed in the .cscfgfile

    <ConfigurationSettings>
      <Setting name="DiagnosticsConnectionString" value="UseDevelopmentStorage=true" />
      <Setting name="MessageConnectionString" value="UseDevelopmentStorage=true" />
    </ConfigurationSettings>

For the moment I am using Development storage so this is what the current settings point to. So that is the storage setup.

The base Messaging Object

All the objects I am going to write to the database are based on a single object that implements IDisposable.

 public class MessagingObject : IMessagingObject,IDisposable
    {
        public string IP
        {
            get;
            set;
        }

        public MessageAction Action
        {
            get;
            set;
        }

        public void Dispose()
        {
            IP = String.Empty;
        }

Going quickly through the object. First off it inherits from IDisposable. Apart from the obvious benefits of disposing of objects properly. It also allows us to use the following construct when using any of our MessageObjects.

            using (MyObject myInstance = new MyObject())
            {
            }

The MessageObject only exists between the curly Brackets and is disposed of by the .Net Namespace.

As part of the security of the application I am going to record the IP address. This can be found by running the following code;

            OperationContext context = OperationContext.Current;
            MessageProperties prop = context.IncomingMessageProperties;
            RemoteEndpointMessageProperty endpoint = prop[RemoteEndpointMessageProperty.Name] as RemoteEndpointMessageProperty;
            string ip = endpoint.Address;

Next we have the action. This is how we are going to tell the worker role what we want done with the object. I’ve used an enumerated type – which may grow in the future

public enum MessageAction
{
        Create,
        Write
}

At the bottom is a Dispose.

Finally – this object implements an IMessageObject which forces the provision of these base elements.

    public interface IMessagingObject
    {
        String IP { get; set; }
        MessageAction Action { get; set; }
    }

Posting our objects to the queue.

Queue storage requires that the objects are text – so we now need to convert our objects to a string representation. As it happens there is a way of converting objects to a string built into the .Net Serialization Namespace. To use this ensure your create a reference in your project to the System.Runtime.Serialization namespace and place a using statement at the top of your module;

using System.Xml.Serialization;

We first have to initialize an object to do our serialization.

XmlSerializer serializer = new XmlSerializer(typeof(MyObject));

The XmlSerializer uses a stream to write the serialized object so we have to set those up as well.

 MemoryStream ms = new MemoryStream();
 XmlTextWriter xmlTextWriter = new XmlTextWriter(ms, Encoding.ASCII);

Serializing the object is fairly easy. We just use the Serialize method

serializer.Serialize(xmlTextWriter, myObject);

This takes the TextWriter and the object as parameters.

Next we need to connect to the queue to store the message

                var storageAccount = CloudStorageAccount.FromConfigurationSetting("MessageConnectionString");

                // retrieve a reference to the messages queue
                var queueClient = storageAccount.CreateCloudQueueClient();
                var queue = queueClient.GetQueueReference("messagequeue");

                queue.CreateIfNotExist();

So here we we have a message and a queue – now to write that message to the queue.

                var cloudMessage = new CloudQueueMessage(ms.ToArray());
                queue.AddMessage(cloudMessage);

First the MemoryStream is converted to a Byte Array and then this is pushed to the queue.

That now leaves the message on the queue – the next stage is to write the message to the database – and this is done by a worker role.

Initialising the connection to the queue to read it.

Queues are described as FIFO – First In, First Out – which is why they are good for the current activity – since we need to ensure everything is written in the same order of the request.

We first need to open a connection to the queue

            var storageAccount = CloudStorageAccount.FromConfigurationSetting("MessageConnectionString");

            // retrieve a reference to the messages queue
            var queueClient = storageAccount.CreateCloudQueueClient();
            var queue = queueClient.GetQueueReference("messagequeue");

Reading entries from the queue.

A worker role just sits in the background – goes to sleep for a pre-determined period and then wakes up to do it’s task – in this instance read the queue.

First activity is to get the message at the front of the queue.

 var msg = queue.GetMessage();

Now this code is going to have to work for any type of object we throw at it – so we need a way of telling what kind of object it is – so we can then later initialise the correct deserialization object.

                        sMsg    = msg.AsString;
                        doc     = new System.Xml.XmlDocument();

                        doc.LoadXml(sMsg);
                        ms = new MemoryStream(encoder.GetBytes(sMsg));

                        documentElement = doc.DocumentElement.Name;

All this code is doing is reading the message into an XML document and then reading the first element – this will be the type of the object.

Once we have done this a simple switch statement can then be used to select the correct deserialization.

switch (documentElement.ToLower())
                        {
                            case "user":
                                serializer = new XmlSerializer(typeof(MyObject));
                                MessageMarshaller.Execute((MyObject)serializer.Deserialize(ms));
                                break;   

                            default:
                                serializer = new XmlSerializer(typeof(Object));
                                break;
                        }

The real magic here is the use of Overloading to select the correct MessageMarshaller. .Net does all the hard work of selecting the correct one for us. The Deserializer method returns an object and we cast it to the correct type. Now all the MessageMarshaller does is use the MessageAction to select the correct action.

A version of the Marshaller is then created for all objects in our database.

A few things to tidy up.

There is a few things missing from this. The most important is error handling. If a message is not decoded and then subsequently written to the database that must be handled. In this instance Messages should be written to a quarantine table and a function written to write them manually to the database.

How this helps in scalability.

There can be any number of a particular role running in an application and this is how the scalability works. By careful analysis of the queue size we can see how many copies should be running and increase, or decrease the number as required. Since the more you have, the higher the cost, and the fewer you have, the higher the response times – a careful balance needs to be maintained between cost and response.

Sending a confirmation email after registration

My site will send a confirmation email once a user has registered with it. So once the user has registered they will get a nice colourful email showing them their login details;

Within C# the ability to send an email is contained within the System.Net.Mail namespace. I first off created a new class called Postman to encapsulate the code sending the email.

This will have the following properties

public string To { get; set; }
public string From { get; set; }
public string Body { get; set; }
public string Host { get; set; }
public string Subject { get; set; }
public string Token { get; set; }
public Boolean IsBodyHtml { get; set; }

to do this I have taken advantage of C#’s ability to generate field variables automatically- this greatly reduces the amount of code I need to create properties. Of course if I really need to do validation and the lot I could always use a more traditional property definition.

The Email sending functionality is almost all set in a method called Send(). First off we have to create a message object, and an SmtpClient object.

client = new SmtpClient(host: Host);
to = new MailAddress(address: To);
from = new MailAddress(address: From);
msg = new MailMessage(from: From, to: To);

I have also set the address the email is from and to. Next we set the form of the email.

msg.IsBodyHtml = true

then the body of the email

msg.Body = Body;

msg.BodyEncoding = System.Text.Encoding.UTF8;

and it’s subject

msg.Subject = Subject;

msg.SubjectEncoding = System.Text.Encoding.UTF8;

Now because this is being sent from a web service I want to send the email asynchronously. In this way the user is not held up while we are doing the actual send.

This requires that we set up an event handler to execute when the email is sent – at the moment this function does little;

client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted);

.

.

.

void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)

{

string messageId = string.Empty;

try

{

messageId = (String)e.UserState;

}

catch

{

throw;

}

}

Now to send the email

client.SendAsync(message: msg, userToken: Token);

Below is the full code for the Postman object

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Net.Mail;

namespace Simplicita.Services.Support

{

public class Postman : IDisposable

{

public string To { get; set; }

public string From { get; set; }

public string Body { get; set; }

public string Host { get; set; }

public string Subject { get; set; }

public string Token { get; set; }

public Boolean IsBodyHtml { get; set; }

public void Send()

{

SmtpClient client = null;

MailAddress to = null;

MailAddress from = null;

MailMessage msg = null;

try

{

// validate email parameters

if (this.Host == String.Empty)

throw new Exception(“You must provide an SMTP Host”);

if (this.To == String.Empty)

throw new Exception(“You must provide an address to send the email to”);

if (this.From == String.Empty)

throw new Exception(“You must provide an address that the email is from”);

if (this.Subject == String.Empty)

throw new Exception(“You must provide a subject for the email”);

// set a token to identify this email

if ((this.Token == String.Empty) || (this.Token == null))

{

Guid tokenGuid = Guid.NewGuid();

try

{

this.Token = tokenGuid.ToString();

}

catch

{

throw;

}

}

// initialise SMTP Parameters

client = new SmtpClient(host: Host);

to = new MailAddress(address: To);

from = new MailAddress(address: From);

msg = new MailMessage(from: From, to: To);

// initialise the email parameters

msg.IsBodyHtml = true;

msg.Body = Body;

msg.BodyEncoding = System.Text.Encoding.UTF8;

msg.Subject = Subject;

msg.SubjectEncoding = System.Text.Encoding.UTF8;

// set up the Async completed property

client.SendCompleted += new SendCompletedEventHandler(client_SendCompleted);

client.SendAsync(message: msg, userToken: Token);

}

catch

{

throw;

}

}

void client_SendCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)

{

string messageId = string.Empty;

try

{

messageId = (String)e.UserState;

}

catch

{

throw;

}

}

public void Dispose()

{

}

}

}

Getting the project underway

Well it is time to start creating the application. After the problems detailed in the last post we will not currently be using the Azure Tools.

That said there are a few things we need to download.

Visual Studio 2010 (http://msdn.microsoft.com/en-us/vstudio/dd582936.aspx)

WCF RIA Services (http://silverlight.net/getstarted/riaservices/)

Install both of those.

Start Visual Studio 2010

Select File, New Project – in the list of Installed Templates to the left, select the Silverlight option. to use the WCF RIA Services DomainService template we need to make sure .Net Framework 4 is selected in the .Net Framework pulldown. If it is not selected then the WCF RIA Services Class Library is not listed and this is required later to provide the Middle and Back-end tiers of the app.

When you do this you will find a number of templates – some of which are new to Silverlight development.

  • Silverlight Application
  • Silverlight Business Application
  • Silverlight Class Application
  • Silverlight Navigation Application
  • Silverlight Unit Test Application
  • WCF RIA Services Class Library

I’m not doing to use them but the Business Appliction and Navigation Applicaton deserve some consideration. One of the latest additions is the ability to allow the user to use the Back button of the browser in Navigating the application. This is achieved by using the Navigation Application template and it provides a way of allowing different pages of an application to be created and navigated around.

The Business Application is the virtually the same but in addition to a Silverlight application it also includes a WCF RIA Services Class to provide the database backend. On the face of it this would seem the ideal candidate for my application. However my app is a single page with drag and drop functionality – I really don’t want extras in the app that are not required. For this reason I am going to create my Silverlight Application from scratch and set up the reference links between them manually.

First off is to create the Silverlight Application. Now a Silverlight Solution consists in the first instance of two projects – The Silverlight application itself and a web application to host it.

  • Select Silverlight Application template
  • In the New Silverlight Application Window there is a checkbox labelled ‘Host the Silverlight application in a new Web site’. As this is a new solution we want this checked. If you were adding this project to an existing solution you do get the option to add Silverlight to the app, but in this instance we can keep it clicked
  • The next option of interest is the Silverlight version. For Visual Studio 2010 it will default to Silverlight 4 which I want to use.
  • The Final option Enable RIA Services also needs to be checked. Now although this does not refer to WCF RIA Services – RIA Services was renamed to refer to it and in reality there are effectively the same thing.

That gets the initial project created, clicking on OK allows Visual Studio to go away and create all of the projects and links required for the application. Now it is time for the Middle and Back End Tiers.

  • Click on the Solution in the Solution Explorer,
  • Right Click and then Select Add, New Project
  • Select the WCF RIA Services Class Library
  • Give it a name
  • Then Click on OK

Again Visual Studio goes on to create the projects. When it is finished you will have a new folder which contains two projects; one ending in .Web which contains an empty class and another project.

So having created the RIA Class project you should have the a Services Library containing two folders, a Silverlight Application Project and a Web Project. Now is the time to wire up the refences between the Middle/Back Tier and the Silverlight Application.

Right Click on the Silverlight Host Website References and Select the project option. Select the WCF RIA Services Web Host

Right Click on the Silverlight Application References and Select the project option. Now select the WCF RIA Services Class.

When this is done you should have something like the following setup;

So there we have it. The project is now created, we have linked the Backend. Time to get writing some code.