Monday, 30 August 2010

Writing a windows phone 7 application with an Azure backend: part 4 (Security)

In my previous post I created a WCF service and deployed that on Azure. I did not add any security to that service at all. Basically everyone can use my service now. In the case of the example of the previous post that is not a huge problem, but if I want to put my wine management service in the cloud, I will certainly need to add security.

My first thought was to add username/password authentication. However it turned out to be more tricky than expected. The basics are pretty straightforward and this post explains how you can do this. The result however is that we need to use a secure SSL connection. So I changed the WCF configuration of my service and added an https endpoint to my cloudservice only to find out that WP7 does not connect to a server which presents a certificate which is not in the trusted root store and there is no way for the application to override this behavior or add certificates to the trusted root store.  This means I need to buy a certificate from a trusted authority and install that on Azure. The Azure FAQ has an entry on that as well: How do I get SSL certs for my Windows Azure service? The answer is that Microsoft partners with Verisign to provide SSL certifications for Windows Azure services. The cheapest certificate I could find on the Verisign site still costs $399. That’s quite expensive if you just want to build a small wp7 application and put it on the marketplace. I did not try that solution since this post would be quite expensive to write then.

There is of course a workaround for this as well, and it is explained in this post. You basically get your own domain from for example GoDaddy and use CNAME to point it to blabla.cloudapp.net. You can then buy a certificate from for example RapidSSL which only costs $79. You might even get away with a free certificate from for example StartSSL I am not sure though whether StartSSL is supported by WP7.

So, it is not that easy to secure your service hosted on Azure and still be able to call it from your WP7 application. That’s why I did some thinking on whether I would not go for another solution for my wine cellar management application. If you are a big company that needs to develop and host services for a WP7 application Windows Azure is certainly a valid choice, but if you just want to develop a small application and put it on the marketplace it is possibly another story. Windows Azure has a pay per use model which totally makes sense because it is a cloud offering. If I put an application on the WP7 marketplace I do however not have an option to offer a pay-per-use model. I can only sell the application for a certain price, which makes it difficult to predict the profitability of the application.  I think I would want to avoid having a monthly cost as much as possible. That’s why I decided to go for another approach and use an embedded database for my application, but that is something for a next post.

Wednesday, 18 August 2010

Update: Writing a windows phone 7 application with an Azure backend: part 3 (WCF services)

Update: apparently my first version of this post worked in the development fabric but did not work on Azure due to the load balancer. I updated this post so that it works both on the development fabric and on Azure.

The third post in this series will explain how to create a WCF service running on Azure that can be consumed by a WP7 client. It will focus on creating the WCF service and consuming the repository we created in the previous post. In the next post I will then have a closer look at how we can secure this service while making sure we can still use it from our WP7 application.

Creating the service

It all starts with adding a “Windows Cloud Service” to your solution.

  • Click right on the solution;
  • Choose “Add new item”;
  • Choose the “Windows Cloud Service” type

image

Click “OK”. This will give you the screen underneath.

image

  • Choose “WCF Service Web Role” in the left pane and move it to the right pane.
  • You can change the proposed name by clicking on the pencil. I find that a bit confusing but there is no other way.
  • Choose a name for your services project and click “ok”.

You can find more details on the things we just did here. You’ll notice that Visual Studio has created two new projects in your solution. The WCF Service Web Role project already contains a WCF service. Rename that service to for example “WineService”.

Now we need to make sure our service works well with the load balancer on Azure. My colleague Yves Goeleven explained me how to do that. The solution is based on one of the known issues that are posted on MSDN.

First you need to download the WCF REST starter kit from codeplex. Then you need to write a custom ServiceHostFactory.

public class VinoHostFactory : WebServiceHost2Factory
{             
    protected override ServiceHost CreateServiceHost(Type serviceType, Uri[] baseAddresses)
    {            
        var host = new VinoHost(serviceType,true, baseAddresses);            
        host.Interceptors.Add(new BaseAddressFixer());            
        return host;
    }
}

Two things to notice in the above code snippet. The custom ServiceHostFactory first creates a new ServiceHost and then adds an interceptor to that host. The detailed explanation of what this does can again be found in the MSDN article. My host looks like this:

public class VinoHost :WebServiceHost2
{
    public VinoHost(object singletonInstance, params Uri[] baseAddresses) : base(singletonInstance, baseAddresses)
    {
    }
 
    public VinoHost(Type serviceType, bool dummy, params Uri[] baseAddresses) : base(serviceType, dummy, baseAddresses)
    {
    }
 
    protected override void OnOpening()
    {            
        base.OnOpening();         
        #if DEBUG
            Description.Endpoints.Find(typeof(IWineService)).Address = new EndpointAddress("http://127.0.0.1:84/WineService.svc");
        #endif
        #if (!DEBUG)
            Description.Endpoints.Find(typeof(IWineService)).Address = new EndpointAddress("http://vino.cloudapp.net/WineService.svc");
        #endif
        Description.Endpoints.Find(typeof(IWineService)).ListenUri = this.BaseAddresses[0];
    }
}
}

and the code of the interceptor, the BaseAddressFixer is entirely copied from MSDN.

Then you should change the markup of your service so that it looks like this:

<%@ ServiceHost Service="Vino.Services.WineService" 
Factory="Vino.Services.VinoHostFactory" %>

Now that we have all of this in place, we can write the following code in the service:

[CallContextBehavior(typeof(VinoCallContext))]
public class WineService : IWineService
{
    private readonly IWineRepository _wineRepository;
 
    public WineService()
    {
        _wineRepository = new WineRepository();
    }
 
    public IEnumerable<WineData> GetAllWinesByTenant(string tenantId)
    {
        Mapper.CreateMap<Wine,WineData>();
        return Mapper.Map<IEnumerable<Wine>, IEnumerable<WineData>>(_wineRepository.GetAllWinesByTenant(tenantId));            
    }
 
    public string HelloWorld()
    {
        return "Nothing to creative. Let's just return Hello World";
    }
}

I use Automapper to map my entities to datacontracts. Automapper relies on conventions to automatically do a mapping between your entities and the datacontracts. If you respect those conventions mapping is as easy as defining the mapping source and target (Mapper.CreateMap<Wine,WineData>();) and actually mapping (Mapper.Map<Wine,WineData>(wine);) the source to the target. By using Automapper you don’t have to write that tedious mapping code anymore.

You also notice the “CallContextBehavior” attribute on top of the class. You can read about the implementation in a post from my colleague Gino Heyman. The only thing I still need to do in my application is implement my own call context to open a NHibernate session per WCF call:

public class VinoCallContext :CallContext
{
    public static readonly ISessionFactory sessionFactory = SessionFactoryBuilder.BuildSessionFactory();
 
    protected override void Initialize()
    {
        SessionScope.CurrentSession = sessionFactory.OpenSession();
    }
 
    protected override void Dispose()
    {
        SessionScope.CurrentSession.Dispose();
    }
}

Finally we need to configure the service. It is pretty standard. For now I will just use the configuration as generated by Visual Studio.

   1: <system.serviceModel>    
   2: serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
   3: diagnostics>
   4:  <messageLogging logMalformedMessages="true" logMessagesAtTransportLevel="true"/>
   5: /diagnostics>   
   6: client/>    
   7: behaviors>
   8:  <serviceBehaviors>
   9:    <behavior name="debugBehavior">
  10:      <serviceMetadata httpGetEnabled="true" />
  11:      <serviceDebug includeExceptionDetailInFaults="true" />
  12:    </behavior>       
  13:  </serviceBehaviors>
  14: /behaviors>
  15: services>
  16:  <service behaviorConfiguration="debugBehavior" name="Vino.Services.WineService">
  17:    <clear />
  18:    <endpoint binding="basicHttpBinding"
  19:      contract="Vino.Services.IWineService" />
  20:    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
  21:  </service>      
  22: /services>    
  23: ystem.serviceModel>

Notice that I am using a “basicHttpBinding” here and not a WSHttpBinding. That is because Silverlight does not have support for the WSHttpBinding and we want to be able to call this service from a WP7 application of course.  We have a working version of our service now that we can call from within a WP7 application but before putting this service in production we definitely need to think about security. At this moment our service is not secured and if we would deploy it on Azure everyone would be able to call it. Someone could easily mess with my wine cellar and that’s something I want to avoid. It turns out that the combination WCF, Windows Phone 7 and security can be quite challenging. That’s why I will cover it in a next post.

Let’s deploy the service to Azure now.

Right click on your web role for your WCF service and choose publish.

image The “Enable Intellitrace for .NET 4 roles” checkbox will only be enabled if you installed this patch.  Also notice that I deployed to production. That’s because in my service host I set the enpoint to the production URL. That’s somewhat easier for the demo because the staging URL changes with each deploy.

While waiting for my WCF service to get deployed on Azure, I created a small console application to check whether my service was working.  Just add a console application to your solution, add a service reference to the service (when it is running in the development fabric for example) and call one of the methods on your service. I added a stupid HelloWorld method to my service.

image

Monday, 16 August 2010

Writing a windows phone 7 application with an Azure backend: part 2 (data access)

In the first part of this series I gave a high level overview of the architecture of the windows phone 7 application I am writing. In this post I will discuss the data access part of the application. I will use the first version of the Azure driver for Nhibernate as a foundation. This post assumes that you have a Azure account or that you have installed the development fabric. If that is not the case, you' will need to download and install it first.

Let’s start with defining a simple entity. I will reuse my favorite entity: Wine ;-)

public class Wine
{
    public virtual string Id { get; set; }
    public virtual string TenantId { get; set; }
    public virtual string Name { get; set; }
    public virtual int Price { get; set; }
    public virtual int Rating { get; set; }
    public virtual string Region { get; set; }
    public virtual string Style { get; set; }
 
    public override bool Equals(object obj)
    {
        if (obj == null) return false;
        var candidate = obj as Wine;
        if (candidate == null) return false;
        return this.Id == candidate.Id && this.TenantId == candidate.TenantId;
    }
 
    public override int GetHashCode()
    {
        int hash = 13;
        hash = hash + (null == this.Id ? 0 : this.Id.GetHashCode());
        hash = hash + (null == this.Id ? 0 : this.TenantId.GetHashCode());
        return hash;
    }
}

and the Nhibernate mapping that goes with this entity:

<?xml version="1.0" encoding="utf-8" ?>
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2"
                   assembly="Vino.Domain"
                   namespace="Vino.Domain.Models">
  <class name="Wine" table="wines">
    <composite-id>
      <key-property name="Id" column="RowKey" />
      <key-property name="TenantId" column="PartitionKey"/>
    </composite-id>
    <property name="Price" type="System.Int32" />
    <property name="Rating" type="System.Int32" />
    <property name="Name" type="String" />
    <property name="Style" type="String" />
    <property name="Region" type="String"></property>
  </class>
</hibernate-mapping>

As Yves mentioned in his post to introduce the Nhibernate driver for Azure the identifier must be a composite key that included “RowKey” and “PartitionKey” and both of them have to be strings. It is also important to choose your partition key wisely. Tables on azure table storage are partitioned to support load balancing across storage nodes. Choose a property as partition key that groups your entitities. In my case I took the “tenant id” which means I will have a separate partition for the wines of each tenant. The remainder of the mapping and the entity itself is pretty straightforward, so let’s move on to the repository.

public class WineRepository :IWineRepository
    {
        public IEnumerable<Wine> GetAllWinesByTenant(string tenantId)
        {
            return SessionScope.CurrentSession.CreateCriteria<Wine>()
                    .Add(Restrictions.Eq("TenantId", "1"))
                    .List<Wine>();
        }
    }

The method “GetAllWinesByTenant” actually looks exactly the same as it does when you would write a method to get data out of SqlServer with NHibernate. Note however that the Azure driver for Nhibernate does not support queries without a where clause at this moment. This is by design because normally it does not make much sense to read an entire table from Azure table storage into the memory of your application. It might be added in the future though.

SessionScope is a class from the Capgemini framework. It has a CurrentSession property which gives you the current session during a WCF call. I will show you in the next post how this CurrentSession is set for each WCF call. One of the things it will certainly need is a NHibernate session factory to be able to open NHibernate sessions. You can build the NHibernate session factory as follows:

public class SessionFactoryBuilder
{
    public static ISessionFactory BuildSessionFactory()
    {
        return Fluently.Configure().Database(AzureConfiguration.TableStorage
                .ProxyFactoryFactory(typeof(ProxyFactoryFactory).AssemblyQualifiedName).ShowSql())
                .Mappings(cfg => cfg.HbmMappings.AddFromAssemblyOf<Wine>())                    
                .BuildSessionFactory();
    }
}

After this post you should be able to write some unit tests that store and retrieve data from the Azure table storage. To do that you will need an entity, a NHibernate mapping file and a configured session factory to be able to open NHibernate sessions.

In the next post I will explain how we can bring WCF in the mix and use the repositories from within a WCF service.

Thursday, 12 August 2010

Writing a windows phone 7 application: part 1

After WPC 10 I realized that there is a lot of new stuff available or coming to us at high speed. You can certainly say the cloud and windows phone 7 were hot topics at WPC. About time to discover these technologies in somewhat more depth. To do that I decided to get hands on with "Windows Azure" and "Windows Phone 7" and create an application to uses them both.

There is a lot to say about writing a windows phone 7 application that uses WCF services that run in the cloud. The idea is to write several posts on the topic. This posts serves as an introduction and will give an high level overview of the architecture of the solution and the frameworks used. In the next posts I will explain in more detail how I implemented the different layers of the architecture.

Let's start with a picture:

I guess the diagram is pretty straightforward. Everything starts with the windows phone client that calls a WCF service that is hosted on windows azure. The windows phone client will be implemented with the help of Caliburn.Micro. The WCF services layer uses the Castle WCF integration facility to create services and resolve dependencies. In case the WCF service just has to retrieve something from the domain, it calls a repository. The repository uses NHibernate with the Azure driver to access the azure table storage. The repository then returns a domain object to the WCF service after which the WCF service uses AutoMapper to map the domain object to a data contract. The data contract is then returned to the windows phone client.

In the next post I will go into more detail on the repositories.

Monday, 14 June 2010

Combining Scrum and Prince2

In my previous post I wrote a reaction on a post that discussed how to combine Scrum and Prince2. In this post I want to discuss how I feel you can combine Scrum and Prince2. In my approach Prince2 will be used as a governance framework on top of Scrum. It will not be used to drive a project, that will be the role of Scrum.

It all begins with a sprint zero. In that sprint zero several activities take place to prepare for the development sprints:

  • Creation of an initial product backlog
  • Definition of a high level agile solution architecture: the architecture will further evolve during the project.
  • Setup of the development environment
  • Writing of the project brief

A project brief is a Prince2 deliverable that describes the objectives of the project. Be having this 2-4 weeks sprint zero phase you will already have a good idea on the vision and scope of the project. By also defining the initial product backlog in this phase the scope of the project also gets very tangible.

After the sprint zero phase you start with the development sprints. They will typically take 2-4 weeks for each sprint, and the goal is to produce working software that is verified by a tester role at the end of every sprint. Prince2 does enforce the project to deliver a certain amount of deliverables and Prince2 also has a stage by stage process with control gates after each stage. How can we integrate this in Scrum.

It is actually not that difficult but you need the support of your organization. That is actually the difficult part. Now how does it work? The Prince2 deliverables that have to be produced in the project have to be put on the product backlog. Most of the Prince2 artifacts have to be delivered by the project manager for which he needs of course input of the team. This will probably result in the team delivering less working software at the end of each sprint but this does not have to be dramatic. Controlling the stages (phases) can be done by using "Releases". After a couple of sprints a formal release can be done.

That release will of course also contain Prince2 deliverables, and the release will have to be approved to be able to go to the next phase. A common pitfall here is that the approval process takes too long and the team is waiting. You can do several things to solve that. You could have the approval at the sprint review meeting which means the team can continue right way. If that is too shocking for your organization at first, give the decision makers clear deadlines for the approval and let the team continue in the mean time. Remarks from those decision makers that come in later can be put on the product backlog again. This second approach is less ideal for the team because by then they are already working on other product backlog items. Therefore you should strive for the first approach and have the approval in the sprint review meeting.

If you combine Scrum and Prince2 in this way you do not loose the Scrum agile spirit and you comply with the Prince2 practices which actually gives you a best of both worlds.