Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Integrate HSS Interlink with Microsoft LightSwitch

0.00/5 (No votes)
18 Nov 2011 1  
Integrating the HSS Interlink UploadFileDialog feature with Microsoft’s application platform, LightSwitch for Visual Studio.

Introduction


In this post, I will briefly review integrating the HSS Interlink UploadFileDialog feature with Microsoft’s application platform, LightSwitch for Visual Studio.


I must admit this is my first time using LightSwitch, so if anyone has a better idea, please share but after an hour or so of playing around with a fresh install of LightSwitch I was able to get HSS Interlink up and running.


For basic HSS Interlink implementation, you should read this first: HSS Interlink – Quickstart.


For the original blog post, you can read it here.


Background


The first hurdle was figuring out the Dispatcher processing in LightSwitch. Apparently LightSwitch button event handlers run inside a custom UI Dispatcher. So to create a new instance of the Upload dialog, it had to be created on the main Dispatcher. That was easy enough using the Deployment Dispatcher. But in order for the FileDialog to work, it has to be called from a user initiated event, which all user initiated events in LightSwitch run in this custom UI Dispatcher. So we call the Show method from that dispatcher. I was not able to get the BrowseAndShow method to work since the creation was being done on the main thread, so the only option is the Show method.


On the server side, it was a little tricky figuring out how LightSwitch generated the xap package and where the Web App was running from. But after digging around in the solution folder, I discovered the ServerGenerated folder and in there is the source web config file. From there, I was able to integrate the required web config changes.


Note, I do not cover LightSwitch basics such as creating a button, etc., I assume you’re already familiar with LightSwitch and how to access the client and server projects and add/remove references.


Using the Code


Starting with the Client Project, do the following:


Note: This assumes you’re running as a Web application. If you’re running OOB, you will have to specify the absolute URI back to the web server.



  1. You have to add a reference to the HSS.Interlink.dll
  2. You have to add a reference to System.Windows.Controls.dll
  3. LightSwitch custom dispatcher hack:
    C#
    UploadFileDialog d;
    
    partial void UploadFile_Execute()
    {
        System.Windows.Deployment.Current.Dispatcher.BeginInvoke(() =>
        {
            d = new UploadFileDialog();
            d.AllowNewUpload = false;
            d.MaxFileSizeKB = int.MaxValue;
            d.AutoUpload = true;
            d.AllowFileOverwrite = true;
            d.Background = new System.Windows.Media.SolidColorBrush(Colors.Gray);
            d.Closed += new EventHandler(d_Closed);
            Microsoft.LightSwitch.Threading.Dispatchers.Current.BeginInvoke(() =>
            {
                d.Show();
            });
        });
    }
    
    void d_Closed(object sender, EventArgs e)
    {
        d.Closed -= new EventHandler(d_Closed);
        d = null;
        this.ShowMessageBox("Upload Dialog Closed.");
    }

    Then for the Server Project, do the following:


    • Add a reference to the HSS.Interlink.Web DLL

    • Implement your UploadHandler in the server project (I have included below)

    • Find your web.config file. Mine was here (..\Application1\Application1\ServerGenerated) and add the appropriate entries. I’ve included examples below, but you will have to modify to reference your application.


Note: After you make changes to your web config and server, you will have to do a complete Compile/Rebuild of the Solution.


XML
<!-- App Settings -->
<add key="UploadHandler" value="LightSwitchApplication.UploadHandler, Application.Server"/>

<!-- httpHandlers -->
<add verb="GET,POST" path="FileDownload.ashx" type="HSS.Interlink.Web.FileDownload, HSS.Interlink.Web" />
<add verb="GET,POST" path="FileUpload.ashx" type="HSS.Interlink.Web.FileUpload, HSS.Interlink.Web" />

C#
// Server side File Upload Handler
namespace LightSwitchApplication
{
 #region Using Directives
 using System.IO;
 using HSS.Interlink.Web;
 #endregion

 #region UploadHandler
 /// <summary>
 /// Simple Upload File Handler implementation.
 /// </summary>
 public class UploadHandler : HSS.Interlink.Web.BaseUploadHandler
 {
  /// <summary>
  /// The Folder where the uploaded files are stored.
  /// </summary>
  public static string FileStoreFolder = @"Interlink\Uploads";
  
  // If you support retries
  //string retryKey;
  
  // <summary>
  // Constructor
  // </summary>
  public UploadHandler()
  {
   //
   // Uncomment the following line to turn off purging of temp files.
   //
   // NOTE:
   // The default value for purging is 5 minutes.
   // If your uploads take longer than 5 minutes
   // you WILL have to modify this to be longer
   // than your anticipated longest individual
   // file upload duration.
   //
   //this.PurgeInterval = 0;
  }

  string GetFilePath()
  {
   return Path.Combine(this.GetFolder(FileStoreFolder), this.FileName);
  }

  #region BaseUploadHandler Members
  public override bool CheckFileExists()
  {
   //Debug.WriteLine("CheckFileExists...");
   // Take some action based upon the metadata.
   //Debug.WriteLine("Metadata: " + this.Metadata);
   string file = GetFilePath();
   return File.Exists(file);
   // If you support overwriting files, do so in CreateNewFile.
  }
  public override Responses CreateNewFile()
  {
   #region Test Retry (see AppendToFile)
   // If you support for retries
   //this.retryKey = this.Query.JobId + this.FileName + "retries";
   //this.Context.Cache.Add(retryKey, 0, null, DateTime.Now.AddMinutes(60), 
   //     Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
   #endregion
   // Take some action based upon the metadata.
   //Debug.WriteLine("Metadata: " + this.Metadata);
   string file = this.GetFilePath();
   try
   {
    if (File.Exists(file))// If you support overwriting files, do so here.
     File.Delete(file);
   }
   catch { }
   File.Create(file).Close();
   return HSS.Interlink.Web.Responses.Success;
  }
  public override Responses AppendToFile(byte[] buffer)
  {
   //System.Threading.Thread.Sleep(1200);
   //Debug.WriteLine("Appending...");
   // Take some action based upon the metadata.
   //Debug.WriteLine("Metadata: " + this.Metadata);
   #region Test exception
   //throw new Exception("test");
   #endregion
   #region Test Retry (see CreateNewFile)
   // If you support for retries
   // If not able to persist chunk, request a Retry...
   //if (someTest == Failed)
   //{
   //    int retries = 0;
   //    this.retryKey = this.Query.JobId + this.FileName + "retries";
   //    object objRetries = this.Context.Cache[retryKey];
   //    if (null == objRetries)
   //        retries = 1;
   //    else
   //        retries = (int)objRetries + 1;
   //    this.Context.Cache[retryKey] = retries;
   //    if (retries > 3)
   //        return HSS.Interlink.Web.Responses.FatalError;
   //    return HSS.Interlink.Web.Responses.AppendFileRetry;
   //}
   #endregion
   string file = this.GetFilePath();
   using (FileStream fs = File.Open(file, FileMode.Append))
    fs.Write(buffer, 0, buffer.Length);
   return HSS.Interlink.Web.Responses.Success;
  }
  public override void CancelUpload()
  {
   string file = this.GetFilePath();
   try
   {
    if (File.Exists(file))
     File.Delete(file);
   }
   catch { }
  }
  public override string UploadComplete()
  {
   string file = GetFilePath();
   // Move to final destination.
   //File.Copy(file, finalFile);
   // Delete
   //File.Delete(file);
   //Debug.WriteLine("Completed...");
   return "Hey we made it!"; // Optional string to return to caller.
  }
  public override bool IsAuthorized()
  {
   //Debug.WriteLine("IsAuthorized...");
   #region Test Authorization
   //if (this.Context.User.Identity.IsAuthenticated)
   //{
   //    if (this.Context.User.IsInRole("requiredRole"))
   //        return true;
   //}
   //return false;
   #endregion
   return true;
  }
  public override void OnError(System.Exception ex)
  {
   // Log the error...
   // Delete the file...
   string file = this.GetFilePath();
   try
   {
    if (File.Exists(file))
     File.Delete(file);
   }
   catch { }
  }
  #endregion
 }
 #endregion
}

Build and run and it should work.


You can test this in an existing project or you can download the test solution at the top of this article.


Points of Interest


So learning how to manipulate the dispatchers in LightSwitch proved to be key to this exercise. But once that was resolved, everything worked as normal.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here