To give you the context – we have SPA ERP to build and we have a very good set of jQuery/HTML5 controls for the UI – Infragistics Ignite UI. After installing the IG Ignite UI I started to experiment with the upload control and read its documentation here, here and here (A better organized documentation seated in one place is needed 🙂 ) and experimenting with the examples we got stuck because :
1. The default back-end implementation requires you to register static event handlers for handling the upload process. We build SPA ERP so we will get at the end more then hundred redundant event handlers for each module which is not smart thing to do.
2. The upload process actually happens outside of the MVC pipeline therefore your HtppContext does not have its User populated neither you can point it to a Controller. Therefore we can not validate the user anyway and for an enterprise app this is A problem.
3. There is no (obvious) way to parametrise the upload call which is not a good situation when you work with a SPA.
Point 1 and 3 are solved by using the default implementation provided in the documentation and (the tricky part) by adding more arguments to the upload control on initialization :
controlId: 'UploadHandler&UploadParams=' + ParametrisedGetUriStringWhichYouMustNotTrustEverAndSanitizeInTheBackEndByDefault,
Of course you have to initialize you upload control every time your user clicks some ‘Upload’ button and not just once on document.load
Doing it this way you have
(1) one pair of Upload Event Handlers in the back-end and
(2) one parametrised upload method in the front end by which
(3) you can use your DI through DependencyResolver.Get() to get the required component and dispatch the file to it.
Point 2 we solved in two different ways and I find the second more convenient, elegant and not so error prone – especially if you are going to have multiple web instances.
The first way, buy keeping sessions-users dictionary is suggested by Infragistics support team here after initial discussion on ‘ To Stream or not to Stream?’ here. ( You better stream because otherwise you risk your web instance/servers RAM to explode one day unexpectedly leaving you wonder). The problem with this approach is that you have to make this dictionary and to be careful with cookie expiration.
The other way is simpler but not obvious at all and it was pointed out to me by another guy from Infragistics but who is not in the support team. The advice is to use the already existing ASP.NET machinery from inside ‘FinishedUpload’ event handler :
var ticket = FormsAuthentication.Decrypt(HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
throw new InvalidOperationException("Ticket expired.");
HttpContext.Current.User = new RolePrincipal(new FormsIdentity(ticket));
This way you get the same cookie the user uses to authenticate and which cookie you probably use with [Authorize] attribute. Of course you can not point your upload control to Controller because the upload happens outside of the MVC pipeline. But after you set the HttpContext.Current.User you can use your implemented Role Provider to check if the user has the particular role or whatever.