dileno

Subscribe

Hi! I'm Martin Söderlund, the owner of this blog. I work as a web consultant in Stockholm, Sweden. My main focus areas are .NET development and interface development.
If you've got something on your mind, feel free to contact me.

Close

Thank you for visiting!

Please consider subscribing to the RSS feed or following me on Twitter.

Ajax File Download That Works!

So you want to download a file and show an Ajax loader until the download is complete? Here's a way to do it:

  1. User clicks the download button and a JavaScript function is called.  In this JS function, a number of things will happen:
    • Show an AJAX loader.
    • Create a cookie.
    • Run a check cookie function.
    • Redirect to the file download (in this case an MVC method that returns the file).
  2. If successful, the MVC method removes the cookie and returns the file. When the cookie is removed, disable the Ajax loader (happens in check cookie function).
  3. Done.

Step 1 - JS call

User clicks our download button and we call this export function. Note: just before we create the timer and cookieName variables.

var timer = null;
var cookieName = 'App_FileExportCookie';
	
var export = function () {
    $('#ajax-loader').show();

    var cookie = $.cookie(cookieName);

    if (cookie === undefined) {
        cookie = $.cookie(cookieName, 0);
    }
    checkCookie();

    window.location = '/FileExport';
}

We show the Ajax loader and then check if a cookie exists (using jQuery Cookie plugin). Finally we redirect to the URL where the actual file generation and download will happen.

Step 2 - Check cookie

In step 1, we called the checkCookie function. This one is really important as it will check and see the status of the file download, through checking our cookie.

var checkCookie = function (doClearTimeout) {

    if (doClearTimeout) {
        clearTimeout(timer);
    }
    else {
        timer = setTimeout(function () {

            var cookie = $.cookie(cookieName);

            if (cookie === undefined) {
                $('#ajax-loader').hide();
	        checkCookie(true);
	    } else {
            checkCookie(false);
	    }
	}, 1500);
    }
}

What will happen here, is we set a timeout where we look for our cookie. We call this function until we can't find the cookie we created in step 1 any more. When the cookie doesn't exist, we hide the AJAX loader and clear the timeout.

Finally, we need a place to remove the cookie. Enter step 3.

Step 3 - file generation and remove cookie

In step 1, we redirected the user to the /FileExport url. In ASP.NET MVC, we will have an ActionResult with that name and here we will generate and return the file, plus remove the cookie we created in the beginning. The final code:

private string _fileCookieName = "App_FileExportCookie";
private const string _excelMimeType =
 "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";

public FileResult FileExport()
{
    ExcelFile excel;
	
    try {
        excel = GenerateExcel();
    }
    catch (Exception ex)
    {
        // handle exceptions
    }
    finally
    {
	// same as in JavaScript cookie name
	var cookieName = _fileCookieName;
	var cookie = Request.Cookies[_fileCookieName];

	if (cookie != null)
	{
    	    cookie.Expires = DateTime.Now.AddDays(-1);
	    Response.SetCookie(cookie);
        }
    }
	
    return File(excel.FilePath, _excelMimeType);
}

This is just some pseudo code for generating an Excel file, the important stuff happens in the finally block. We look for our cookie and remove it once the file is generated. Finally, we return the file in proper Excel format.

That's it!

IE Edge, Angular and Highlighting a Text Field

Recently, I stumbled upon a problem using the Angular Material framework. While using the md-autocomplete component, I wanted to highlight a text field when the user clicked said text field. Easier said than done.

I started writing a directive, which highlights a text field when it's focused. Of course I went for the focus event. When the focus event is triggered, I simply highlight the text field. It worked everywhere. Except in IE Edge.

After some debugging, I simply switched the focus event for the click event, and it started working everywhere.

Here's the directive:

app.directive('autocompleteFocus', function($timeout, $log){
  return{
    link: function(scope, element, attrs){
       $timeout(selectOnFocus, 0);

       function selectOnFocus(){
           element.find("#my-field").bind("click", function () {
               angular.element(this).select();
           });
       }
    }
 }
});

Use it like this:

<md-autocomplete ... autocomplete-focus />

Check if Bootstrap CSS is Loaded and Provide Local Fallback

When a CDN somehow fails, you want to make sure you can load a local fallback.

Here's a snippet to check if Bootstrap CDN is down, and then proceed to load a local Boostrap fallback version, utilizing Boostrap's hidden CSS class.

If Bootstrap is loaded, the span will be hidden. We simply check if it is hidden, and if it aint - we assume Bootstrap wasn't loaded from CDN and load our local fallback instead.

Run this script after you've tried to load Boostrap from a CDN.

var $span = $('<span class="bs hidden"></span>');
var $bs = $('body').append($span).find('.bs');

if ($bs.css('display') !== 'none') {
	$("head").append('<link rel="stylesheet" href="/css/Bootstrap/bootstrap.min.css">');
}
$bs.remove();

Other, more sofisticated methods, depend on libraries like yepnope or requirejs. Meanwhile, this method works just fine.

Take Ownership on Windows 10

Update: Now there's a nice tool with an interface that you can use instead. Reset Files Permission

After installing Windows 10, you suddenly don't have permissions to save in some locations. It doesn't matter if you're an administrator either.

After some research, I found a simple solution in this thread on TenForums.

Simply fire up a command prompt (hit Windows key, type CMD, right click and choose Run as administrator) and run this command on your location or drive (change E: to appropriate):

icacls "E:" /setowner "Administrators" /T /C

Depending of the number of files in your location, it might take some time.

To the top