Saturday, 9 May 2009

Why-o-why is this so difficult!

This is really getting my goat today – I’ve been looking around for a week now for some way of sucking out the content of my old blog (community server 2.1, self hosted) and spitting it out into my new host (blogger.com). I want to take across all of the content, including attachments, images, posting dates and tags etc, but there is nothing out there that seems to do a particularly adequate job!

Blogging has been around for a while now, and regardless of the type of host we use, blog articles are largely all the same – they have a title, some rich text, inline images, tags, attachments and a publishing date time. How hard can it be to come up with a canonical format to easily move this content into and out of different hosts and have all the hosts support that standard.

Hard is all I can assume as it’s not been done in the years that blogging has been around, with the exception of half hearted attempts at standardisation like with BlogML, which doesn’t deliver on the objectives I’ve mentioned.

Wednesday, 4 March 2009

Using Regular Expressions to identify HTML tags

In many situations we might find ourselves looking to find specific HTML tags within a fragment in order to process them in some way. A good example would be a HTML “white list” of tags that you want to pre-process to allow through anti cross site scripting encoding.

The following regular expression will find all tags specified (highlighted red) in the input, regardless of them being start tags, end tags, self terminating tags and irrespective of the number of attributes etc.

<[/]?(P|B|I)(/>|\s/>|\s[\S|\s]*?>|>)

This will also return correct results when looking for <I> tags in that it won’t incorrectly allow <IMG> to be a positive match.

Wednesday, 21 January 2009

NHibernate and schema creation/update

A colleague of mine today enlightened me about one of the features in NHibernate that lets you completely ignore the whole issue of managing and updating database schema. You can use NH mappings to define the entire schema and let NH worry about creating the database and updating between the different versions.

Back in the day I used to build data first, designing ERDs and sprocs before writing any code, and so I was a little worried about indexing, constraints, naming foreign keys and such like, but the schema is more than capable of articulating this too.

Tying this up with Fluent NHibernate, strongly typed mapping files / auto map and you have a very powerful, quick to implement platform for domain driven data access.

Here's an article that tells you all about it better than I can;

http://blogs.hibernatingrhinos.com/nhibernate/archive/2008/04/28/create-and-update-database-schema.aspx

Saturday, 20 December 2008

Building a Silverlight RSS reader - part 2 - getting the data.

Continuing from part 1, we're now going to extend our Silverlight application to get data (available feeds and actual RSS postings) which we will shortly bind to in the UI.

One of the things we need to work around is the cross domain security in Silverlight. It doesn't allow you to send any requests to services/sites outside of the domain in which the Silverlight xap is hosted without explicit permission from the service/site you're trying to call. This permission is granted by placing a cross domain policy file on the target server, but in our case we can't guarantee that our target RSS feed servers will have one in place.

Silverlight has this restriction for a very good reason - it would be very easy to create a distributed denial of service attack using Silverlight if it was able to call any web resource directly. Imagine making a nice Silverlight app that is used by hundreds of people and putting a payload in there that cripples a target web site.

To work around this we can send a request for data back to a web service in the ASP.NET application that is hosting the Silverlight application. This is then free to send a request to the target server for the data we're looking for (thereby circumventing any DDoS attack possibility as now all requests are coming from the server).

Defining the feeds.
Before we look at that though, we'll start with the simpler task of getting a list of available feeds. For this, create a feeds.xml file within your web solution (in the root) with content similar to the following. (feel free to replace with your own feeds).

   1: <?xml version="1.0" encoding="utf-8" ?>
   2: <feeds>
   3:   
   4:   <feed id="ScottGuthrie">
   5:     <title>Scott Guthrie</title>
   6:     <url>http://weblogs.asp.net/scottgu/rss.aspx</url>
   7:   </feed>
   8:  
   9:   <feed id="Deepcode">
  10:     <title>Deepcode.co.uk</title>
  11:     <url>http://www.deepcode.co.uk/rss.aspx</url>
  12:   </feed>
  13:  
  14:   <feed id="AyendeRaihen">
  15:     <title>Ayende Raihen</title>
  16:     <url>http://feeds.feedburner.com/AyendeRahien?format=xml</url>
  17:   </feed>
  18:  
  19: </feeds>

Now that we have a list of feeds, we need to get this up to Silverlight and populate the drop down list of available feeds. We could use a web request to simply load the XML, but as we're going to be building a WCF service anyway to marshal requests out to feeds, we might as well piggy back on those contracts and have one cohesive service.

Defining the service, operation and data contracts.
Now, under normal circumstances I'd advocate the use of several namespaces to separate and re-use the contracts etc. I'd have separate assemblies for the data contracts (RSSReader.Services.Contracts) another to define the "specification" of the services, or in other words, the operation contracts (RSSReader.Services.Spec) and another for the service itself. (RSSReader.Services). As you can't re-use assemblies in Silverlight though, this seems a little pointless for this particular exercise so we're just going to go with a single assembly - RSSReader.Services.

Let's go ahead and create this "class library" now. Right click the solution and select Add new project and select C# class library. Delete the automatically generated class1.cs file.

Add references to System.Runtime.Serialization and System.ServiceModel. These references allow WCF constructs to be used within your application;

image

image And finally, create 3 directories within the new project - Contracts, Repositories and Spec. In contracts we will define the classes that will be used to represent the data being sent between Silverlight and our service, in Spec we'll define the operational contracts - the methods we can call on our service and in repositories we'll add the data access code to get data from sources.

 

We now want to define what data we're going to expect to receive from Silverlight and what data we're going to send back to it. We're going to have two operations on our service - a method to get a list of all available RSS feeds, and a method to get the postings within a selected feed.

For the method to get a list of feeds, we won't have any data passed in, but we want to pass back out a list of feeds. We'll wrap the list of feeds into a response object in case we need to add anything new later. As such we'll have the following classes for querying what feeds we can select;

image

Notice the use of the DTO suffix. This stands for Data Transfer Object and is standard terminology when talking about what data will be exchanged between services. See the enterprise stack posting for more information about this.

When we request feed articles, we need to tell the service which feed we want to get articles for, and have it return the articles in a list, again wrapped in a response object should we need to expand it later. This gives us these classes;

image

These contracts are all just plain old CLR objects (POCOs), onto which we add WCF specific attributes to tell the service that the class is a data contract and what members should be serialised and sent over the wire. We do this using the DataContract and DataMember attribute. The code for GetFeedRequestDTO is shown below;

   1: using System.Runtime.Serialization;
   2: using System.Collections.Generic;
   3:  
   4: namespace RSSReader.Services.Contracts
   5: {
   6:     [DataContract]
   7:     public class GetAvailableFeedsResponseDTO
   8:     {
   9:         private readonly IList<RSSFeedDTO> _feeds 
  10:             = new List<RSSFeedDTO>();
  11:  
  12:         [DataMember]
  13:         public IList<RSSFeedDTO> Feeds
  14:         {
  15:             get 
  16:             {
  17:                 return _feeds;
  18:             }
  19:         }
  20:     }
  21: }

As you can see, we've marked the class as being a data contract and the Feeds property as being a data member.

The entire listing for the various contracts is shown below;

   1: /***** GetAvailableFeedsResponseDTO.cs *****/
   2: using System.Runtime.Serialization;
   3: using System.Collections.Generic;
   4:  
   5: namespace RSSReader.Services.Contracts
   6: {
   7:     [DataContract]
   8:     public class GetAvailableFeedsResponseDTO
   9:     {
  10:         private readonly IList<RSSFeedDTO> _feeds = new List<RSSFeedDTO>();
  11:  
  12:         [DataMember]
  13:         public IList<RSSFeedDTO> Feeds
  14:         {
  15:             get 
  16:             {
  17:                 return _feeds;
  18:             }
  19:         }
  20:     }
  21: }
  22:  
  23: /***** RSSFeedDTO.cs *****/
  24: using System.Runtime.Serialization;
  25:  
  26: namespace RSSReader.Services.Contracts
  27: {
  28:     [DataContract]
  29:     public class RSSFeedDTO
  30:     {
  31:         [DataMember]
  32:         public string Id { get; set; }
  33:  
  34:         [DataMember]
  35:         public string Title { get; set; }
  36:  
  37:         [DataMember]
  38:         public string FeedUrl { get; set; }
  39:     }
  40: }
  41:  
  42: /***** GetFeedRequestDTO.cs *****/
  43: using System.Runtime.Serialization;
  44:  
  45: namespace RSSReader.Services.Contracts
  46: {
  47:     [DataContract]
  48:     public class GetFeedRequestDTO
  49:     {
  50:         [DataMember]
  51:         public string FeedId { get; set; }
  52:     }
  53: }
  54:  
  55: /***** GetFeedResponseDTO.cs *****/
  56: using System.Runtime.Serialization;
  57: using System.Collections.Generic;
  58:  
  59: namespace RSSReader.Services.Contracts
  60: {
  61:     [DataContract]
  62:     public class GetFeedResponseDTO
  63:     {
  64:         private readonly IList<FeedArticleDTO> _articles 
  65:             = new List<FeedArticleDTO>();
  66:  
  67:         [DataMember]
  68:         public IList<FeedArticleDTO> Articles
  69:         {
  70:             get 
  71:             {
  72:                 return _articles;
  73:             }
  74:         }
  75:     }
  76: }
  77:  
  78: /***** FeedArticleDTO.cs *****/
  79: using System;
  80: using System.Runtime.Serialization;
  81:  
  82: namespace RSSReader.Services.Contracts
  83: {
  84:     [DataContract]
  85:     public class FeedArticleDTO
  86:     {
  87:         [DataMember]
  88:         public string Title { get; set; }
  89:  
  90:         [DataMember]
  91:         public DateTime Published { get; set; }
  92:  
  93:         [DataMember]
  94:         public string BodyContent { get; set; }
  95:     }
  96: }
  97:  

With our data contracts defined, we can now look at defining the operation contracts - the services themselves. As mentioned above, we're going to have a single service, lets call it RSSProxyService, and it will have two methods. A method to get all of the feeds that are available and a method to get the articles for a selected feed. The signatures of these methods will use the data contracts defined above. Within the Spec folder, create a new class file and name it IRSSProxyService.cs. The code should be as follows;

   1: using System.ServiceModel;
   2: using RSSReader.Services.Contracts;
   3:  
   4: namespace RSSReader.Services.Spec
   5: {
   6:     [ServiceContract]
   7:     public interface IRSSProxyService
   8:     {
   9:         [OperationContract]
  10:         GetAvailableFeedsResponseDTO GetAvailableFeeds();
  11:  
  12:         [OperationContract]
  13:         GetFeedResponseDTO GetFeed(GetFeedRequestDTO request);
  14:     }
  15: }

In WCF we define services as interfaces and then tell the service definition which concrete class to use that implements this interface. As you can see our two methods are marked up with [OperationContract] attributes, indicating that these are methods that will be exposed through the service and the interface itself is defined with a [ServiceContract] attribute.

We now need to provide a concrete implementation of the service. As such, create a new class called RSSProxyService.cs within the root of RSSReader.Services project;

   1: using System;
   2: using RSSReader.Services.Spec;
   3: using RSSReader.Services.Contracts;
   4:  
   5: namespace RSSReader.Services
   6: {
   7:     public class RSSProxyService : IRSSProxyService
   8:     {
   9:         public GetAvailableFeedsResponseDTO GetAvailableFeeds()
  10:         {
  11:             throw new NotImplementedException();
  12:         }
  13:  
  14:         public GetFeedResponseDTO GetFeed(GetFeedRequestDTO request)
  15:         {
  16:             throw new NotImplementedException();
  17:         }
  18:     }
  19: }

If you build now, things should build, but as we've not hooked anything up yet, it won't do a great deal. Lets make it actually do something and write some unit tests to check our implementation actually works.

Implementing the repository
Before we can get into the guts of the service itself, we need to think about how we're going to get data out of feeds.xml and from the RSS feeds themselves. I've chosen to implement a repository class so that my service concentrates on logic and uses the repository to handle any data persistence/access.

Before we dive headlong into writing a repository class though, we need to give some thought to testing. We want to be able to unit test this service to verify that it is working as anticipated, but we want to test the logic, not test if the internet is up and running (which is what we would be doing if we consumed an RSS feed directly - pass/fail would be dependent upon the RSS feed being available).

As such, we are going to want to replace the repository code when testing with a pre-canned or mocked version of it. This will allow us to control what data is sent to the service when we invoke it. To do this we must define an interface for the repository.

Within the repositories folder, create a new file - IFeedRepository.cs with the following content;

   1: using System.Collections.Generic;
   2: using RSSReader.Services.Contracts;
   3:  
   4: namespace RSSReader.Services.Repositories
   5: {
   6:     public interface IFeedRepository
   7:     {
   8:         IEnumerable<RSSFeedDTO> GetFeedDefinitionList();
   9:         RSSFeedDTO GetFeedDefinitionById(string id);
  10:         IEnumerable<FeedArticleDTO> GetArticlesForFeedId(string id);
  11:     }
  12: }

In this instance, our feed repository will offer 3 methods. One to get the feed definition list, one to get a specific feed definition record from the list and one to get all of the articles for a specified feed id.

We can then implement this by creating FeedRepository.cs, as follows;

   1: using System;
   2: using System.Collections.Generic;
   3: using System.IO;
   4: using System.Linq;
   5: using System.Net;
   6: using System.Xml.Linq;
   7: using RSSReader.Services.Contracts;
   8:  
   9: namespace RSSReader.Services.Repositories
  10: {
  11:     public class FeedRepository : IFeedRepository
  12:     {
  13:         private static XDocument GetFeedDefinitionData()
  14:         {
  15:             string filename = Path.GetFullPath(
  16:                 AppDomain.CurrentDomain.BaseDirectory) + "\\feeds.xml";
  17:             XDocument doc = XDocument.Load(filename);
  18:             return doc;
  19:         }
  20:  
  21:         /// <summary>
  22:         /// Loads the feed definition list from the XML file "feeds.xml"
  23:         /// </summary>
  24:         /// <returns></returns>
  25:         public IEnumerable<RSSFeedDTO> GetFeedDefinitionList()
  26:         {
  27:             XDocument doc = GetFeedDefinitionData();
  28:             
  29:             IEnumerable<RSSFeedDTO> list =
  30:                 from item in doc.Descendants("feed")
  31:                 select new RSSFeedDTO
  32:                 {
  33:                     Id = (string)item.Attribute("id"),
  34:                     Title = (string)item.Element("title"),
  35:                     FeedUrl = (string)item.Element("url")
  36:                 };
  37:  
  38:             return list;
  39:         }
  40:  
  41:         /// <summary>
  42:         /// Gets one feed definition item from feeds.xml
  43:         /// </summary>
  44:         /// <param name="id"></param>
  45:         /// <returns></returns>
  46:         public RSSFeedDTO GetFeedDefinitionById(string id)
  47:         {
  48:             XDocument doc = GetFeedDefinitionData();
  49:  
  50:             // query it for feed items and create RSSFeedDTO objects
  51:             var matchedFeeds =
  52:                 from item in doc.Descendants("feed")
  53:                 where ((string)item.Attribute("id")) == id
  54:                 select new RSSFeedDTO
  55:                 {
  56:                     Id = (string)item.Attribute("id"),
  57:                     Title = (string)item.Element("title"),
  58:                     FeedUrl = (string)item.Element("url")
  59:                 };
  60:  
  61:             if (matchedFeeds.Count() < 1) return null;
  62:  
  63:             return matchedFeeds.First();
  64:         }
  65:  
  66:         /// <summary>
  67:         /// Gets all of the articles available from the RSS feed
  68:         /// definition id specified.
  69:         /// </summary>
  70:         /// <param name="id"></param>
  71:         /// <returns></returns>
  72:         public IEnumerable<FeedArticleDTO> GetArticlesForFeedId(string id)
  73:         {
  74:             // Find the feed
  75:             RSSFeedDTO feed = GetFeedDefinitionById(id);
  76:             if (feed == null) throw new ArgumentException(
  77:                     String.Format("Feed id {0} not found", id));
  78:  
  79:             // Get the RSS payload
  80:             WebClient client = new WebClient();
  81:             string responsePayload = client.DownloadString(feed.FeedUrl);
  82:  
  83:             // Load it into LINQ to XML and find all items, 
  84:             // translate to FeedArticleDTOs
  85:             XDocument rssResponse = XDocument.Parse(responsePayload);
  86:             
  87:             IEnumerable<FeedArticleDTO> list =
  88:                 from item in rssResponse.Descendants("item")
  89:                 select new FeedArticleDTO
  90:                 {
  91:                     Title = item.Element("title").Value,
  92:                     Published = DateTime.Parse(item.Element("pubDate").Value),
  93:                     BodyContent = item.Element("description").Value
  94:                 };
  95:  
  96:             return list;
  97:         }
  98:     }
  99: }

As you can see, we're using LINQ to XML to query the XML data from feeds.xml and transform the data into our DTO classes, and when we retrieve data from the physical RSS feeds we're going to use the WebClient object, and again query and extract this with LINQ.

Implementing the service
With our repository in place we can now build our service implementation. Go back to our RSSProxyService.cs and change it's code to match this;

   1: using RSSReader.Services.Spec;
   2: using RSSReader.Services.Contracts;
   3: using RSSReader.Services.Repositories;
   4:  
   5:  
   6: namespace RSSReader.Services
   7: {
   8:     public class RSSProxyService : IRSSProxyService
   9:     {
  10:         // The feed repository we will use
  11:         private readonly IFeedRepository _feedRepository;
  12:  
  13:         public RSSProxyService()
  14:         {
  15:             _feedRepository = new FeedRepository();
  16:         }
  17:  
  18:         public RSSProxyService(IFeedRepository feedRepository)
  19:         {
  20:             _feedRepository = feedRepository;
  21:         }
  22:  
  23:         /// <summary>
  24:         /// Interrogates the feeds.xml file to return a list of 
  25:         /// available RSS feeds that can be displayed
  26:         /// </summary>
  27:         /// <returns></returns>
  28:         public GetAvailableFeedsResponseDTO GetAvailableFeeds()
  29:         {
  30:             GetAvailableFeedsResponseDTO feeds 
  31:                 = new GetAvailableFeedsResponseDTO();
  32:  
  33:             foreach (RSSFeedDTO feed in 
  34:                 _feedRepository.GetFeedDefinitionList())
  35:             {
  36:                 feeds.Feeds.Add(feed);
  37:             }
  38:  
  39:             return feeds;
  40:         }
  41:  
  42:         /// <summary>
  43:         /// Gets articles from the requested RSS feed.
  44:         /// </summary>
  45:         /// <param name="request"></param>
  46:         /// <returns></returns>
  47:         public GetFeedResponseDTO GetFeed(GetFeedRequestDTO request)
  48:         {
  49:             GetFeedResponseDTO response = new GetFeedResponseDTO();
  50:             foreach (FeedArticleDTO article in 
  51:                 _feedRepository.GetArticlesForFeedId(request.FeedId))
  52:             {
  53:                 response.Articles.Add(article);
  54:             }
  55:  
  56:             return response;
  57:         }
  58:     }
  59: }

If you notice our constructors now, we either create or accept an IFeedRepository object depending on which constructor is used - this allows us to write (or mock) a replacement repository, specifically for testing this service. (This is an example of coding for testability as when not thinking about unit testing, you wouldn't write code like this).

Our implementation of the service itself is now complete. We have to now either expose this via our web interface and write all the front end code to consume it in order to test it, or we need to write unit tests to satisfy ourselves that things are working as they should. I'd sooner find problems as early as possible, so lets write some unit tests.

Writing unit tests to check the service
Add a new project to your solution, a test project and call it RSSReader.Services.Tests.

image

You can then clear out the AuhtoringTests.txt file, and rename the UnitTest1.cs file to RSSProxyServiceTests.cs. Also copy the feeds.xml file into your test project. You will need to tell the test project to deploy the feeds.xml file when it runs the tests, as follows;

Select the Test menu and choose "Edit Test run configurations" and then "Local test run". From the resultant dialog, select the deployment page and select "Add File" - choose feeds.xml from the RSSReader.Services.Tests directory and click Apply to save the changes.

image

In order to provide our service with a canned set of data from the repository, we're going to "mock" the repository using a mocking framework.

We're going to use the excellent Rhino Mocks mocking framework by Oren Eini (aka Ayende Rahien). You'll need to download this from here, extract it, and then add a reference in your test project to Rhino.Mocks.dll. Also add a reference to the RSSReader.Services project.

Finally change the RSSPRoxyServiceTests.cs to match the following;

   1: using System;
   2: using System.Collections.Generic;
   3: using Rhino.Mocks;
   4: using Microsoft.VisualStudio.TestTools.UnitTesting;
   5: using RSSReader.Services.Repositories;
   6: using RSSReader.Services.Spec;
   7: using RSSReader.Services.Contracts;
   8:  
   9: namespace RSSReader.Services.Tests
  10: {
  11:     [TestClass]
  12:     public class RSSProxyServiceTests
  13:     {
  14:         /// <summary>
  15:         /// This test validates that the feeds.xml file can be loaded
  16:         /// correctly and that it contains 3 defined feeds.
  17:         /// </summary>
  18:         [TestMethod]
  19:         public void ValidateFeedsLoaded()
  20:         {
  21:             IRSSProxyService service = new RSSProxyService();
  22:             GetAvailableFeedsResponseDTO response = 
  23:                 service.GetAvailableFeeds();
  24:  
  25:             Assert.IsNotNull(response);
  26:             Assert.AreEqual(3, response.Feeds.Count);
  27:         }
  28:  
  29:         /// <summary>
  30:         /// This test uses a mocked IFeedRepository to returned canned
  31:         /// data into the RSS proxy service implementation to allow it's 
  32:         /// logic to be tested. It ensures the correct number of articles
  33:         /// are returned when a feed is queried by ID.
  34:         /// </summary>
  35:         [TestMethod]
  36:         public void ValidateArticleCounts()
  37:         {
  38:             MockRepository mocks = new MockRepository();
  39:  
  40:             // Define the data we want the IFeedRepository to return
  41:             IEnumerable<FeedArticleDTO> feedList = new List<FeedArticleDTO>
  42:             {
  43:                 new FeedArticleDTO{Title="Article 1", 
  44:                     Published=DateTime.Now, BodyContent=""},
  45:  
  46:                 new FeedArticleDTO{Title="Article 2", 
  47:                     Published=DateTime.Now, BodyContent=""},
  48:  
  49:                 new FeedArticleDTO{Title="Article 3", 
  50:                     Published=DateTime.Now, BodyContent=""},
  51:  
  52:                 new FeedArticleDTO{Title="Article 4", 
  53:                     Published=DateTime.Now, BodyContent=""},
  54:  
  55:                 new FeedArticleDTO{Title="Article 5", 
  56:                     Published=DateTime.Now, BodyContent=""}
  57:             };
  58:  
  59:             // Mock the feed repository and setup some expectations
  60:             IFeedRepository feedRepository = 
  61:                 mocks.StrictMock<IFeedRepository>();
  62:  
  63:             using (mocks.Record())
  64:             {
  65:                 Expect.Call(feedRepository.GetArticlesForFeedId("MOCK"))
  66:                     .Return(feedList);
  67:             }
  68:  
  69:             GetFeedResponseDTO response;
  70:             using (mocks.Playback())
  71:             {
  72:                 // Test the service - the service will use the mock repository
  73:                 IRSSProxyService service = 
  74:                     new RSSProxyService(feedRepository);
  75:  
  76:                 // Request the MOCK feed
  77:                 GetFeedRequestDTO request = new GetFeedRequestDTO();
  78:                 request.FeedId = "MOCK";
  79:  
  80:                 // Get the response and test
  81:                 response = service.GetFeed(request);
  82:             }
  83:  
  84:             Assert.IsNotNull(response);
  85:             Assert.AreEqual(5, response.Articles.Count);
  86:         }
  87:     }
  88: }

This test class contains two specific tests that will test the workings of the service itself - ValidateFeedsLoaded will test that the service can load the feeds.xml file and correctly assemble the XML into the objects we're expecting.

ValidateArticleCounts is a little different in that it's using mocks. We define what data the repository is going to return when invoked, create a mocked object of the repository and then setup some expectations on what we expect the service code to do with our mocked repository.

In this case, we tell the mocking framework that we expect the service to call the repositories GetArticlesForFeedId method with a parameter of "MOCK", and when it does, the mock framework should return the canned data we've setup.

We then invoke the service, passing in the mocked repository so that it is used instead of the default and then we invoke the service with the parameters expected. If all goes well, the expected calls will be invoked and we will have a response from the service with the correct number of articles.

Now, for those eagle eyed among you, you will notice we're not testing the functionality of the repository. We certainly should, but as this series of posts is supposed to be about Silverlight, I'll leave that as an exercise for the reader - but we would have to encapsulate the WebClient so that it, itself, could be mocked so the repository is tested, not the availability of the RSS feeds...

If you now build your application and run it you'll find we have nothing more than we did at the end of the last article!! However we do have a completed service implementation and we can use test view to run the two unit tests and validate that our service is functional.

image

image

(NOTE: When you run your unit tests, you may get a "Test run deployment issue" saying "Rhino.Mocks.dll" is not trusted. This is because you downloaded the files from the Internet. The solution is to find the DLL's on your machine using explorer, right click each DLL and click "Unblock" - then do a rebuild and you should be good to go)

That's all for this instalment (it was longer than I expected!) - in part 3 we'll look at exposing the above service through the web project, consuming it in Silverlight and having fun with data binding.

Again, have a good Christmas!

Get the source code here.

Wednesday, 17 December 2008

The Uncanny Valley effect...

I've always rejected building web applications that ape desktop applications, but articulating this rejection has always failed me. I've never been able to put my finger on why I don't like fancy ajax interfaces that mimic desktop application, but Jeff Atwood has a post today that explains it extremely well.

http://www.codinghorror.com/blog/archives/000869.html

Tuesday, 16 December 2008

Building a Silverlight RSS reader - part 1 - getting the skeleton structure ready

In this series of posts, I'm going to look at building a simple RSS reader in silverlight. I chose an RSS reader as it covers a number of typical scenarios including;

  • Cross domain requests - where you can't guarantee the target domain has a cross domain policy in place.
  • A configurable source on the host server controlling which RSS feeds the reader should display.
  • Creating a skinnable UI
  • Touching on things silverlight can't yet do (display HTML natively for example).

So kicking off, I'm going to create a new solution as follows;

image

I've selected a new silverlight application and named it RSSReader.UI.Components (as it may contain other components later). I've also chosen to create a directory for the solution and named this SilverlightRSSReader.

VS.NET then asks us how we want to run the application. In this case, I'm going to want to write code on the website too, so I've chosen to create a new ASP.NET web project solution and named it RSSReader.UI.Web

image

This then gives us the following solution structure;

image

This needs some tidying up before we begin. First off, delete default.aspx and the test page.html. Finally rename the testpage aspx to default.aspx and also tidy up the source to something more akin to the following;

   1: <%@ Page Language="C#" AutoEventWireup="true" %>
   2: <%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls" TagPrefix="asp" %>
   3:  
   4: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
   5:  
   6: <html xmlns="http://www.w3.org/1999/xhtml" style="height:100%;">
   7: <head runat="server">
   8:     <title>RSSReader.UI.Components</title>
   9: </head>
  10:  
  11: <body style="height:100%;margin:0;">
  12:     <form id="form1" runat="server" style="height:100%;">
  13:         <asp:ScriptManager ID="ScriptManager1" runat="server"></asp:ScriptManager>
  14:  
  15:         <div id="silverlightHost" style="height:100%;">
  16:  
  17:             <asp:Silverlight ID="Xaml1" runat="server" PluginBackground="Transparent" Windowless="true"
  18:                 Source="~/ClientBin/RSSReader.UI.Components.xap" 
  19:                 MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />
  20:  
  21:         </div>
  22:     </form>
  23: </body>
  24: </html>

You finally want to set the default.aspx page to be the page used on start up. You can do this by right clicking on it in solution explorer and clicking set as start page.

If you run your application now, it should compile correctly and show you a rather underwhelming blank silverlight application. Let's correct that and get the basic form and structure of our application ready.

The following is a wireframe for how I want my application to look:

image

Creating this basic layout is extremely simple using XAML, but first, we want to pull in an image resource for the branding and change the html body colour. Copy in rss.png from the attached zip file, and put it in a new folder called Resource within your silverlight application.

Finally, add the following to the head section of default.aspx;

<style>
    BODY
    {
        background-color: black;
    }
    #silverlightHost
    {
        background-color: Transparent;
        position: absolute;
        width: 100%;
        height: 100%;
        left: 0px;
        top: 0px;
    }
</style>   

This is simply setting the window to be black coloured (after all, every silverlight app must be black - it's an unwritten law !!). If you're wondering why we're not just setting the background in the silverlight and instead are setting that to transparent - the reason will become apparent later when we have to have the browser show HTML and we need it to look like it's within our silverlight app.

Next, in your silverlight app, add a reference to System.Windows.Controls.Data - this gives us the data grid component to use in our app.

Finally, open page.xaml and use the following skeleton code;

   1: <UserControl x:Class="RSSReader.UI.Components.Page"
   2:     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
   3:     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   4:     xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data">
   5:  
   6:     <Grid>
   7:         <!-- The main UI stack -->
   8:         <StackPanel Margin="10,10,10,10">
   9:  
  10:             <!-- Top bar area -->
  11:             <Grid Background="Black">
  12:                 <Grid.ColumnDefinitions>
  13:                     <ColumnDefinition Width="Auto"/>
  14:                     <ColumnDefinition Width="Auto"/>
  15:                     <ColumnDefinition Width="*"/>
  16:                 </Grid.ColumnDefinitions>
  17:  
  18:                 <Image Source="Resource/rss.jpg" Margin="0,0,10,0"/>
  19:  
  20:                 <TextBlock Grid.Column="1" Margin="0,6,0,0" FontSize="18" Foreground="White">RSS Exemplar</TextBlock>
  21:  
  22:                 <ComboBox x:Name="_availableFeeds" Grid.Column="2" Margin="0,6,0,0" IsEnabled="False" 
  23:                       VerticalAlignment="Top" HorizontalAlignment="Right" Height="30" MinWidth="250">
  24:                 </ComboBox>
  25:             </Grid>
  26:  
  27:             <!-- Grid binding to articles -->
  28:             <data:DataGrid x:Name="_articleList" AutoGenerateColumns="False">
  29:                 <data:DataGrid.Columns>
  30:                     <data:DataGridTextColumn Header="Published Date" Width="150"/>
  31:                     <data:DataGridTextColumn Header="Title"/>
  32:                 </data:DataGrid.Columns>
  33:             </data:DataGrid>
  34:  
  35:             <!-- Todo: content preview pane -->
  36:             <!-- Todo: status area and skin selector -->
  37:         </StackPanel>
  38:     </Grid>
  39:  
  40: </UserControl>

Run your application and you should see:

image

Hardly the most exciting application in the world so far, but it gives us everything we need to build on in the next articles. If you want to skip ahead and try to move the application on, go ahead, the next topics will cover;

  • Getting data and binding to it
    • Getting available feeds for the combo box
    • Getting feed data from the RSS feed itself using an intermediate, marshalling, service.
    • Adding a service reference
  • Displaying and interfacing to HTML
    • Silverlight can't display HTML directly, we need to display the article content itself by asking the HTML host to do it. This article will cover integration to HTML, and will result in a positioned DIV in the correct place beneath the silverlight app to show the post content. (This is why our silverlight is made transparent)
  • Skinning the application and changing skins
    • This will cover making the app look pretty(ish) and how to dynamically change skins on the fly.

For now, have a good Christmas.

Download the source code here

.

Monday, 8 December 2008

Essential reading

Here's a quick list of what my top 4 general development books that everyone should have on their shelf;

image
Code complete (2nd Edition)

Steve McConnell
Microsoft Press

This is a practical guide to programming in general and the definitive guide to software construction.
image
Design Patterns - Elements of Reusable object oriented software.
Gamma, Helm, Johnson and Vlissides
Addison Wesley

The famous gang of four OO design patterns book.
image
Patterns of Enterprise Application Architecture
Martin Fowler
Addison Wesley

This book details many software design patterns found in enterprise software by the Thoughtworks guru, Martin Fowler.
image
The Mythical Man-Month
Frederick P. Brooks
Addison Wesley

This is a collection of essays on software project management that was first published in 1975. It contains the legendary "Brooks Law" - that adding manpower to a late project makes it later. The concepts laid out in this book are as valid today as they were 30 years ago.

Tuesday, 2 December 2008

"New XBOX Experience" trashes my 360...

Whilst I like to keep this as a technical blog, I must doff my cap to Microsoft's XBOX 360 warranty and repair service. I bought my 360 in Jan 2006 and didn't have any problems with it until the new XBOX experience was launched a couple of weeks ago.

image Almost immediately (and probably coincidentally) I started to get video corruption problems, hanging and then finally, the ubiquitous 3 red rings of death!

But that's not the point, first off kudos on extending the warranty to 3 years for this specific error - of which my 360 was just 1 month away from being out of warranty, and secondly for the lightning fast repair service.

I've just logged on to check up on where my unit is, which I only posted to them on Wednesday last week, and they've fixed it and have shipped it back, it's being delivered tomorrow - that's less than 1 week!!

COD: World at war stress relieving marathon due this weekend ;-) The wife will be pleased.....

Tuesday, 18 November 2008

Expand a virtual PC VHD file and extend the partition

Ran into a few problems today, for one client who uses a VPN that doesn't work at all well with Vista, I have an XP development virtual PC. I needed to install visual studio sp1 (yet again) on it but my boot drive only had 4Gb of free space - the temporary installer needs more than that.

After finding the excellent VHD Resizer I was able to resize by virtual disk by an additional 10Gb, however it doesn't extend the disk into this space and diskpart won't let you issue an extend command on the boot disk.

The solution? Boot off another VHD with the resized disk as a second drive, then extend under this environment before shutting down and setting it back to the newly extended drive.

Full answer here...

http://www.enusbaum.com/blog/2008/02/07/expand-a-virtual-pc-vhd-file-and-extend-the-partition/

Sunday, 16 November 2008

Using attached properties to compose new behaviour

I was inspired by a posting on stackoverflow.com - "How do I drag an image around a canvas in WPF" - where the first response in most peoples heads is to work with mouse up/down/move events, track offset positions and move the UI element around in response - pretty reasonable right?

Seeing as WPF's principles favours composition over inheritance and such like, what if instead we used the power of attached properties to attach new behaviour to a UIElement? Here's how to do it, first the code for the dependency property:

public class DraggableExtender : DependencyObject
{
    // This is the dependency property we're exposing - we'll 
    // access this as DraggableExtender.CanDrag="true"/"false"
    public static readonly DependencyProperty CanDragProperty =
        DependencyProperty.RegisterAttached("CanDrag",
        typeof(bool),
        typeof(DraggableExtender),
        new UIPropertyMetadata(false, OnChangeCanDragProperty));

    // The expected static setter
    public static void SetCanDrag(UIElement element, bool o)
    {
        element.SetValue(CanDragProperty, o);
    }

    // the expected static getter
    public static bool GetCanDrag(UIElement element)
    {
        return (bool) element.GetValue(CanDragProperty);
    }

    // This is triggered when the CanDrag property is set. We'll
    // simply check the element is a UI element and that it is
    // within a canvas. If it is, we'll hook into the mouse events
    private static void OnChangeCanDragProperty(DependencyObject d, 
        DependencyPropertyChangedEventArgs e)
    {
        UIElement element = d as UIElement;
        if (element == null) return;

        if (e.NewValue != e.OldValue)
        {
            if ((bool)e.NewValue)
            {
                element.PreviewMouseDown += element_PreviewMouseDown;
                element.PreviewMouseUp += element_PreviewMouseUp;
                element.PreviewMouseMove += element_PreviewMouseMove;
            }
            else
            {
                element.PreviewMouseDown -= element_PreviewMouseDown;
                element.PreviewMouseUp -= element_PreviewMouseUp;
                element.PreviewMouseMove -= element_PreviewMouseMove;
            }
        }
    }

    // Determine if we're presently dragging
    private static bool _isDragging = false;
    // The offset from the top, left of the item being dragged 
    // versus the original mouse down
    private static Point _offset;

    // This is triggered when the mouse button is pressed 
    // on the element being hooked
    static void element_PreviewMouseDown(object sender, MouseButtonEventArgs e)
    {
        // Ensure it's a framework element as we'll need to 
        // get access to the visual tree
        FrameworkElement element = sender as FrameworkElement;
        if (element == null) return;

        // start dragging and get the offset of the mouse 
        // relative to the element
        _isDragging = true;
        _offset = e.GetPosition(element);
    }

    // This is triggered when the mouse is moved over the element
    private static void element_PreviewMouseMove(object sender, 
        MouseEventArgs e)
    {
        // If we're not dragging, don't bother
        if (!_isDragging) return;

        FrameworkElement element = sender as FrameworkElement;
        if (element == null) return;

        Canvas canvas = element.Parent as Canvas;
        if( canvas == null ) return;
        
        // Get the position of the mouse relative to the canvas
        Point mousePoint = e.GetPosition(canvas);

        // Offset the mouse position by the original offset position
        mousePoint.Offset(-_offset.X, -_offset.Y);

        // Move the element on the canvas
        element.SetValue(Canvas.LeftProperty, mousePoint.X);
        element.SetValue(Canvas.TopProperty, mousePoint.Y);
    }

    // this is triggered when the mouse is released
    private static void element_PreviewMouseUp(object sender, 
        MouseButtonEventArgs e)
    {
        _isDragging = false;
    }
}

As you can see, we hook into the events exposed from the target element whenever we detect the property being changed. This allows us to inject any logic we like!

To use the behaviour, we include the namespace in XAML:

<Window x:Class="WPFFunWithDragging.Window1"
        xmlns:local="clr-namespace:WPFFunWithDragging"

And then just attach the behaviour to the elements we want to be able to drag like so;

<Canvas>
       <Image Source="Garden.jpg" 
              Width="50" 
              Canvas.Left="10" Canvas.Top="10" 
              local:DraggableExtender.CanDrag="true"/>
   </Canvas>

Cool huh? Sample code attached....