Uploadify (Session and authentication) with ASP.NET

Challenge:

Sorry, comrades for not sharing anything with you since so long. But was bit occupied with other stuff, and as told you earlier that currently my main focus is on my Sitecore blog and yes, with your good wishes and god’s grace — got awarded as Sitecore MVP for the year of 2013! – Thank you!
Before couple of months back, we were trying to incorporate Uploadify [http://www.uploadify.com/documentation/] in to our solution. And while working on that we came across with Flash session bug, due to use Session, authentication and authorization — it means if your user is logged in and if your file upload operation wants that only logged in users can upload file then it won’t work with Uploadify by default. Don’t worry, we have a way to get out of it!

Solution:

I asked solution of this challenge to our common friend — Google, and found really interesting links:
http://joncahill.zero41.com/2009/11/problems-with-uploadify-aspnet-mvc-and.html

“Basically the issue is with flash where it will ignore the browser’s session state and grab the cookies from IE, which is a known and active bug. This means that both Chrome and Firefox won’t work with Uploadify and authorisation because flash will send no cookies! It also means it is entirely possible for it to have previously work for me while testing because I probably also had a IE window open and logged in while testing, which would have given me a valid cookie.”

http://trycatchfail.com/blog/post/2009/05/23/using-flash-with-aspnet-mvc-and-authentication.aspx

There is a well-known bug in Flash that causes it to completely ignore the browser’s session state when it makes a request.  Instead, it either pulls cookies from Internet Explorer or just starts a new session with no cookies.  GOOD CALL, ADOBE.  And when I say this bug is well-known, I mean it was reported in Flash 8.  It’s still sitting in the Adobe bug tracker.  It has been triaged, it seems to have high priority, yet it remains unfixed.  Again, GREAT job, Adobe.

http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx
http://stackoverflow.com/questions/1729179/uploadify-session-and-authentication-with-asp-net-mvc
Big thanks to all these article writers. Because it only helped us to find a solution. Using this solutions we were able to make session working. But authentication and membership information was not working . But we modified a bit in Global.asax and it started working. So, let me share a final solution with you:
1.  Pass session related information from your upload page in your upload call:
Just a note : This javascript code also covers other challenges as well (Which are not in scope of this article. But you may find it helpful!) e.g. passing dynamic data via onUploadStart, sending formdata via settings, showing uploadresult etc. The main variables which does the trick are — RequireUploadifySessionSync,SecurityToken,SessionId
[sourcecode language=”html”]
<script type="text/javascript">
var UploadifyAuthCookie = ‘<% = Request.Cookies[FormsAuthentication.FormsCookieName] == null ? string.Empty : Request.Cookies[FormsAuthentication.FormsCookieName].Value %>’;
var UploadifySessionId = ‘<%= Session.SessionID %>’;
$("#file_upload").uploadify({
‘buttonImage’: ‘/MultipleUploads/_scripts/browse-btn.jpg’,
‘scriptData’: { RequireUploadifySessionSync: true, SecurityToken: UploadifyAuthCookie, SessionId: UploadifySessionId },
‘formData’: { ‘KeyA’: ‘AValue’, ‘KeyB’: 1, RequireUploadifySessionSync: true, SecurityToken: UploadifyAuthCookie, SessionId: UploadifySessionId, UserName: UploadifyUserName }, // If some static data
‘auto’: false,
‘multi’: ‘true’,
‘swf’: ‘_scripts/uploadify.swf’,
‘uploader’: ‘<%= ResolveUrl("FileUploads.aspx") %>’,
‘onUploadStart’: function (file) {
// for all dynamic data
var objCheckUnPack = document.getElementById("chkUnpack");
var objCheckOverwrite = document.getElementById("chkOverwrite");
//                    alert(objCheckUnPack.checked);
//                    alert(objCheckOverwrite.checked);
$("#file_upload").uploadify("settings", "formData", { ‘IsUnPack’: objCheckUnPack.checked, ‘IsOverwrite’: objCheckOverwrite.checked });
//http://stackoverflow.com/questions/10781368/uploadify-dynamic-formdata-does-not-change
},
‘onQueueComplete’: function (queueData) {
alert(queueData.uploadsSuccessful + ‘ files were successfully uploaded. And there were few errors during upload for this number of files : ‘ + queueData.uploadsErrored);
window.open(‘<%= ResolveUrl("FileUploadResultPage.aspx") %>’, ‘Test’, ‘width=300,height=300’);
}
});
});
[/sourcecode]
2. Now, in Global.asax we have to handle this variables:
[sourcecode language=”csharp”]
protected void Application_BeginRequest(Object sender, EventArgs e)
{
// This check will ensure that we need to sync session only during uploadify upload!
if (HttpContext.Current.Request["RequireUploadifySessionSync"] != null)
UploadifySessionSync();
}
/// <summary>
/// Uploadify uses a Flash object to upload files. This method retrieves and hydrates Auth and Session objects when the Uploadify Flash is calling.
/// </summary>
/// <remarks>
///     Kudos: http://geekswithblogs.net/apopovsky/archive/2009/05/06/working-around-flash-cookie-bug-in-asp.net-mvc.aspx
///     More kudos: http://stackoverflow.com/questions/1729179/uploadify-session-and-authentication-with-asp-net-mvc
/// </remarks>
protected void UploadifySessionSync()
{
try
{
string session_param_name = "SessionId";
string session_cookie_name = "ASP.NET_SessionId";
if (HttpContext.Current.Request[session_param_name] != null)
UploadifyUpdateCookie(session_cookie_name, HttpContext.Current.Request.Form[session_param_name]);
}
catch { }
try
{
string auth_param_name = "SecurityToken";
string auth_cookie_name = FormsAuthentication.FormsCookieName;
if (HttpContext.Current.Request[auth_param_name] != null)
{
FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(HttpContext.Current.Request.Form[auth_param_name]);
if (ticket != null)
{
FormsIdentity identity = new FormsIdentity(ticket);
// This helped us to restore user details
string[] roles = System.Web.Security.Roles.GetRolesForUser(identity.Name);
System.Security.Principal.GenericPrincipal principal = new System.Security.Principal.GenericPrincipal(identity, roles);
HttpContext.Current.User = principal;
}
UploadifyUpdateCookie(auth_cookie_name, HttpContext.Current.Request.Form[auth_param_name]);
}
}
catch { }
}
private void UploadifyUpdateCookie(string cookie_name, string cookie_value)
{
HttpCookie cookie = HttpContext.Current.Request.Cookies.Get(cookie_name);
if (cookie == null)
cookie = new HttpCookie(cookie_name);
cookie.Value = cookie_value;
HttpContext.Current.Request.Cookies.Set(cookie);
}
[/sourcecode]
Happy Uploading via Uploadify! 🙂