Jim @ imason

Internet Architect by day, environmentalist by night: Jim Schwartz @ imason.

  • Jim @ imason

    Silverlight in Desktop Applications

    • 2 Comments

    Earlier this year I headed up a development team to build 2 Silverlight applications for The Weather Network. The first application to be released a few weeks ago is “WeatherEye Golf” (press release) which provides weather information for over 17,000 golf courses in Canada and the U.S. The second app that was just released last week is called “TrafficEye” (press release) which provides up-to-the-minute traffic information for the Greater Toronto Area (With plans to expand out to other areas). It includes traffic flow, highway conditions, traffic incidents, and traffic cameras. You can save up to 10 of your favourite highway cameras (If you download it now, you will be entered to win 1 of 2 Xbox 360 Game Consoles!!).

    These applications were quite unique because they needed to be downloadable and run on the desktop. Silverlight has several benefits over the other options we had explored. First of all, Silverlight runs as a web application, so it’s very easy to update in the future; you don’t need to push out updates to the desktop, and the user doesn’t need to re-install anything.  One of the issues with the flagship WeatherEye product (Which is purely a desktop application) is that they need to push out updates to users which can be very time consuming since there are approximately 2 million active users of the WeatherEye product. With Silverlight, the IT Staff simply needs to update the Web Application and the next time the user runs the app, they will have the latest version.

    Another benefit of Silverlight is the fact that you can easily port the application over to any web site, by simply adding an <object> tag to the HTML. Whether it’s a PHP page, ASPX, JSP, HTML, you can display the Silverlight application anywhere.

    The third benefit of Silverlight is the platform independence. We have a Mac version of the TrafficEye application that we are planning to release in the near future. It’s pretty neat to see a Microsoft solution running on a Mac desktop.

    To display the Silverlight application on the desktop we built a Visual Basic 6 application that displays a browser frame, (while in Mac we are using a Cocoa application developed using the XCode tools). The desktop shim is very basic and allows us to consolidate the application functionality in Silverlight. Silverlight uses Isolated Storage to persist user settings. We chose VB6 so that it will run on various desktop configurations without requiring the .NET framework, and also to keep the installation as small as possible.

    Overall I’m happy with the result of the applications. There are a couple kinks on certain desktop configurations, but overall the response from the public has been positive so far.

    TrafficEye WeatherEye Golf

  • Jim @ imason

    Rehydrating a State Machine Workflow

    • 3 Comments

    At first glance, Windows Workflow does a good job of persisting workflows to the database for long-running State Machine Workflows.

    However, what happens when you update your workflow assembly? Windows Workflow will try to retrieve the workflow from the SQL Persistence store and de-serialize the object, but it will throw an exception (You’ll see a SerializationException or IndexOutOfRangeException).

    There are different ways to handle this situation. The first (and most obvious way) is to set versions on your DLLs so that the workflow will de-serialize into a previous version of a workflow and continue running in the older version. But what if the change you made to the workflow fixes an important bug in the previous version? In this case, you may want  your previously persisted workflows to use the new version of the code.

    A few quick Google searches will lead you to a few different options in handling this situation:

    • Using an assembly resolver or using the “AppliesTo” attribute [1]
    • Dynamic Workflows [2]
    • Breaking up into smaller workflows [3]

    None of these options are particularly appealing to me, so I had to find a better way to handle updates to the workflow code but still allow my long-running workflows to operate.

    My “outside the box” solution: Workflow Rehydration

    To achieve Workflow Rehydration, I’m keeping track of the current state in a SQL database and if the current workflow can’t be de-serialized (because the workflow has been updated), I instantiate a new workflow and I set the state to the state it was previously in.

    The obvious concern that comes up using this approach is “how do I avoid executing the code inside my StateInitializationActivity?

    To get around this issue, I’m passing in a boolean parameter into my State Machine workflow that indicates whether or not the workflow is being rehydrated. I then use an IfElseActivity to execute my State Initialization code only if the workflow is not being rehydrated.

    image

    The end result is that the workflow goes back into its previous state, but it’s now running inside the new updated workflow code. You might call this a “Utopia State” (Apologies for the lame pun).

    The end user has no idea that the workflow has gone through this transformation from an old version of the workflow code to the new version; and it only took a little bit of code along with some IF conditions.

    References: 

    [1] http://msdn.microsoft.com/en-us/library/aa349375(VS.85).aspx

    [2] http://community.bartdesmet.net/blogs/bart/archive/2006/08/28/4322.aspx

    [3] http://www.sitechno.com/Blog/WorkflowVersioningOfLongRunningProcessesSucksHereIsMyTakeOnIt.aspx

  • Jim @ imason

    NAnt, SharePoint and Production Deployments

    • 3 Comments

    On my current SharePoint/InfoPath project, we’re using NAnt to deploy absolutely everything. NAnt creates SharePoint pages, imports web parts to pages, activates SharePoint features, deploys assemblies, creates SharePoint lists, creates/updates SQL databases (via DBDeploy), packages and deploys InfoPath forms, copies XSLT/XML/ASPX files, and much much more.

    I always boast about how when a new developer comes on the project, he/she can have a fully operational SharePoint development environment within minutes. This is an important achievement, as most SharePoint Developers know it can be painful to automate deployments to SharePoint sites.

    This works great for a Development environment, but what happens when you need to deploy to Production? Some companies don’t allow NAnt to be executed directly in Production, so you’ll need to setup your NAnt build files to execute on a build server to prepare for a Production deployment.

    To achieve this, I went back into my NAnt build file and updated my NAnt targets to allow for the “preparation” of a deployment rather than actually performing the deployment. This provides us the ability to run NAnt on a build server in order to package everything for an easy automated deployment in Production (without NAnt).

    I’m leveraging Windows Installer XML (WiX) in order to package the deployment files into MSI packages (In a future post I’ll get into more detail about using WiX MSI’s for SharePoint deployments). For SharePoint feature installation/activations and InfoPath form deployments I’m generating a batch file from NAnt that gets packaged into the MSI and executed when the MSI is installed on the server.

    First we prepare the batch files – this will create 3 new empty batch files with a line “ECHO OFF” inside them:

       1: <target name="PrepareBatchFiles"> 
       2:     <echo file ="${featuresDeployment.cmd}" append="true" message="ECHO OFF" /> 
       3:     <echo file ="${formsDeployment.cmd}" append="true" message="ECHO OFF" /> 
       4:     <echo file ="${dataConnectionsDeployment.cmd}" append="true" message="ECHO OFF" /> 
       5: </target>

    Next, we append STSADM calls to the batch files – anytime we call STSADM from NAnt, we will add a row into the batch file. Here’s an example when we’re calling the “UploadForm” NAnt target:

       1: <target name="UploadFormTemplate" description="Uploads an InfoPath Form">
       2:     <choose>
       3:         <when test="${prepareDeployment=='true'}">
       4:             <echo file="${formDeploymentBatchFile}" append="true" message="echo Attempting to upload form template '${formName}.xsn'" />
       5:             <echo file="${formDeploymentBatchFile}" append="true" message="${stsadm.exe} -o uploadformtemplate -filename &quot;${deploymentFolder}\Forms\${formName}.xsn&quot;" />
       6:         </when>
       7:         <otherwise>
       8:             <exec program="${stsadm.exe}">
       9:                 <arg line="-o uploadformtemplate" />
      10:                 <arg line="-filename &quot;${publishedFormsFolder}${formName}.xsn&quot;" />
      11:             </exec>
      12:         </otherwise>
      13:     </choose>
      14: </target>

    You can see from the NAnt target above that  it checks whether we’re “Preparing” a deployment or if we’re actually deploying. If we’re preparing the deployment, it will generate batch files and copy files to a deployment folder. I’ve added the “choose –> while” condition into each NAnt target so that I can prepare my deployment files for the MSI.

    The generated batch file will look something like this:

       1: SET STSADM=C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN\STSADM.exe
       2: ECHO OFF
       3: "%STSADM%" -o deactivateformtemplate -url http://sharepoint-serv -filename "C:\MyForms\MyInfoPathForm.xsn"
       4: "%STSADM%" -o removeformtemplate -filename "C:\MyForms\MyInfoPathForm.xsn"
       5: "%STSADM%" -o execadmsvcjobs
       6: ECHO Attempting to upload form template 'MyInfoPathForm.xsn'
       7: "%STSADM%" -o uploadformtemplate -filename "C:\MyForms\MyInfoPathForm.xsn"
       8: "%STSADM%" -o execadmsvcjobs
       9: "%STSADM%" -o activateformtemplate -url http://sharepoint-serv -filename "C:\MyForms\MyInfoPathForm.xsn"

    Now when I add a new form to be deployed, it will be automatically added to the batch file for the Production deployment. The end result is that I can run my NAnt scripts on a development environment to actually deploy my SharePoint components, or I can run the same batch scripts on a Production server via an MSI package.

  • Jim @ imason

    Isolated Storage in Silverlight 2 Beta 2

    • 2 Comments

    In Silverlight 2 Beta 1, storing user settings in IsolatedStorage was almost as much of a pain as storing user settings in Vista Gadgets (Except you can write .NET code to stream the data to file instead of using JavaScript).

    With the recent release of Silverlight 2 Beta 2, storing data in IsolatedStorage is as easy as storing and retrieving values from a web.config.

    To store business objects into IsolatedStorage, I would recommend creating a Class in your Silverlight project to hold all of the user settings. You also need to set the “DataContract” attribute on any classes that you want to persist to IsolatedStorage as well as the “DataMember” attribute for the properties you’d like to persist. This will allow the class to be serialized into IsolatedStorage.

    Here is an example of a simple entity class with some data that I’d like to persist:

    using System.Runtime.Serialization;

     

    namespace My.Silverlight.Application

    {

        [DataContract]

        public class City

        {

            private string _cityName;

     

            [DataMember]

            public string CityName

            {

                get { return _cityName; }

                set { _cityName = value; }

            }

        }

    }

     

    Next, I’ll store this City object in my “UserSettings” object along with the Silverlight user’s e-mail address.

    using System;

    using System.Collections.Generic;

     

    namespace My.Silverlight.Application

    {

        public class UserSettings

        {

            private City _citySetting;

            private string _userEmailAddress;

        }

    }

     

    Lastly, I’ll clear the IsolatedStorage application settings, then add my UserSettings object and save to IsolatedStorage ApplicationSettings:

    IsolatedStorageSettings.ApplicationSettings.Clear();

    IsolatedStorageSettings.ApplicationSettings.Add("UserSettings", settings);

     

    That’s it!

    You could alternatively write string values into IsolatedStorage if you only need to store simple string values. The above examples shows you how to store business objects directly to IsolatedStorage. Keep posted for more articles on developing on Silverlight 2 Beta 2.

  • Jim @ imason

    Advanced InfoPath Development with SharePoint

    • 1 Comments

    Thanks to everyone who made it out to our Advanced InfoPath Development session yesterday at the Toronto SharePoint Camp. We had quite a good turnout; so I’m glad to see there are lots of other people out there using browser-based InfoPath forms using Forms Services on SharePoint.

    InfoPath makes it easy to quickly develop forms, but it doesn’t come without its limitations. It’s very heavy on JavaScript, thus performance isn’t great when you have a lot of fields and rules. It doesn’t support multilingual, and it’s not very good at field validation. In this session we showed the audience how to get around these limitations by writing some simple C# code.

    I’ve posted the PowerPoint slides as well as the source code for the InfoPath form, the Web Service, the Web Part, and the NAnt XML build definition.

    If you’re interested in learning more about NAnt, send me an e-mail because I’m thinking about organizing a NAnt lunch and learn session at the imason office open to all Developers. We’re located in downtown Toronto on Adelaide Street near Peter St.

    Download the source code (SharePointCamp.zip), and PowerPoint slides (SharePointCamp-2009.pptx) here.

    image

    image

Page 1 of 5 (22 items) 12345