How to Implement Silverlight File Upload: Step-by-Step Guide
Silverlight applications can provide rich client-side experiences, including file uploads to a server. This guide walks through a complete, practical implementation using Silverlight 5, covering client-side selection, validation, progress reporting, and server-side handling (ASP.NET). Example code snippets are included for each step.
Prerequisites
- Visual Studio (2010–2015 recommended for Silverlight support).
- Silverlight 5 SDK and developer runtime installed.
- An ASP.NET Web Application (MVC or WebForms) for server endpoints.
- Basic familiarity with C#, XAML, and HTTP.
Overview of the approach
- Create a Silverlight project and host page.
- Add UI for file selection and upload progress.
- Use the OpenFileDialog to pick files in Silverlight.
- Validate files (size, type) client-side.
- Stream the file using WebClient/HttpWebRequest or WCF stream to the server.
- Implement server endpoint to receive and store the file.
- Report progress and handle errors.
1. Create the Silverlight project and host
- In Visual Studio, create a new “Silverlight Application”. Choose to host in a new Web Application.
- Ensure the Web project has an ASP.NET page (Default.aspx) that embeds the Silverlight XAP.
2. Build the UI (XAML)
Add controls: a Button to open file picker, a TextBlock for selected filename, a ProgressBar, and an Upload Button.
xml
<UserControl x:Class=“FileUploadSample.MainPage” xmlns=“http://schemas.microsoft.com/winfx/2006/xaml/presentation” xmlns:x=“http://schemas.microsoft.com/winfx/2006/xaml” Width=“400” Height=“140”> <StackPanel Margin=“10” VerticalAlignment=“Top”> <Button x:Name=“BrowseButton” Content=“Browse…” Width=“80” Click=“BrowseButton_Click”/> <TextBlock x:Name=“FileNameText” Margin=“0,6,0,0”/> <ProgressBar x:Name=“UploadProgress” Height=“18” Width=“360” Minimum=“0” Maximum=“100” Margin=“0,6,0,0”/> <Button x:Name=“UploadButton” Content=“Upload” Width=“80” Click=“UploadButtonClick” Margin=“0,8,0,0”/> <TextBlock x:Name=“StatusText” Foreground=“Red” Margin=“0,6,0,0”/> </StackPanel> </UserControl>
3. Let users pick files (OpenFileDialog)
Use OpenFileDialog to allow selection; access file(s) as StreamResourceInfo or Stream.
csharp
using System.Windows.Controls; using System.Windows; using System.IO; using System.Windows.Resources; private Stream _selectedFileStream; private string _selectedFileName; private void BrowseButton_Click(object sender, RoutedEventArgs e) { var dlg = new OpenFileDialog(); dlg.Filter = “All files (.)|.”; dlg.Multiselect = false; if (dlg.ShowDialog() == true) { var file = dlg.File; _selectedFileName = file.Name; FileNameText.Text = _selectedFileName; selectedFileStream = file.OpenRead(); // Stream of selected file StatusText.Text = ””; } }
4. Client-side validation
Check file size and extension before uploading.
csharp
private const int MaxSizeBytes = 10 1024 1024; // 10 MB private bool ValidateSelectedFile() { if (_selectedFileStream == null) { StatusText.Text = “No file selected.”; return false; } if (selectedFileStream.Length > MaxSizeBytes) { StatusText.Text = “File too large (max 10 MB).”; return false; } // optional: validate extension return true; }
5. Uploading the file from Silverlight
Two common approaches: WebClient (multipart/form-data) or HttpWebRequest with chunked streaming. WebClient is simpler but less flexible. Below is a WebClient multipart approach using a MemoryStream to build the multipart content.
csharp
using System.Net; using System.Text; private void UploadButton_Click(object sender, RoutedEventArgs e) { StatusText.Text = ””; if (!ValidateSelectedFile()) return; var client = new WebClient(); client.UploadProgressChanged += Client_UploadProgressChanged; client.UploadStringCompleted += Client_UploadStringCompleted; // Build a multipart/form-data body string boundary = ”—————————” + DateTime.Now.Ticks.ToString(“x”); client.Headers[“Content-Type”] = “multipart/form-data; boundary=” + boundary; var ms = new MemoryStream(); var writer = new StreamWriter(ms); string header = \("--</span><span class="token interpolation-string interpolation" style="color: rgb(57, 58, 52);">{</span><span class="token interpolation-string interpolation expression language-csharp">boundary</span><span class="token interpolation-string interpolation" style="color: rgb(57, 58, 52);">}</span><span class="token interpolation-string" style="color: rgb(163, 21, 21);"> Content-Disposition: form-data; name="file"; filename="</span><span class="token interpolation-string interpolation" style="color: rgb(57, 58, 52);">{</span><span class="token interpolation-string interpolation expression language-csharp">_selectedFileName</span><span class="token interpolation-string interpolation" style="color: rgb(57, 58, 52);">}</span><span class="token interpolation-string" style="color: rgb(163, 21, 21);">" Content-Type: application/octet-stream "</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> writer</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(57, 58, 52);">Write</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span>header</span><span class="token" style="color: rgb(57, 58, 52);">)</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> writer</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(57, 58, 52);">Flush</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span class="token" style="color: rgb(57, 58, 52);">)</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span> <span> </span><span class="token" style="color: rgb(0, 128, 0); font-style: italic;">// copy file stream</span><span> </span><span> _selectedFileStream</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span>Position </span><span class="token" style="color: rgb(57, 58, 52);">=</span><span> </span><span class="token" style="color: rgb(54, 172, 170);">0</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> _selectedFileStream</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(57, 58, 52);">CopyTo</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span>ms</span><span class="token" style="color: rgb(57, 58, 52);">)</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> writer</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(57, 58, 52);">Write</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span class="token" style="color: rgb(163, 21, 21);">" "</span><span class="token" style="color: rgb(57, 58, 52);">)</span><span class="token" style="color: rgb(57, 58, 52);">;</span><span> </span><span> writer</span><span class="token" style="color: rgb(57, 58, 52);">.</span><span class="token" style="color: rgb(57, 58, 52);">Write</span><span class="token" style="color: rgb(57, 58, 52);">(</span><span class="token interpolation-string" style="color: rgb(163, 21, 21);">\)”–{boundary}– “); writer.Flush(); ms.Position = 0; var buffer = new byte[ms.Length]; ms.Read(buffer, 0, buffer.Length); // endpoint on server Uri uri = new Uri(HtmlPage.Document.DocumentUri, ”/FileUploadHandler.ashx”); client.UploadDataAsync(uri, “POST”, buffer); }
Progress and completion handlers:
csharp
private void Client_UploadProgressChanged(object sender, UploadProgressChangedEventArgs e) { UploadProgress.Value = e.ProgressPercentage; StatusText.Text = $“Uploading… {e.ProgressPercentage}%”; } private void ClientUploadStringCompleted(object sender, UploadStringCompletedEventArgs e) { if (e.Error != null) { StatusText.Text = “Upload failed: “ + e.Error.Message; return; } StatusText.Text = “Upload complete”; }
Note: UploadDataAsync triggers UploadDataCompleted rather than UploadStringCompleted if using UploadDataAsync; adapt handlers accordingly.
Alternative: HttpWebRequest for chunked or large uploads and for reporting finer-grained progress.
6. Server-side: Receive and save the file (ASP.NET handler)
Create FileUploadHandler.ashx in the web project to accept multipart uploads.
csharp
public class FileUploadHandler : IHttpHandler { public void ProcessRequest(HttpContext context) { try { if (context.Request.Files.Count > 0) { var file = context.Request.Files[0]; string savePath = context.Server.MapPath(”~/UploadedFiles/”); if (!Directory.Exists(savePath)) Directory.CreateDirectory(savePath); string full = Path.Combine(savePath, Path.GetFileName(file.FileName)); file.SaveAs(full); context.Response.StatusCode = 200; context.Response.Write(“OK”); } else { context.Response.StatusCode = 400; context.Response.Write(“No file received”); } } catch (Exception ex) { context.Response.StatusCode = 500; context.Response.Write(“Error: “ + ex.Message); } } public bool IsReusable { get { return false; } } }
For MVC, accept via HttpPostedFileBase in a controller action.
7. Security and robustness tips
- Validate file type and size on server-side too.
- Store uploads outside the webroot or sanitize filenames.
- Scan for malware if appropriate.
- Use HTTPS to protect data in transit.
- Implement authentication/authorization if uploads are restricted.
- For large files, implement chunked uploads and resume support.
8. Large files and advanced scenarios
- Use HttpWebRequest with BeginGetRequestStream/BeginGetResponse for streaming.
- Implement chunked uploads: split file into parts client-side and reassemble server-side.
- Consider WCF streaming for direct streamed calls to services.
Example: Simple HttpWebRequest upload (outline)
- Create HttpWebRequest to POST to handler.
- Get request stream asynchronously, write file bytes in chunks, call GetResponse.
(For brevity, code omitted; follow similar patterns as WebClient but managing streams directly.)
9. Testing and debugging
- Test with various file sizes and types.
- Use Fiddler or browser dev tools to inspect requests.
- Log server-side exceptions.
- Ensure content-length and boundaries are correct in multipart body.
10. Wrap-up
This guide demonstrated creating a Silverlight UI to pick a file, validate it, upload via multipart/form-data to an ASP.NET endpoint, and handle progress and errors. For production, prefer server-side validation, HTTPS, and handling large files via streaming or chunking.
If you want, I can provide a full sample project (client and server) with HttpWebRequest chunked upload and resume support.
Leave a Reply