MVC Single Page Application Template for ASP.NET and Web Tools 2012.2

Xinyang Qiu

With the final release of ASP.NET and Web Tools 2012.2, we refreshed single page application page on asp.net .  It talks about KnockoutJS Template and introduced 4 community created SPA templates that you can install as MVC templates.

There are four improvements for the MVC SPA template RTM release over the RC release that worth a note.

Antiforgery support for Web API calls

The ValidateAntiForgeryToken filter only works on MVC calls. Web API doesn’t have a default Antiforgery filter yet. We implemented attribute “ValidateHttpAntiForgeryToken” inside Filters\ValidateHttpAntiForgeryTokenAttribute.cs to support antiforgery in Web API calls.  You can see section Anti-CSRF in KnockoutJS Template article for more information.

ValidateHttpAntiForgeryToken attribute is used for TodoController class and 3 methods for TodoListController class.

In index.cshtml, we have the following code:

@functions{
    public string GetAntiForgeryToken()
    {
        string cookieToken, formToken;
        AntiForgery.GetTokens(null, out cookieToken, out formToken);
        return cookieToken + ":" + formToken;                
    }
}
<input id="antiForgeryToken" type="hidden" value="@GetAntiForgeryToken()" />
In todo.datacontext.js file, as part of the AJAX call, we have:
var antiForgeryToken = $("#antiForgeryToken").val();
if (antiForgeryToken) {
    options.headers = {
        'RequestVerificationToken': antiForgeryToken
    }
}

Use camel case for JSON data

We listened to John Papa’s advice and changed to camel casing for all the JavaScript models.  We added the following line in app_start/webapiconfig.cs to support the camel case for JSON serialization.

// Use camel case for JSON data.
config.Formatters.JsonFormatter.SerializerSettings.ContractResolver = 
new CamelCasePropertyNamesContractResolver();

Support JQuery.1.9 JSON parser change

JQuery 1.9 has a change for JSON Parser that it no longer accept empty string as valid return.  We change the jquery.validate.unobtrusive.js file for all the MVC templates to support JQuery.1.9.  For SPA template, we use “text” datatype instead of “json” when we are not expecting a JSON output in todo.datacontext.js file:

    function saveChangedTodoList(todoList) {
        clearErrorMessage(todoList);
        return ajaxRequest("put", todoListUrl(todoList.todoListId), todoList, "text")
            .fail(function () {
                todoList.errorMessage("Error updating the todo list title. Please make sure it is non-empty.");
            });
    }

    // …
    function ajaxRequest(type, url, data, dataType) { // Ajax helper
        var options = {
            dataType: dataType || "json",
            contentType: "application/json",
            cache: false,
            type: type,
            data: data ? data.toJson() : null
        };
        
// …
        return $.ajax(url, options);
    }

Support KO ObservableArray IntelliSense by using JavaScript XML Documentation Comments

The editor uses “scripts/_references.js” file’s references files to get the Knockout’s IntelliSense in the data-bind attributes.  Sometimes it’s impossible for the JavaScript engine to figure out what the correct object type is for KO’s ObservableArray.  We need to add some XML Documentation Comments to help the JavaScript engine to provide meaningful JavaScript IntelliSense

todo.model.js

    function todoList(data) {
        var self = this;
        data = data || {};
        // …
        self.todos = ko.observableArray(importTodoItems(data.todos));

    // …

    function importTodoItems(todoItems) {
        /// <returns value="[new todoItem()]"></returns>
        return $.map(todoItems || [],
                function (todoItemData) {
                    return datacontext.createTodoItem(todoItemData);
                });
    }

todo.viewmodel.js:

window.todoApp.todoListViewModel = (function (ko, datacontext) {
    /// <field name="todoLists" value="[new datacontext.todoList()]"></field>
    var todoLists = ko.observableArray(),
So in general, if we have a simple code like below,
function TaskListViewModel() {
    var self = this;
    self.tasks = ko.observableArray([]);
we can convert to the following to support tasks IntelliSense in VS:
function TaskListViewModel() {
    var self = this;
    self.tasks = ko.observableArray(function () {
        /// <returns value="[new Task()]"></returns>
        return [];
    }());

Summary

There are quite a few SPA frameworks around.  You can easily customize a MVC template and create a VSIX file for other people to install.  If you have a great template to share, feel free to contact us to get your template listed in our asp.net SPA page.

0 comments

Discussion is closed.

Feedback usabilla icon