AJAX File Uploads with HTML 5

I see on StackOverflow the question often how to upload a file via AJAX.  It turns out it is actually not that difficult. We utilize a solution using the Html 5 FileReader component. The idea is have the file reader read a PDF file contents, and transfer those contents to a hidden field (stored in the $hidden variable). A portion of the script we use is shown below.

$("#FileUpload").on('change', function (e) {
var $self = this;
var file = $self.files[0];

var fileReader = new FileReader();
fileReader.addEventListener('load', function () {
   var result = fileReader.result;
   $hidden.val(result);
});
fileReader.readAsDataURL(file);

$self.val('');
});

Once a file is read, it invokes the “load” event with the contents of the file; the contents of the file are then stored in a hidden field. Since the contents are in the HTML file, it’s possible then to send those HTML contents to the server, or be a part of a normal postback lifecycle.

The idea with “readAsDataURL” is it creates a URL like the following: “data:text/html,sdafadf34533543sefkafdsadf90809as8dfasdf90asdf9fsdf” where the contents of the PDF are really large. You’ll need to extend what is acceptable as a part of your content.

On the server side, the solution is as simple as splitting the contents after the first comma like:

//Strip off the "data:text/html," portion of the data URL posted back to the server
fileContents.Substring(fileContents.IndexOf(",") + 1);

This is one of many solutions; there are a wide variety of JQuery or other solutions out there.

Watch Your Scoping

I recently found a bug in a plugin and so I figured that would be a good time to offer a public service announcement as to why you have to be careful with scoping in JavaScript.  The plugin I’m featuring is just a quick example of the problem.  Suppose your had the following HTML snippet:


< div id="section1" class="section" >
First Button
< span id="sp1" >0< /span >
< /div >
< div id="section2" class="section" >
Second Button
< span id="sp2" >0< /span >
< /div >
< div id="section3" class="section" >
Third Button
< span id="sp3" >0< /span >
< /div >

Pretty simple. The idea of my plugin was to target the root DIV tag, and then parse down to the BUTTON and SPAN at an individual level. Now, as I think about writing this, the reality is of the situation, I should have considered the JQuery Widget API, as I think that would have been better situated for what I am about to do. I was under the gun to get this feature completed, and this solution was not optimal, but it worked and did get the job done. Anyway, the JQuery plugin is below:

$.fn.parse = function() {
  return this.each(function() {
    var spn = $(this).find("span");
    btn = $(this).find("button");
    
    btn.on("click", function(e) {
       var n = parseFloat(spn.html());
       n += 1;
       spn.html(n);
    
       btn.html(btn.html() + "(clicked)");
    });
  });
}

The idea is that the span and button are retrieved within the context of the root DIV, and when the button is clicked, both elements are updated to indicate that a click occurred. You’ll notice though, that while the span gets the proper update, the button does not (always targets the last). This is simply because the button doesn’t include “var” declaration. This means the button is scoped beyond the current context of the each() callback. Because of this, the last button was selected and thus the last button is represented in the query.

This produces the result:

jsscreenshot

Adding VAR was the immediate solution. Another reminder why you need to make sure you variables are scoped correctly.

Just to brainstorm, another solution could be to, using the current reference within the button click, access the button through the callback and even target the SPAN that way, rather than relying on variables.

You can view the Gist here.

ASP.NET MVC Dynamic Reference Data Loading

MVC, like any other language, is a tool that has plenty of capabilities when rendering client markup; one method call can render pages of client markup. Using a server-side approach can simplify some of the rendering of content needed. As a for instance, here is one common situation I often use a server-side approach to rendering content within an application. An application may have a Kendo DropDownList, which is highly dependent on a list of some data in JSON format. The initialization script looks like the following:

$("DropDownList").kendoDropDownList({
   dataSource [{ .. }],
   dataTextField: "Text",
   dataValueField: "Value"
});

Typically, the data source is some lookup data source; in most applications, lookup data typically contains a key and value. The dataTextField and dataValueField properties map to values within these It’s helpful to have lookup data that’s standardized, because it’s easy to create a helper function that does the following:

@Helper LookupData(IList data)
{
   return NewtonSoft.JSON.JsonConvert.SerializeObject(data);
}

This helper converts data to JSON, which is used in the script below.

$("DropDownList").kendoDropDownList({
   dataSource @LookupData(Model.CustomerTypes),
   dataTextField: "Text",
   dataValueField: "Value"
});

Here we take a collection of reference items and use that to convert it to JSON. Really, that approach may not be that useful, but where you can find use is if you have a common reference table loader object. Using this, the helper function can automatically retrieve a common dataset based on a given type of reference data:

@Helper LookupData(Type referenceType)
{
    var container = Framework.Container; // this is a singleton reference to the dependency injection container
    var referenceData = container.GetInstance(); //A utility class to load common reference data

    return JSONConvert.DeserializeObject(referenceData.GetValues(referenceType));
}

The reference data uses an IReferenceTableManager class to perform the work. Behind the scenes, this could be anything, including Entity Framework. Below is one possible solution:

public class ReferenceValue
{
    public int ID { get; set; }

    public string Text { get; set; }
}

public interface IReferenceTableManager { 
   IEnumerable GetValues(Type type);
}

public class EFReferenceTableManager : IReferenceTableManager {
  public IEnumerable GetValues(Type type)
  {
     var ctx = new EntityFrameworkContextInstance();

     //From a given type, there are multiple ways to get the data from the DB; I am not
     //aware of a way to query by type (at least easily). There may be a better way to do this,
     // but for the time being, the two possible ways to do query referenced data dynamically
     //by generics are: using reflection or, using a long if statement and type checking like:
     if (type.Equals(typeof(Countries))) {
       return ctx.Set().ToList();
     }
     else if (type.Equals(typeof(States))) {
       return ctx.Set().ToList();
     }
     .
     .
  }

}

Not the best implementation; I’m sure there is something better out there, but you get the idea as to how this dependency can now be implemented dynamically. However, the question most will have is whether this is scope creep on behalf of the view (as to whether this is a responsibility of the controller). It’s also possible to have the lookup helper examine a given model and extract the data from there too. There are multiple ways to solve this problem.

Dynamic Script Registering Component in ASP.NET MVC

One of the performance enhancements recommended in tools like YSlow and others is to put your JavaScript script files at the bottom of the page. The great difficulty in a web forms or MVC web application with doing that is scripts at the bottom of the page are typically added in the master page. Any pages or views can make use of a special section just for scripts, but partial views or user controls can’t take advantage of that.

I’m about to illustrate a solution that will do just that. It’s setup for MVC, but could be easily adapted for web forms by making the helpers as controls. You have to understand that MVC is a top down structure. So as views or partials render, they render their contents in place. The common approach is to have a section for scripts:

site.master:


  // master page common scripts


@* for any custom scripts in the view *@
@RenderSection("scripts", false)

The view can add a @section scripts { } to take advantage of this, but the partial view cannot. Additionally, everything is rendered in top down format; if a partial view at the top of your page has a script like:


$(function() { alert("In the partial view"); });

The problem with this script is that the final rendered view (when scripts are defined at the bottom) will look like:


$(function() { alert("In the partial view"); });


.
.
.
view content
. . // master page common scripts // view scripts

Since it’s top down, it’s also dependent on order, so scripts defined have no dependency (lacking a dependency feature like angular or script JS).

The following solution was meant to give more control over placement of defined scripts. Scripts are defined in a wrapper, and queued up for later rendering. The solution I’m providing is simple, but easily enhanced to add dependencies in scripts, custom ordering, and more features.

To give an idea of what we need to do, the system will achieve something like the following:

view.cshtml:

@Html.AddScript("ViewInit", () => @$(function() { .. }));

partial view:

@Helper Script()
{
   
     ..
   
}

@Html.AddScript("PartialInit", (m) => Script());

master:

@Html.PlaceScripts()

The idea is to add scripts via a method, which queues them up to be rendered, and writes them out at the point the PlaceScripts method is called. Note that for partial views, I’m using a little trick I noted earlier, whereby using a helper is the only way to circumvent exceptions that occur when using the action-based approach.

AddScript essentially adds the definitions to the HttpContext.Items collection, a common trick for storing singleton-like data elements that are available across the application. Since HttpContext.Items is available to add and then render scripts, it’s a great place to share content. The AddScript method shoves in data:

public void AddScript(HtmlHelper html, string key, Action fn)
{
    var http = html.ViewContext.HttpContext;
	var list = http.Items["_Scripts"] as Dictionary;
	
	if (list == null)
		list = new Dictionary();
	
	list[key] = fn;
	
	http.Items["_Scripts"] = list;
}

This method checks to see if we have a dictionary in the items collection; if not, it creates it, pushes in our item, and updates the collection. Similar, our other method, which takes a helper result, uses another overload to store the string result for easy rendering:

public void AddScript(this HtmlHelper html, string key, HelperResult fn)
{
	this.AddScript(html, key, fn(html.ViewData.Model).ToHtmlString());
}

public void AddScript(this HtmlHelper html, string key, string script)
{
    var http = html.ViewContext.HttpContext;
	var list = http.Items["_Scripts"] as Dictionary;
	
	if (list == null)
		list = new Dictionary();
	
	list[key] = script;
	
	http.Items["_Scripts"] = list;
}

We could easily add dependencies and ordering requirements to this solution if we needed; for now, let’s finish this out by showing how to grab the contents and render them:

public void PlaceScripts(this HtmlHelper html)
{
var http = html.ViewContext.HttpContext;
var list = http.Items[“_Scripts”] as Dictionary;

if (list == null)
return;

using writer = new HtmlTextWriter(html.ViewContext.Writer)
{
foreach (var entry in list)
{
if (typeof(entry.Value) is string) {
writer.WriteLine(entry.Value);
}
else {
//This is an action; the action will be
//rendered in the current output stream, and
//do not need to be directly written
entry.Value(html.ViewData.Model);
}
}
}

}

This would need greatly enhanced for dependencies and sorting; right now, we take the list in order and render it out. For HTML results or just plain string definitions, it gets rendered to the current response stream. Actions get processed the same way, but MVC handles that internally, rather than your code.

And voila, we are done; now we can define scripts in the view and partial views and expect them to be rendered where we want them placed, and have a component that can be easily enhanced to do much more.

Kendo MaskedTextBox Custom Rules

The Kendo UI MaskedTextBox plugin is great for limiting the input entered into a textbox. For instance, to validate a phone number, you could do the following:

$("#tb").kendoMaskedTextBox({
    mask: "(000) 000-0000"
});

The value zero ensures only numbers are entered. The masked text box also has these placeholders as well:

9 – 0 to 9 plus space
# – 0 to 9, space, plus, minus
L – a-z, A-Z
? – a-z, A-Z, space
& – any character
C – any character, space
A – letters, digits
a – letters, digits, space
. – Decimal
, – Thousands placeholder
$ – Currency

Outside of these rules, it’s possible to add your own, such as the following:

$("#tb").kendoMaskedTextBox({
    mask: "~A-00-000",
    rules: {
       "~": /[3-9]/,
       "*": /[ASDF]/
    }
});

The “~” and the “*” are the mask placeholder, whereas the /[3-9]/ and /[ASDF]/ define the range of acceptable values. This way, you can create a range to be whatever you desire.