Click here to Skip to main content
Licence CPOL
First Posted 18 Nov 2011
Views 7,251
Downloads 0
Bookmarked 2 times

Integrate HSS Interlink with Microsoft LightSwitch

By Glen Banta | 18 Nov 2011 | Tip
Integrating the HSS Interlink UploadFileDialog feature with Microsoft’s application platform, LightSwitch for Visual Studio.
   5.00 (2 votes)

1

2

3

4
2 votes, 100.0%
5
5.00/5 - 2 votes
μ 5.00, σa 5.00 [?]
 

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:
    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.

<!-- 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" />
// 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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Glen Banta

Chief Technology Officer
HighSpeed-Solutions, LLC
United States United States

Member

Follow on Twitter Follow on Twitter


Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board. (secure sign-in)
 
Search this forum  
 FAQ
    Noise  Layout  Per page   
  Refresh
GeneralReason for my vote of 5 Good Article. Tried it and it worked... Pinmembersimon.roderus5:04 21 Nov '11  
GeneralGood Trick. Was really helpful for me. Pinmembersimon.roderus5:07 21 Nov '11  

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Mobile
Web02 | 2.5.120309.1 | Last Updated 18 Nov 2011
Article Copyright 2011 by Glen Banta
Everything else Copyright © CodeProject, 1999-2012
Terms of Use
Layout: fixed | fluid