File Uploader using Silverlight and WCF
From Silverlight 2 onwards it supports Open File Dialog, which helps developers to implement upload file logic, with the help of WCF services. Silverlight Open File Dialog offers better control over the existing HTML FileUpload control, like File Filter, File Sizes etc, and it can be managed from client side. Here is a simple implementation of Silverlight uploader with WCF.
Silverlight UI – XAML
<Canvas x:Name="LayoutRoot">
<StackPanel Margin="10" Background="White" Orientation="Horizontal">
<TextBlock Text="Select File :" />
<TextBox Name="txtFileName" Width="200" />
<Button Name="cmdBrowse" Content="Browse" Click="cmdBrowse_Click" />
<Button Name="cmdUpload" Content="Upload" Click="cmdUpload_Click" />
</StackPanel>
</Canvas>
And the code behind
FileInfo fi;
private void cmdBrowse_Click(object sender, RoutedEventArgs e)
{
//Open File Dialog
OpenFileDialog dlg = new OpenFileDialog();
//The _FilterText variable used to control file extentions
//supported by the Upload control
dlg.Filter = this._FilterText;
bool? result = dlg.ShowDialog();
if (result.HasValue && result.Value)
{
this.fi = dlg.File;
//The _FileSize variable used to control the
//Maximum Size supported by the control.
if (this.fi.Length > this._FileSize)
{
//Control will fire a FileSizeError event, if the
//Uploading File Size greater than the specified.
if (this._onFileSizeError != null)
{
this._onFileSizeError(this, EventArgs.Empty);
}
return;
}
this.txtFileName.Text = this.fi.Name;
}
}
private void cmdUpload_Click(object sender, RoutedEventArgs e)
{
//Uploading part.
if (this.fi != null)
{
byte[] buffer = new byte[this.fi.Length];
using (Stream s = this.fi.OpenRead())
{
//Reading the File Content to the Stream.
//It is using a WCF Service with Upload File method
s.Read(buffer, 0, buffer.Length);
ServiceReference1.Service1Client client = new ServiceReference1.Service1Client();
client.UploadFileCompleted += new EventHandler<System.ComponentModel.AsyncCompletedEventArgs>(client_UploadFileCompleted);
client.UploadFileAsync(this.fi.Name, buffer);
}
}
}
private void client_UploadFileCompleted(object sender, System.ComponentModel.AsyncCompletedEventArgs e)
{
//Application will raise another Event
//after the completion of the File Upload.
if (this._onFileUploadCompleted != null)
{
this._onFileUploadCompleted(this, EventArgs.Empty);
}
}
And here is the WCF Service with Upload File method.
//IService1 Interface
[ServiceContract]
public interface IService1
{
[OperationContract]
void UploadFile(string fileName, byte[] content);
}
//IService1 Interface implementation
public class Service1 : IService1
{
public void UploadFile(string fileName, byte[] content)
{
using (FileStream sw = File.OpenWrite(Path.Combine(@"C:\Uploads", fileName)))
{
sw.Write(content, 0, content.Length);
}
}
}
To enable communication between Silverlight and Javascript the “System.Windows.Browser” namespace is used. Which supports various attributes and methods, will expose the properties and events of the silverlight application to the Javascript.
public MainPage()
{
InitializeComponent();
//This method enables the scripting support to the Application.
//From Javascript developer can access the Properties and events
//like SilverlightObj.Content.Page.Property
HtmlPage.RegisterScriptableObject("Page", this);
}
private string _FilterText = "Text Files|*.txt";
private int _FileSize = 1000;
private event EventHandler _onFileSizeError;
private event EventHandler _onFileUploadCompleted;
//This attribute used to expose the Property to Client side.
//From Javascript : ctrl.Content.Page.FileSize = 2000;
[ScriptableMember]
public int FileSize
{
get
{
return this._FileSize;
}
set
{
this._FileSize = value;
}
}
[ScriptableMember]
public string Filter
{
get
{
return this._FilterText;
}
set
{
this._FilterText = value;
}
}
[ScriptableMemberAttribute]
public EventHandler OnFileSizeError
{
get
{
return this._onFileSizeError;
}
set
{
this._onFileSizeError = value;
}
}
[ScriptableMemberAttribute]
public EventHandler OnFileUploadCompleted
{
get
{
return this._onFileUploadCompleted;
}
set
{
this._onFileUploadCompleted = value;
}
}
And in the Javascript, the property can access and can modify it.
function onPluginLoaded() {
var ctrl = document.getElementById("silverlightControlHost1");
ctrl.Content.Page.Filter = "Image Files|*.jpg;*.gif;*.png|All Files(*.*)|*.*";
ctrl.Content.Page.FileSize = 20000;
ctrl.Content.Page.OnFileSizeError = function () {
alert("File Size should be less than 2 KB");
};
ctrl.Content.Page.OnFileUploadCompleted = function () {
alert("Uploaded successfully !");
};
}
And the HTML Part – Here the onLoad parameter will assign the Javascript to execute on loading of the silverlight application.
<object id="silverlightControlHost1" data="data:application/x-silverlight-2," type="application/x-silverlight-2"
width="100%" height="100%">
<param name="onLoad" value="onPluginLoaded" />
</object>
And here is the screen shot, of the same running on my Windows 7 machine.
Please let me know your comments and feedbacks. Happy Programming.
Http Compression in ASP.Net
Yesterday I got a chance to attend web performance optimization team meeting, and they suggested, HTTP Compression will help to reduce the Bandwidth and thus improves the performance. Later I come to know some of other teams in my organization are using these techniques in their web applications. I found few implementations, and the code is written in Global.asax. But the problem with this approach is the code is not reusable. I thought of implementing it an Http Module for compressing the HTTP response. For more information about HttpModules, check MSDN.
Here is the code of Compression Module.
public class CompressionModule : IHttpModule
{
private HttpApplication httpApplication;
private string acceptEncoding;
private const string DEFLATE = "deflate";
private const string GZIP = "gzip";
private const string AJAX = "HTTP_X_MICROSOFTAJAX";
private const string WEBSERVICE = "SyncSessionlessHandler";
/// <summary>
/// Disposes of the resources (other than memory) used by the module that implements <see cref="T:System.Web.IHttpModule"/>.
/// </summary>
public void Dispose()
{
//Do nothing
}
/// <summary>
/// Initializes a module and prepares it to handle requests.
/// </summary>
/// <param name="context">An <see cref="T:System.Web.HttpApplication"/> that provides access to the methods, properties, and events common to all application objects within an ASP.NET application</param>
public void Init(HttpApplication context)
{
context.BeginRequest += new EventHandler(context_BeginRequest);
this.httpApplication = context;
}
/// <summary>
/// Handles the BeginRequest event of the context control.
/// </summary>
/// <param name="sender">The source of the event.</param>
/// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
private void context_BeginRequest(object sender, EventArgs e)
{
if (IsEncodingSupported)
{
//Converting the Accept encoding to lower, it can be gZip, GZip, Gzip
this.acceptEncoding = acceptEncoding.ToLower();
Stream prevUncompressedStream = this.httpApplication.Response.Filter;
//First checks whether deflate compression is supported or not.
//Because Deflate offers better compression compared to GZip
if (acceptEncoding.Contains(DEFLATE) || acceptEncoding == "*")
{
// defalte
this.httpApplication.Response.Filter = new DeflateStream(prevUncompressedStream,
CompressionMode.Compress);
this.httpApplication.Response.AppendHeader("Content-Encoding", DEFLATE);
}
else if (acceptEncoding.Contains(GZIP))
{
// gzip
this.httpApplication.Response.Filter = new GZipStream(prevUncompressedStream,
CompressionMode.Compress);
this.httpApplication.Response.AppendHeader("Content-Encoding", GZIP);
}
}
}
/// <summary>
/// Gets a value indicating whether this instance is encoding supported.
/// </summary>
/// <value>
/// <c>true</c> if this instance is encoding supported; otherwise, <c>false</c>.
/// </value>
private bool IsEncodingSupported
{
get
{
//Check wheather the Request is for Page or Web Service.
//Also check wheather it an AJAX Request.
this.acceptEncoding = this.httpApplication.Request.Headers["Accept-Encoding"];
if (!this.httpApplication.Request.RawUrl.Contains(".aspx") ||
this.httpApplication.Request[AJAX] != null)
{
return (false);
}
//Check whether browser supports compression.
if (acceptEncoding == null || acceptEncoding.Length == 0)
{
return (false);
}
return true;
}
}
}
As the code is in App_Code folder, you need to register the http module in the Web.Config file.
<httpModules>
<add name="CompressionModule" type="CompressionModule, App_Code"/>
</httpModules>
If you are using IIS 7 the settings will be different like this.
<system.webServer>
<modules>
<add name="CompressionModule" type="CompressionModule, App_Code"/>
</modules>
</system.webServer>
