Friday, January 23, 2009

Adventures while building a Silverlight Enterprise application part #5

It's been a while sins part #4 of this series, mainly because I had some distractions from this project, but also because some requirements were still unclear and we had to wait to see how these would impact implementation details. Now that we are a little further in time, I had some interesting discussion about how we should implement our application.

As I promised dsoltesz in part #3 of this series, I would come up with a post on setting up projects for Silverlight. Although we haven't worked out all the details yet, I didn't want to wait any longer, so this post is mainly about what to look for when starting up a large scale Silverlight 2 project.

Your options
So what are your options for setting up a large scale Silverlight 2 development? Obviously there are many ways to go about it, but I will discuss a few common ones and point out why or why not to use some approaches.

  1. Use a single Silverlight Application
  2. Use a single Silverlight Application with Silverlight Class Libraries
  3. Use multiple Silverlight Applications on different pages
  4. Use multiple Silverlight Applications and load them dynamically
Combinations of 2, 3 and 4 are obviously possible and may balance out some of the pros and cons for some of these approaches in specific scenarios.

Before going into details of each of these approaches, I would like to point out that when I talk about a large Silverlight development, I'm talking about at least over twenty different 'forms' to call and an extensive functionality being provided in both the service layer as well as in the UI (validations, algorithms, etc).

Use a single Silverlight Application

The upside of things is that this is very easy to setup... and that's about the only upside I can think of. Downsides? Long initial loading, heavy memory load on the client, harder to maintain, harder to reuse parts. This is obviously a no-go for a large application.

Use a single Silverlight Application with Silverlight Class libraries

This is pretty much the same approach as just having a single application, however, it does make it somewhat easier to maintain and a lot easier to reuse parts. If you have a maybe not so large application, this might be worth investigating.

Use multiple Silverlight Applications on different pages

This makes setup a challenge, because you have to consider what to put on each page, but also what information you would need to share between pages, and how to do this. On its own, this approach will give you shorter load times, easier maintenance and lighter loads on the client. Combine it with the previous approach and you also gain the reusable thing.

This is a good approach IF you can come up with a clear way to split up your application in different pages and you don't have to share large chunks of data between each page.

Use multiple Silverlight Applications and load them dynamically

This makes setup a bit less challenging then the previous approach as you don't have to worry about splitting up over different pages. Sharing data however still requires some thinking, although you do keep state when loading different parts of the application. A different problem with this is, that you do load a lot of overhead if you end up with a large number of small applications (say one for each small 'form').

You do get better load times, but also better response times when navigating through the application. Load on the client is smaller, sharing data is slightly easier then with the previous approach and maintainability is better then all the others. Re usability is also better then all the others.

This would be the way to go, as long as you can come up with a decent design and some common ground on sharing data. A decent service layer is also a requirement.

Applications vs Class libraries

This is actually not a typical Silverlight topic, but as a lot of Silverlight developers have a strictly web background, I figure it wont heart to tough the subject. For everything you build there is the choice, do I put it in an application or in class library? Although there is no 'right way' to go with this there are some pointers:

  • Is this something I'm going to use in other parts of the development?
  • Is this something I might reuse in other projects?
  • Is this a custom control?
  • Is this not a UIElement?

If any of these questions result in a positive answer (watch the not in the last one and think like a developer ;-)), then you probably want to use a class library. In most other cases you can just put it in an application and you'll be fine.

Solutions

Another part of setting up the project is the solution files. Although Microsoft states that a solution file is developer specific and because of this could very per developer, this is usually not what happens in practice. On the other hand I've seen a lot of developments slow down to a crawl, because they just threw all their projects in one huge solution, that would take ages to load and if someone made the mistake to rebuild the solution, it would take even longer to complete.

Obviously the truth lays somewhere in the middle, so using a few solutions is usually a good idea. How you split them up, however, is very dependent on the team, the tools, the project and also personal preference. In our case, our goal is to have several developers build modules for our application. To make this possible we're building a framework that supports running these modules and provides all the common UI elements and behaviour. This makes up one solution. Other solutions will contain sets of modules that are grouped based on their logical purpose.

We can work with smaller solutions, because we have Team Foundation Server and use a build server to generate releases, so we don't have to worry about manually opening all the solutions, and build them. Also, all our modules have to be able to run without the framework, so we don't have to worry about test runs during development. All we have to do is do integration testing for the modules.

If you don't have a build server, or another form of automated building, then you probably want to cut back on the number of solutions, but always look out for the size. Once a solution becomes slow to load and/or build, think about moving some projects to another solution.

I hoped you enjoyed this article and I'm looking forward to your comments below.

Wednesday, January 21, 2009

Ole and accessing files embedded in Access part #1

Well, it's been a while sins my last post. I've been really busy on building the software that makes this article possible and in my spare time I've also been really busy on a website, of which I'll tell you more when the time is ripe.

But down to business, today's post is the start of a short series on Ole and files in Microsoft Access. Unfortunately we're looking at technology of the stone age here and documentation on the subject is hard to find. Still we need a way to extract the files we had stored through Access, to be able to move away from this technology.

In this first article we'll look at some theory and the challenges will become apparent. The later articles will show the code for working with Ole in C#. But before we go on, I would like to express a big 'thank you' to Ernst Raedecker, who provided me with some insight on the actual headers. Also I would like to thank Eduardo Morcillo for providing me with a .NET library to handle structured storage.

Files in Microsoft Access
So let's get started. The first thing we need to understand is why this is so difficult. The Access team, back in the day, needed a way to not only store files in an Access database, but also to present it to the user, with other software installed on the users computer. Because back then, there was no reliable way to find out through the OS what software handled what file type, they had to come up with some other way. That way is OLE: Object Linking and Embedding. It was first released in 1990.

All is well, we just determine the length of the header and footer and chop 'm off, right? Wrong. Unfortunately someone, somewhere decided that it would be more efficient in storage to vary the length of a part of the header based on it's contents. Oh, and someone came up with structured storage, so your original file is actually embedded in a mini file system, which needs reading out... but not always.

Here is how a file is stored inside Access:
  • Package header
  • Ole header
  • Data block length
  • Data (which can be a structured storage, but it can also be the actual file)
  • Sometimes a metafilepict block
  • Ole footer

So as you can see, there is a lot of variation in Ole files. Fortunately they do have some things in common to help with the process of extraction, but if you are looking to get a better understanding, I would advice to install a Hex-editor.

The first thing to look at is both of the headers. The package header looks like this:

  • A Signature (short): this indicates that the file is a package
  • The header size (short)
  • An object type (uint): 0 = linked, 1= embedded, 2 = either (who came up with either?)
  • The length of the friendly name in the header (short)
  • The length of the class name in the header (short)
  • The offset of the friendly name (short)
  • The offset of the class name (short)
  • The size of the object (int)
  • The friendly name (string, variable length)
  • The class name (string, variable length)

So, as you can see, you need to actually interpret the package header to get the right length, to skip over the header, but also you can learn what is inside the package by reading some of the information it provides.

The Ole header has a lot less information inside it:

  • The Ole version (uint)
  • The Format (uint)
  • The object type name length (int)
  • The object type name (string, variable length)

The Ole header actually ends with 8 empty bytes followed by 4 bytes that make up the length of the datablock as an int.

As I explained earlier, inside the datablock can be the actual file, but also there can be a structured storage. To determine if this is a structured storage, there is actually an 8 byte signature at the start of the storage.

Inside the storage, there is a mini file system, of which you can find the specs here. If you look in to them, you'll understand why I chose to use Eduardo's library, instead of building my own :-). Say, "thank you, Eduardo".

But... you should not always dig into the structured storage. If, for example you stored a Microsoft Word document in Access, you need to leave the structured storage in tact, as it's part of the Word document. So at this part, the class name from the package header comes in handy.

If you do have to dig into the structured storage, what you're looking for is the stream inside the CONTENTS element. It is the binary stream that makes up the original file.

Now, if you're dealing with images, like I am, there is another catch, called the metafilepict block. You're not likely to find a CONTENTS element if you need to read the metafilepict block. The big question for me was, where is the metafilepict block. It turns out that it is at a position you can calculate like this:

metefilepict start position = total package header length + total ole header length + 8 (empty bytes) + 4 (data length bytes) + data length + 45 (metafilepict header length)

The stream at this position contains your actual image file.

So now you know how it all works. In the next post we'll dive into some code I wrote to handle all this. If you have any questions, comments or suggestions, please leave us all a comment.

Monday, January 12, 2009

Adventures while building a Silverlight Enterprise application part #4

Another week has gone. Here we are with part 4 of our adventure. Last time we dough into the ins and outs of using multiple XAP files. Thanks again to dsoltesz for some constructive comments on that article.

This time we want to look into something I've been struggling with for about a day, last week. It's localizing our application. As you may remember from the first post, one of the requirements is that the application has to be available in both English and Dutch. "Well, that is easy. Just go to silverlight.net and you'll find a very nice instructional video on this", I hear you say.
That was our initial thought as well and it proved to be true...

...until, that is, we tried to apply this to a datagrid. I'll describe what happened by using the car application from some of my other articles.

The default implementation
As documented by many, we did the following to localize our application:
  • Add a folder named "Resources" to our projects
  • Add a file named "Strings.resx" and add any strings for the neutral culture (in our case nl-NL for dutch in the Netherlands)
  • Add a file for each culture you want to support (in our case only "Strings.en.resx") with all the same strings
  • Add a local resource to each UserControl for the generated class:

<UserControl.Resources>
<cardemo:Engines x:Key="Engines" />
<local:Strings x:Key="LocalStrings" />
</UserControl.Resources>

  • Bind each string to display to an entry in the resource:
<data:DataGridTextColumn Binding="{Binding Brand}" Header="{Binding brandLabel, Source={StaticResource LocalStrings}}">
</data:DataGridTextColumn>

And Bob's your uncle. For any control, this works great, but not for the datagrid. Run the code and you'll get the following exception:

System.Windows.Markup.XamlParseException occurred Message="AG_E_PARSER_BAD_TYPE [Line: 11 Position: 46]" LineNumber=11 LinePosition=46 StackTrace: at System.Windows.Application.LoadComponent(Object component, Uri resourceLocator) at ComboLookup.Page.InitializeComponent() at ComboLookup.Page..ctor()

First thing I did was Google around to find out if someone already solved this problem. I found out this problem was introduced in the RTW release and I found some forum treads on silverlight.net, discussing this problem. I even found some solutions, but I was not very happy with those. One solution ended up using some reflection code inside a LINQ statement to add all the string entries to the local Resources instance (which could end up being a performance issue in applications with larger resource files). Another solution involved building a custom mechanism for filling up the headers of the datagrid, which seems like a maintenance nightmare to me.

So I figured I would have to come up with some better solution. First I started digging to find out what was causing the problem. I used Reflector to dig into the code that is actually executed and found out that the problem is actually deep down in the core of the Silverlight .NET Framework, where the XAML is actually parsed, and you can't get to that code. This struck me as odd, as you would expect the XAML parser to be completely generic, but still there is this specific case for a specific control that goes wrong.
Based on this fact, I concluded that a fix would not be lying in the controls code, and in fact it would not be possible for me to fix the underlying problem. This meant I had to find a decent workaround for this problem, that would fit our application.

So it was back to Google again and time to study the solutions of others, to get some inspiration for a good fix. In the end, I wouldn't mind to add the strings to the local Resources instance, as this would result in nice XAML and would work the most intuitive. The problem was that I didn't like the way people were getting to the strings in the resource file. There had to be a better way, then to actually use reflection to get each property we need.

I played around with the ResourceManager class and read some documentation, with the following code as a result:

private void LoadLocalStrings()
{
ResourceManager manager = new ResourceManager("ComboLookup.Resources.Strings", Assembly.GetExecutingAssembly());
ResourceSet resourceSet = manager.GetResourceSet(CultureInfo.CurrentUICulture, true, true);
IDictionaryEnumerator resourceEnum = resourceSet.GetEnumerator();

while (resourceEnum.MoveNext())
{
Resources.Add(resourceEnum.Key.ToString(), resourceEnum.Value);
}
}

This method is called in the constructor BEFORE InitializeComponents().

What happens is that a resource manager with the specified base name ("ComboLookup.Resources.Strings") is looked for in the assembly you specify. The base name has to be the fully qualified name for the instance of the resource class.

It should be noted that if you have resources defined in your XAML, they will override the earlier loaded resources. If you need to load other resources besides the localized strings, you should do so from code, by adding them to the Resources instance.

The XAML for using localized strings looks like this:

<data:DataGridTextColumn Binding="{Binding Brand}" Header="{StaticResource brandLabel}">
</data:DataGridTextColumn>

Note that you can now directly access a resource with the required string.
To prevent us from implementing this in every single module we have to build, we defined a base class that solves this for us. All that has changed in this method is that we specify a different assembly, trough a property that is overridden in the derived class. Same goes for the name of the resource manager.

The demo project can be downloaded below:


I hope this saves you all a lot of troubles. If you have any questions or comments, please leave them below. I always enjoy reading and answering them.

Tuesday, January 6, 2009

Troubleshooting Silverlight Isolated Storage

Today I ran into this bug in the software I'm working on. I was building a log on mechanism, that would persist a users security token to Isolated Storage. I wanted to do this, because it would enable the application to automatically log on if a valid token was still available.

I actually had this whole thing working last week, but I changed some code on the server end of things and wanted to test my sliding expiration code. So I tested the above functionality only to find out my token was no longer persisted. After extensive debugging, including writing code to watch any changes on the folder holding the Isolated Storage, I came up with nothing.

Getting frustrated, I started searching the Silverlight.net forums for anything on Isolated Storage, to see if anyone had similar issues. I then ran into a post mentioning the Save method on the IsolatedStorageSettings class. I wasn't aware of this method and reading the post, I found out I wasn't the only one. It is not actually mentioned in the video on this topic either.

It is understandable as Save is called automatically whenever a Silverlight application ends, persisting the settings just in time and giving optimal performance, however...
...if, for some reason, an exception occurs while persisting the settings, this results in the settings not being persisted. And that's not the worst. You will NOT notice it, as you will not see the exception.

In my case, I was stupid enough to make one of the classes I use to store information internal, instead of public (as it was before), breaking the serialization of this class. I didn't get any exceptions, until I started calling IsolatedStorageSettings.Save() from code.

My conclusion from all this? Call the save method at some point in your application. It can save you a lot of headaches.

Please leave any comments, questions, remarks below. I'm allways happy to read them and reply.

Sunday, January 4, 2009

Adventures while building a Silverlight Enterprise application part #3

So here we are again. Last time we looked at organizing the project and how it is important to address specifics in the teams culture. I promised some code for this episode, so a more technical subject is on the table today.

In this episode we will have a look at the intricacies of using multiple XAP files for our application. As you may remember from the first post, we expect this technique to help us reach some of the requirement goals we have, but we also identified some potential pitfalls with it.

As we implemented the basics of this we obviously ran into some issues that need solving. Below follow some topics to think about.

Silverlight will handle only one connection at any time
This may not seem obvious at first. If you haven't loaded a XAP file at runtime, you won't know this, so I figured I would give this some explanation. Whenever you load a XAP file you use the WebClient class to get the XAP file from the webserver. As this is done asynchronously, as any other communication, any other code you may invoke will simply execute will the XAP file is being downloaded. However, Silverlight will only allow you to have one connection at any time, so downloading multiple XAP files, or invoking any service calls for that mather, will throw an exception (as documented here).

As we load multiple XAP files at startup, one XAP file has to be downloaded after another. There are a couple of ways to solve this and it realy depends on the application design and requirements, but one thing is for sure: you don't want to bload this.

We chose to have an approach where one load completion leads to another load. In other words, one XAP files load is triggered by another XAP files completion event. We can do this, because one class, and one class only, is responsible for loading any XAP files and we were able to determine an order to load things in that will always work.

Another aproach you may want to consider if the above don't apply to your application (e.g. you can't determine a fixed order to load modules) is to have a queue for loading modules, where the completion of loading a module from the queue can trigger the loading of the next module, etc..

Loading UIElements from XAP files
But getting the XAP file is obviously only the first step in the process. The next step is to actually load the assemblies inside and, in our case at least, get a UIElement from one of these assemblies. To achieve this, we wrote a XapHelper class, that contains a static method to assist in the loading. The code looks like this:

public class XapHelper
{
private const string AppManifestFileName = "AppManifest.xaml";
private const string AssemblySourceAttributeName = "Source";
private const string ApplicationBinaryContentTypeName = "application/binary";

internal static UIElement LoadUIElementFromXap(Stream xapStream, string assemblyName, string className)
{
string applicationManifest = ReadApplicationManifest(xapStream);

XElement deploymentElement = XDocument.Parse(applicationManifest).Root;
IEnumerable<XElement> deploymentParts = from assemblyParts in deploymentElement.Elements().Elements()
select assemblyParts;

Assembly assembly = LoadAssemblies(xapStream, assemblyName, deploymentParts);

UIElement element = assembly.CreateInstance(className) as UIElement;
return element;
}

private static Assembly LoadAssemblies(Stream xapStream, string assemblyName, IEnumerable<XElement> deploymentParts)
{
Assembly assembly = null;
foreach (XElement assemblyPartElement in deploymentParts)
{
string name = assemblyPartElement.Attribute(AssemblySourceAttributeName).Value;

AssemblyPart assemblyPart = new AssemblyPart();

StreamResourceInfo assemblyResourceInfo = new StreamResourceInfo(xapStream, ApplicationBinaryContentTypeName);
Uri assemblyUri = new Uri(name, UriKind.Relative);
StreamResourceInfo streamInfo = Application.GetResourceStream(assemblyResourceInfo, assemblyUri);

if (name == assemblyName)
{
assembly = assemblyPart.Load(streamInfo.Stream);
}
else
{
assemblyPart.Load(streamInfo.Stream);
}
}
return assembly;
}

private static string ReadApplicationManifest(Stream xapStream)
{
StreamResourceInfo manifestResourceInfo = new StreamResourceInfo(xapStream, null);

Uri appManifestUri = new Uri(AppManifestFileName, UriKind.Relative);
StreamResourceInfo applicationResourceStream = Application.GetResourceStream(manifestResourceInfo, appManifestUri);
Stream resourceStream = applicationResourceStream.Stream;
StreamReader streamReader = new StreamReader(resourceStream);
string applicationManifest = streamReader.ReadToEnd();

return applicationManifest;
}
}

As you can see, the main method here is LoadUIElementFromXap and you have to provide it with a stream that contains the XAP file. This stream would be the result of loading it trough the WebClient class. The second parameter is the name of the assembly to load the UIElement from and the third paremeter is the classname for the UIElement.

Also you may have noticed that the code is a little more verbose than some of the samples online. This is done to improve readability and maintainability of the code.

Identify XAP file split-ups
Another obvious question you will run into when using this aproach is, how will I split up my XAP files?

One way to look at it is to have a good look at your general screen design. What parts are always, or at least usually, the same? What parts change a lot?

Another important factor is size. After all, it all started out because of performance. So ask yourself, what parts of the interface are likely to become large and are not all needed at the same time?

Whatever rules you apply to this, one fact is very important. You should identify responsibilities that you need to host in the XAP files. What I mean by that is, you need to make sure you don't split up code that handles a single responsibility, breaking your OO design. Posible subjects for this are:

- Security
- Loading XAP files
- Data connections (altough this one is not likely)
- User settings

And obviously there could be many more, depending on the application your building.

In our case, loading XAP files and security were assigned to the outer XAP file as a responsibility. As we choose to have some navigation assigned to another XAP file, that resulted in loading the first, we created an interface, called ILoadModules, that identifies UserControls that want to load XAP files and supply the main XAP file with a delegate that it can set, to provide a method of doing so.

As I promised dsoltesz earlier I've uploaded a sample project.


I hope you liked the more technical side of this artice and I'm happy to have actually squezed in some code ;-). Please let me know if you have any questions, comments, etc..