Showing posts with label Microsoft Silverlight. Show all posts
Showing posts with label Microsoft Silverlight. Show all posts

Friday, January 22, 2010

Porting a framework to Silverlight

.. a journey getting to the contents

The last time I have been getting familiar with Silverlight. As a .NET developer with a big focus on the web I am interested in the possibilities of this plugin. (Eventhough, I also keep a close eye on the interesting stuff around HTML5.)

The Microsoft Silverlight stack, vectorization...Image via Wikipedia

I always wanted to add a little more to web applications and sites that are maybe possible using clever Javascript, but are probably easier to achieve using a plugin like Flash. Being quite fluent in .NET and C# and reasonably agile in Javascript I didn't want to learn yet another language and different IDE. So, when Silverlight came on stage I was immediatelly interested. I could be using the familiar Visual Studio, familiar C#, familiar (though slightly limited implementation of) .NET framework to do some exciting new stuff. XAML came in as a new aspect, but that was already part of the WPF stuff, so not completely new. Expression Blend to create all sorts of horrible interfaces and well, the sky is not even the limit anymore.

After some useless experimentation (extending "Hello world!") I decided to stop right there and drop everything and make a good start right from the beginning. Fundamentals first.

A framework

Within our company we use a clever framework that implements the MVC pattern. We use the same framework for Windows Forms application and ASP.NET applications. By completely separating the View logic from the Model and Controller (as it should be done) we can use the same Model and Controller logic in both types of applications.

The framework has a Mediator and all functionality is handled through that using Commands. All View controls are registered with the Mediator and are signalled to update the view when "things" change in the Model. The controls then update themselves and show or hide bits of themselves.

At first there was a bit of getting used to this way of programming, but now it strikes me again and again how little code is needed to implement logic.

All logic is handled in commands. When a button is clicked the Mediator is called to execute a command with some optional parameters. These Commands are implemented in various classes and are decorated with a Command attribute and implement an ICommand interface. The ICommand interface makes that the methods that a Command needs are implemented. The Command also has access the Model through ApplicationData object. I made a SilverlightApplicationData type with some small changes to the WebApplicationData type. For instance in the WebApplicationData we grab the buildnumber from the Web.Config and there is no such thing in Silverlight, so it is dropped for this first implementation.

Anyway, just add the attribute and we are good to go.

[Command("COMMANDNAME")]

The code the ICommand interface has among others a Do() method that can be called by the Mediator. A typical Button Click EventHandler is really simple.

Mediator.Execute("COMMANDNAME", "string parameter");

Or ..

Mediator.Execute("COMMANDNAME", "string parameter", intParameter, someOtherClassParameter);

Every parameter after the command name is passed to the actual Command as argument for its constructor.

The Mediator then executes the Command. However, the framework doesn't know which Commands will be implemented. Neither do I. What is needed is a Dictionary with all available Commands.

Dictionary<string, Command> commands

How to can the framework know which commands there are? Do we need to maintain a list in a config file? A bit nasty really. But the backbone of .NET Framework comes to the rescue: Relfection.

Reflection

Using reflection we can iterate all application assemblies and scan all types and make a Dictionary with all types that have the Command attribute. These can then be stored in the Dictionary.

Sounds easy, but is it?

Windows and web is simple

For Windows and Web applications iterating the assemblies is quite simple. We just look at the content of the Bin folder and load all *.dll (and *.exe) files. Then using reflection we scan all Types for the Command attribute. When found we add them to the Dictionary.

            foreach (string file in Directory.GetFiles( path, searchPattern, SearchOption.AllDirectories ))
            {
                Assembly assembly = Assembly.LoadFrom( file );
                Type[] types = assembly.GetTypes();
                foreach (Type type in types)
                {
                    object[] attr = type.GetCustomAttributes(typeof(CommandAttribute), false);
                    if (attr.Length == 1)
                    {
                        CommandAttribute attribute = (CommandAttribute)attr[0];
                        Command command = (Command)assembly.CreateInstance( type.FullName );
                        commands.Add( attribute.CommandName, command );
                    }
                }
            }

This is all done in a static CommandManager so we only need to scan the files once.

Silverlight is slightly different

With Silverlight the situation is a bit more complicated. There is no Bin folder that can be scanned. There is a ClientBin folder, but that's on the web server and even then the files are inside the Xap file!

Inside that renamed Zip file we find the assemblies and AppManifest.xaml file in which these files are listed. Well how do we get there?

Doing quite a bit of Googling I finally got on the right track. The above code sample needs quite a bit of rework. Whe need to do a number things:

  1. Open the Xap file
  2. Read the AppManifest.xaml.
  3. Parse the names of the assemblies
  4. Load the assemblies from the Xap file

Eventhough the Silverlight application is downloaded by the browser to the client computer we can not really get at the Xap file directly. That's the sandboxing security model working against us. So we need a clever workaround.

Luckily there is a way to get there. We can download the file to Local Storage. Since we are on the web this happens asynchronously. Using the OpenReadCompletedEventHandler we can continue the process.

Note that we also check for the existence of the Xap file in LocalStorage, just to prevent repeated downloads when you refresh the web page.

         Uri xapUri = Application.Current.Host.Source;
         string[] parts = xapUri.AbsolutePath.Split('/');
         xapFile = parts[parts.Length - 1];  // the filename is the last part of the path

         using (IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication())
         {
            // check if the file is available
            if (!store.FileExists(xapFile))
            {
               // when not available download it
               WebClient webClient = new WebClient();
               webClient.OpenReadCompleted += new OpenReadCompletedEventHandler(WebClientOpenReadCompleted);
               webClient.OpenReadAsync(new Uri(xapFile, UriKind.Relative));
            }
            else
            {
               LoadAssembliesFromIsolatedStorage();
            }
         }

When WebClient has completed download the stream is copied to IsolatedStorage

      private static void WebClientOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
      {
         using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
         {
            IsolatedStorageFileStream fileStream = storageFile.CreateFile(xapFile);
            WriteStream(e.Result, fileStream);
            fileStream.Close();
         }
         LoadAssembliesFromIsolatedStorage();
      }

Now the assembly processing can begin.

      private static void LoadAssembliesFromIsolatedStorage()
      {
         using (IsolatedStorageFile storageFile = IsolatedStorageFile.GetUserStoreForApplication())
         {
            IsolatedStorageFileStream fileStream = storageFile.OpenFile(xapFile, FileMode.Open, FileAccess.Read);

            // parse the AppManifest.xaml file
            Stream manifestStream = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri("AppManifest.xaml", UriKind.Relative)).Stream;
            string appManifest = new StreamReader(manifestStream).ReadToEnd();

            XElement deploymentRoot = XDocument.Parse(appManifest).Root;
            List deploymentParts = (from assemblyParts in deploymentRoot.Elements().Elements()
                                              select assemblyParts).ToList();

            // now load assemblies one by one
            foreach (XElement xElement in deploymentParts)
            {
               string source = xElement.Attribute("Source").Value;
               AssemblyPart asmPart = new AssemblyPart();
               fileStream = storageFile.OpenFile(xapFile, FileMode.Open, FileAccess.Read);
               StreamResourceInfo streamInfo = Application.GetResourceStream(new StreamResourceInfo(fileStream, "application/binary"), new Uri(source, UriKind.Relative));

               Assembly assembly = asmPart.Load(streamInfo.Stream);
               // from here the code is unchanged
               Type[] types = assembly.GetTypes();
               foreach (Type type in types)
               {
                  object[] attr = type.GetCustomAttributes(typeof(CommandAttribute), false);
                  if (attr.Length == 1)
                  {
                     CommandAttribute attribute = (CommandAttribute)attr[0];
                     Command command = (Command)assembly.CreateInstance(type.FullName);
                     commands.Add(attribute.CommandName, command);
                  }
               }
            }
         }
      }

Well, it took quite some googling around and advice from a friend to get this working, but in the end the steps are quite easy to understand.

Almost there ..

So now we have everything we need. Almost that is.

As I mentioned earlier Silverlight has a slightly limited implementation of .NET framework in the sense that not all namespaces are completely implemented in the same way. And that threw up another hurdle to take.

To create an instance of Command we use an overload of the CreateInstance method in which we can pass the parameters for the command in the args parameter.

ICommand command = (ICommand)assembly.CreateInstance( commandType.FullName, false, BindingFlags.Default, null, args, CultureInfo.InvariantCulture, null );

Unfortunately Silverlight does not have this overload. We cannot pass any parameters to the instance using CreateInstance. In effect only the default constructor is called. Why the overload is omitted in Silverlight strikes me as odd.

Yet, more research was needed to solve this problem. More Reflection was needed to find the correct constructor for the type.

         Type[] parameterTypes = new Type[args.Length];
         // Initialize a ParameterModifier with the number of parameterTypes.
         ParameterModifier parameterModifiers = new ParameterModifier(args.Length);

         for (int i = 0; i < args.Length; i++)
         {
            parameterTypes[i] = args[i].GetType();
            parameterModifiers[i] = true;
         }

         // The ParameterModifier must be passed as the single element of an array.
         ParameterModifier[] paramMods = { parameterModifiers };

         // Get the constructor that takes an integer as a parameter.
         ConstructorInfo constructorInfo = commandType.GetConstructor(BindingFlags.Instance | BindingFlags.Public, 
                                       Type.DefaultBinder, parameterTypes, paramMods);
         ICommand command = (ICommand)constructorInfo.Invoke(args);

This made it all work.

Mediator.Execute("COMMANDNAME", "string parameter");

The Mediator can now make a deep copy of the Command referenced by the name "COMMANDNAME" (using the constructor that takes string parameter) and then call that Command's Do() method to actually execute it.

A really interesting journey it was and now I can start to make something useful using this framework.

Reblog this post [with Zemanta]

Sunday, March 01, 2009

Building an application (4) ...

.. weird debugging problem

One more thing that I have encountered on my wonderful journey in building my first Silverlight application is a debugging issue.

It just not works straight out of the box in Visual Studio 2008. I know, I know, it must be me with all sorts of software loaded or what. Or the missing hotfix 98662654a. But just keeps biting me.

What's up, doc?

I start VS 2008 and make some very very clever changes or just want to try out something. So I set a breakpoint at the right line in the code and hit F5. Easy.

Lots of things happen. The application is built. Well, three applications are built: the Silverlight app, the web app and the web service. So far, so good.

I start my testing and the breakpoints are never hit. At least the IDE does not stop.

And yes, I am running in Debug mode.

What's the cure, doc?

I have found that stopping the debug session (by hitting Shift-F5 in the IDE) and the right-clicking the Web Service project and selecting Debug - Start New Instance does the trick.

Breakpoints are once more hit and they do cause the code to break at those points.

So, what's up, doc?

I honestly can see here that I have no idea. The trick above works for me and to me that is enough.

So, if you come across breakpoints never really breaking than the above trick might work for you.

Reblog this post [with Zemanta]

Friday, February 13, 2009

Building an application (3) ...

.. exchanging and serializing objects

One the interesting things I ran across while building the Trainer Tool was that I had exchange objects between different parts of the system. I have the excercise and its data in a couple of classes and it's the data that's is used in all parts of the system. I store it in my database (in an XML type field). The HttpHandler requests an excercise object through the web service and uses it to generate an image that is shown on the webpage. And so on. Simply said all the blue arrows in the diagram are used to transport an excercise object.

The excercise object

So all the different components need to have access to the defintion of the excercise object. Well, that's easy. Create a separate project, a class library, and simply set references to that from the other projects. Well, almost. It works for the Web Service and the Web Application, but not for the Silverlight project.

Why not? Well simple enough setting a reference to a project copies the compiled assembly (dll) from that project to the referring project's bin folder. And that just will not work with a Silverlight project. Simply because the it's a different type of dll.

The solution is very simple. Since both the .NET parts and the Silverlight files use the same C# (or VB.NET) code you can use the code in both projects.No, do not copy the class files from the .NET class project to the Silverlight! You will be doing all updates twice. It is quite easy to link the files from the class project. Create a folder to link the files into. And then use the context menu to Add Existing items.

In the following file dialog choose the files you need and then notice the small arrow on the add button. That produces a dropdown menu where the option to link the files is hidden.

Now, you have linked the class files. When you open one of the files through either of the projects you are in essence opening the same physical file. In the project explorer you can see the linked files with the little shortcut style arrow, which hints at that behavior. You get a warning when you try to open a file for the second time (once directly and once linked) and that makes perfect sense.

That was all

Another time some more information on how serialization poses some trickery as well.

Window shopping at Eaton's department store.Image via Wikipedia
Reblog this post [with Zemanta]

Thursday, February 12, 2009

Building an application (2) ...

.. coming full circle

In the first part of this journey I have sketched the outlines of my application. The combination of web pages, web service and Silverlight as I plan to build it.

Jumping hurdles and dodging bullets

While building and debugging I have run into numerous obstacles. Not only did Chrome give me an unexpected headache by not refreshing the Silverlight XAP file in the cache, also Visual Studio behaved weirdly during debugging sessions. At first I couldn't make any of the breakpoints work. Only after using the context menu on the web service and picking 'Debug - Start a new instance' did execution break at the breakpoints. And then after a couple of hours it failed all breakpoints completely. Restart of Visual Studio and browser did not work. A full reboot did the job.

BTW I have logged a bug with Chromium for the caching problem.

However

My Proof of Concept piece of spaghetti has now come full circle:

  1. I drag and drop some players, balls on the pitch.
  2. Enter some extra info: name of the excercise and some extra text.
  3. Save the data to the data base using the web service.
  4. The asynchronous callback adds some html to the DOM, which is an image that is generated by a special HttpHandler.
  5. The image shows up in the browser.
  6. I have a smile on my face.
Lots of work to do

en: Picture of a girl rubbing her temples.Image via Wikipedia

There is still lots of work to do:

  • a real user interface has to be designed
  • better, I need to sit down and get the complete UX designed
  • have to add the boring user authentication stuff
  • try out the concept on a real web server
  • implement some of the missing graphical pieces, like lines with arrows
  • think of good way of editing the lines
  • undo / redo ?
  • make the database complete
  • add functionality for picking existing excercises, sharing these, copying, editing etc.

Yep, there is lots to do and so little time.

A little bit more tchnical info in Part 3.

Reblog this post [with Zemanta]

Monday, January 26, 2009

Building an application ...

.. from idea to reality

As posted before I have some plans for this year. One of these plans is building a complete on-line application all by myself using interesting technology. In this first post I will tell you a bit about the architecture I am using to build it.

Let me first explain (maybe again) that I am web developer and I specialize in C#, ASP.NET, HTML and CSS. Above all I like to experiment with these and do ineteresting stuff from time to time.

With the application I am building I want to solve a problem that I experience myself. This ensures that I will have at least one satisfied costumer. First I will very briefly describe the problem I try to solve and then I will tell a bit about the architecture I have planned.

The problem to solve

When you try to build any application you must have a purpose for it and understanding the purpose is part of the solution. Also being able to relate with the owner of the problem is a big advantage. In this project that is all taken care of. I am the owner of the problem.

In my spare time I am trainer slash coach of the Ladies fieldhockey team of MHC Steenwijk. They are doing great this season and have so far won every of their ten games. This puts more pressure on me than on them as I need to give ever better training to them. I see that as an extra challenge and it gives me even more fun and satisfaction.

As part of the preparation of each training I give I need to document my training. I have to think of a subject for the training (like improve position play, penalty corners, scoring) and then I have to find excercises that support that goal. These excercises need to be drawn in a diagram. I simply have to place some pilons, players, opponents and then add some arrows showing where the players should run and pass.

This is something I usually do on paper with a pencil and I can do it in just a few minutes. But if I want to have these drawings in a digital form, then I could scan those or fire up Visio with a special stencil or go into an even bigger tool like Photoshop or Fireworks. All these tools are way too big for this and way too expensive. I want something that is simple and fast and does that what I want and maybe a little more.

Basic archtiecture

Being a web enthousiast I decided quickly that I want to build as an online tool. I looked at drawing using Javascript libraries and even studied SVG. But I let that be and thought this would be a really interesting project to build using Microsoft Silverlight.

All in all I needed a couple of components in my solution that makes it a complete, fully fledged application.

  • First there is a ASP.NET web page that holds the components.
  • One of the components is the editor with a drag and drop interface and some textboxes for inputting data like name and description of the excercise. This is done in Silverlight.
  • The Silverlight editor uses Isolated Storage for storing intermediate data on the client.
  • The Silverlight editor saves the data to the server through webservice. I have implemented an asynchronous call.
  • The webservice is the layer that gives access to the database, which will hold all excercises and, later, user data.
  • There is also a SQL Server database for storing the data.
  • Also on the page a PNG is shown as the result of the lines and symbols placed within the editor. When the excercise is saved to the database succesfully a callback function to the Silverlight editor the adds some HTML to the DOM among which is dynamically generated image.
  • The HttpHandler generates the images using the data from the database, which it retrieves through the webservice.

All these components are relatively simple. Well, except maybe the SilverLight editor. That will have all sorts of editing functionality. The image handler will just take the excercise data to generate the image. Quite a straight forward process. The database is quite simple and have only a few tables and stored procedures.

Status

At this moment I am close to having solved all the problems that are part of this solution. I can save and retrieve data, drag and drop symbols. Save to Isolated Storage. I have the HttpHandler producing some output.

Basically, I can start to fill in the gaps and then start to test in a real server and see if I can get the configuration all set up correctly. But then it just starts, there is much ore that needs to be added and there's a lot code that I need to rerfactor and clean up.

I have only just begun.

But do read on in part 2.

Reblog this post [with Zemanta]

Wednesday, January 14, 2009

A new year

.. a time to look forward

Sunrise shown in time lapse.  The motions of S...Image via Wikipedia

Now 2009 is officially on its way and it is passed the day for sending best wishes I will give a quick update on what I am upto in the coming time.

Currently I am involved in some projects at work (both insourced and outsourced) and personally I am doing a bit of a project as well. Let me tell you some things about these.

Work projects
Normal working hours
HTML syntax highlightingImage via Wikipedia

Working as a consultant I am since May last year working on a huge project for the Dutch Taxes. I was hired out to Getronics PinkRoccade, which was taken over by Capgemini. It's an interesting project. I think that's a nice way of putting it. My main activities are in programming parts of the Intranet site using things like C#, ASP.NET, WCF, HTML, CSS, SQL Server, SharePoint MOSS. All in a nice Team System environment on a virtual machine.

The funny thing is that my first ever job orientation I did was with Capgemini (I declined, finding it did not fit me). The first ever real job interview was at the Dutch Taxes. I completely flunked that as I had no idea what a job interview was. There were seven (!) people sitting across the table and that completely got me confused.

Other moments of the day

That project is not enough apparently and we are working on some in-house side projects. One of those is a Saas application we are devleoping. It's an online version of Microsoft team Foundation Server. Currently we are busy setting up the service. The accompanying site is getting close to full launch. The actual service is (still) in alpha testing and we expect soon to start with the first beta tests. All in all really exciting.

Coming soon

If that still does not seem enough there already running plans for a next in-house project. This is at the moment still hush-hush. But we intend to outsource some of the coding and also make use of our own Online TFS service. Can be really exciting as well.

Is there still time left?

Well, hardly any time left. But time enough to squeeze in a little project of myself. I am writing a small Silverlight application. To learn that environment, but also because I am need a tool to draw the excercises I use in my field hockey trainings. Usually I just jots some lines and arrows on piece of paper and that's it. But I want to go one step further and have something readable for others.

I have looked around the web and found some tools / sites. These are either big downloads and cost a little or a lot of money. But they all lack some of the things I want. I want to be able to share my excercises and let others use them as inspiration to create even better excercises. Very Web 2.0, very social app.

So, I am trying to set all these things up and have chosen Silverlight as the rich UI element for drawing the excercises.

Enough to keep me busy?

It seems I have a family as well and a hockey team and a dog and a cat.

Better get to work and than quick to get back again and be socially responsible.

Reblog this post [with Zemanta]

Monday, December 29, 2008

The end of another year

.. and time to look back

With 2008 drawing to close I sit here behind my laptop doing some fixes on code broken by others who celebrate the year's end somewhere else with probably much better coffee. Time to blame myself for not doing so, I guess.

It's difficult to completely devote myself to this so I let my mind go wandering, where it will go. Fixing a hole where the rain gets in, keeps my mind from wandering, where it will go.

I am not fixing my roof, but writing a blog post. Works equally good.

Indiana Population Density MapImage via Wikipedia
What happened in 2008?

A lot of stuff happened in 2008. I started the year with my brother and sister in law over in Bloomington, Indiana. An interesting three weeks in a completely different country. The ebst way to know more about your own country and your own habits. About the things you take for granted.

Map of France highlighting the Region of BrittanyImage via Wikipedia

This summer we spent our holiday in France. We visited Bretagne and stayed near the beach on a nice camp site. It was good. Weather was reasonable. Had a good time.

Work related stuff in 2008

I continu to work as a consultant and have done three jobs with totally different outcome. The first, a three month contract that never really got started since the project I was hired to participate in, only had a shifting start and a fixed end date. Then the contract was not extended. Don't know what happened to the project.

Then I got parachuted into a project that was originally taken on by someone from another office for just a couple of days. I proofed to be a disaster area. It was immediately clear that was already there was not state of the art, nor was it doen according to the book. Any book. There was no plan, no design, no clear goal even. No planning. No coordination. I praise myself lucky to have stated so on the very first day. Told them that if there was enough time then we should start from scratch.

Looking back at that project I know that in the end we (I brought in a colleague on the prject) could and should have started from scratch. It would have delivered more and a better product. The only thing I hold against myself is that I did not insist hard enough on a design. There was NO DESIGN. Completely and utterly absolutely nothing. I still do not understand how we worked for all those weeks and why we worked as hard as we did.

But I am happy we just quit the project in time.

Then I got into my present project. A huge project. We are working to build a new system for the Taxes. Several teams are working hard to create the various parts of the system. Interesting and sometimes amusing to see that small projects can have small problems and that big projects have their challenges as well.

And there is more

Apart from this projects that I did (and am doing) on site at the customer. There is also a big ongoing internal project that is slowly getting ready to go really live. An full blown online version of Microsoft Team Foundation Server: Online TFS. Still, only in alpha testing, but oh so close to the beta phase. I can hardly wait for that.

Also I am currently working on my first Silverlight application. It will hopefully be of help with my other time consuming hobby.

Going for a promotion

In my spare time I am the proud trainer and coach of the MHC Steenwijk Ladies team. We are on a steam roller currently have beaten ALL OF THE OTHER TEAMS in the field hockey compettion. 30 points out of a possible 30 points: a totally 100% score! Now in the winter break we are preparing for the second part of the season with still 8 games to go. With 7 wins we secure the title. Maybe less if some of the teams lose points along the way.

My Silverlight application should help me document my training excercises. I plan on releasing it some time in 2009 and then I will make it available to just about everyone. I will keep you posted.

Privately

My oldest daughter has moved to a new school this year. My old school. Weird feeling. It seems like only yesterday when I was attending that school. Well, at lot has changed.

My other daughter was champion with her football team ('soccer' for the suckers). My son has probaly beaten you at Mario Kart.

Finally, my wife is going strong and moved to another job and she is hopefully heading the right direction in 2009.

What about 2009?

In the past I have not been very good at predictions. Still, I have some hopes for next year.

My high hopes and wishes for next year:

  • to bring Online TFS out of aplha into beta and into full swing production
  • to start another exciting internal prject
  • to make it to promotion with the Ladies
  • to be champion with the Ladies
  • for my wife, to find joy and satisfaction in her enw job
  • for my kids, to be succesful and happy at school and at sports
  • for my parents, to have a less eventfull year
  • to finish my Silverlight application
  • to have differenet hopes and wishes for 2010

I wish YOU all the best in 2009!

Image representing Microsoft Silverlight as de...Image via CrunchBase
Reblog this post [with Zemanta]