EzDevInfo.com

Durandal

A cross-device, cross-platform client framework written in JavaScript and designed to make building Single Page Applications (SPAs) easy to create and maintain. Home | Durandal durandal is a cross-device, cross-platform client framework written in javascript and designed to make single page applications (spas) easy to create and maintain.

DurandalJS vs AngularJS?

I'm looking for a JS framework to build an SPA and found DurandalJS and AngularJS. Can anyone compare these two frameworks? I did find many articles that compares AngularJS and KnockoutJS, and they say AngularJS is more than data binding, so I think DurandalJS may be the one to compare.

I did a little research on AngularJS, it is good but one thing is bad: the $ prefix does not work when minified, although there is an ugly workaround. And someone said Twitter Bootstrap does not work well with it (I didn't check).

For DurandalJS, I still cannot find the samples (http://durandaljs.com/documentation/Understanding-the-Samples/), so it's hard to say.

Do they work well with TypeScript?


Source: (StackOverflow)

How to make a SPA SEO crawlable?

I've been working on how to make a SPA crawlable by google based on google's instructions. Even though there are quite a few general explanations I couldn't find anywhere a more thorough step-by-step tutorial with actual examples. After having finished this I would like to share my solution so that others may also make use of it and possibly improve it further.
I am using MVC with Webapi controllers, and Phantomjs on the server side, and Durandal on the client side with push-state enabled; I also use Breezejs for client-server data interaction, all of which I strongly recommend, but I'll try to give a general enough explanation that will also help people using other platforms.


Source: (StackOverflow)

Advertisements

MVC Authentication and Antiforgery token with Durandal SPA template

Some areas of my SPA need to be open to all users, and some areas require authentication. In these areas, it's the data loaded via AJAX that I want to protect.

I have an authentication service (see below), which I add as a dependency in my durandal main.js. The service is called:

authentication

In my main.js I call

authentication.handleUnauthorizedAjaxRequest(function () {
        app.showMessage('You are not authorized, please login')
        .then(function () {
            router.navigateTo('#/user/login');
        });
    });

It warns the user they are not authorized, and navigates user to a login view/viewmodel where they can enter details and try logging in.

Some questions that come to mind when building this authentication viewModel:

  • Are there any obvious concerns with what I'm doing?
  • Is this how I'm 'meant' to do things in Durandal?
  • Am I re-inventing the wheel? I couldn't see anything like this within Durandal.

Most people seem to be creating seperate cshtml pages; one for login (if the user is not authenticated), and the usual index.cshtml Is there any good reasons for me to switch to that method?

My login action on my the server-side 'user controller' has the [ValidateAntiForgeryToken] attribute I need to send that as well.
I also have an 'antiforgery' service (see below) which I also add as a dependency in my main.js viewModel file then (also in my main.js).

antiforgery.addAntiForgeryTokenToAjaxRequests();

This intercepts all ajax requests (along with content), and adds the MVC AntiForgeryToken value to the data. Seems to work exactly as I want it to. Please let me know if there's any errors/mistakes.

Complete authentication service below.

// services/authentication.js
define(function (require) {
    var system = require('durandal/system'),
    app = require('durandal/app'),
    router = require('durandal/plugins/router');

    return {
        handleUnauthorizedAjaxRequests: function (callback) {
            if (!callback) {
                return;
            }
            $(document).ajaxError(function (event, request, options) {
                if (request.status === 401) {
                    callback();
                }
            });
        },

        canLogin: function () {         
            return true;
        },
        login: function (userInfo, navigateToUrl) {
            if (!this.canLogin()) {
                return system.defer(function (dfd) {
                    dfd.reject();
                }).promise();
            }
            var jqxhr = $.post("/user/login", userInfo)
                .done(function (data) {
                    if (data.success == true) {
                        if (!!navigateToUrl) {
                            router.navigateTo(navigateToUrl);
                        } else {
                            return true;
                        }
                    } else {
                        return data;
                    }
                })
                .fail(function (data) {
                    return data;
                });

            return jqxhr;
        }
    };
});

// services/antiforgery.js
define(function (require) {
    var app = require('durandal/app');

    return {
        /*  this intercepts all ajax requests (with content)
            and adds the MVC AntiForgeryToken value to the data
            so that your controller actions with the [ValidateAntiForgeryToken] attribute won't fail

            original idea came from http://stackoverflow.com/questions/4074199/jquery-ajax-calls-and-the-html-antiforgerytoken

            to use this

            1) ensure that the following is added to your Durandal Index.cshml
            <form id="__AjaxAntiForgeryForm" action="#" method="post">
                @Html.AntiForgeryToken()
            </form>

            2) in  main.js ensure that this module is added as a dependency

            3) in main.js add the following line
            antiforgery.addAntiForgeryTokenToAjaxRequests();

        */
        addAntiForgeryTokenToAjaxRequests: function () {
            var token = $('#__AjaxAntiForgeryForm     input[name=__RequestVerificationToken]').val();
            if (!token) {
                app.showMessage('ERROR: Authentication Service could not find     __RequestVerificationToken');
            }
            var tokenParam = "__RequestVerificationToken=" + encodeURIComponent(token);

            $(document).ajaxSend(function (event, request, options) {
                if (options.hasContent) {
                    options.data = options.data ? [options.data, tokenParam].join("&") :     tokenParam;
                }
            });
        }

    };
});

Source: (StackOverflow)

How to pass data (selected item) to Durandal composed detail view?

I've started using (as of, a few hours ago) Durandal with the hope to manage views and allow composition within a single page - the previous approach, also using Knockout, was getting too unwieldy to maintain in a fat HTML file.

I've installed/setup Durandal and I can create views and viewmodels - however, I don't know how to get data into the viewmodel to use as a basis for the new viewmodel.

For instance, I have a "left nav bar" for selecting items - when an item is selected it updates a "selected item" observable in the current model, but it should also load the correct "detail view" in the right: because part of the reason to try Durandal to separate the components/views, this should come from a separate view/viewmodel.

I've read through the documentation including Composition and Using Composition, but the method as to how to pass data to the viewmodel is not clear to me. It seems like I could use a view with an existing model (in the current view/scope), but I'd really like to merely use some of the current model data (i.e. an id) to fetch the "real" model data in the view.

Thus, my questions;

  • How is passing initial data, such as the "selected item" to a viewmodel handled? I would prefer to use the declarative "compose:" binding, as that is what make KO .. KO.

  • Is this notion of having/passing initial data the correct way here, or is there a better alternative? I have seen "activeItem" vaguely mentioned, but the details/useage aludes me.


Update 1: I've found How do we share the data between views/Pass the data view to view, but the responses are lacking in actual implementation. I'd really like to not share the viewmodel between parent-child (distinct view/viewmodel pairs) and I'd like to use a declarative approach (no events). The parent need not know about the child, but the child needs to be fed data from the parent.


Update 2: While above I hinted only the "id" was required, I would like an approach that works with any basis object, which the router is not necessarily suitable for. Deep linking is not a concern in this case. However, if you feel the router is the way to approach this, post an argument for such (with details) as an answer and I'll at least give it an up-vote ..


Source: (StackOverflow)

Hot Towel/Durandal/Breeze.js: how to vertically secure data calls?

I'm new to the whole client-side SPA world. I'm using the above technologies, which seem quite promising. However, one huge snag that I can't get over easily is the lack of built-in security. I had to manually roll out the user authorization, which IMHO should be part of the framework.

Now that I have that sorted, I'm getting major headaches with vertical security: where one user is logged in but can easily access other users' info by changing a few parameters in the browser console. I could pass the userId with every call and then compare it with the one on the server, but I was hoping that there would be an overarching solution that doesn't pollute the breeze data calls with user ids.

For example, let's say there's a call from the data service like this:

function getItems(){        
         var query = breeze.EntityQuery.from('Items').expand("Person");
         return manager.executeQuery(query);
}

this will get all the items, not good. So let's limit by userId:

function getItems(userId){        
         var query = breeze.EntityQuery.from('Items').where("userId", "==", authentication.userId).expand("Person");
         return manager.executeQuery(query);
}

in the second example, we get the userId from the authentication service, which stored the userId when the user was logged in. However, a malicious user can easily go the browser console and change that value.

Of course, I could pass the userId using withParameters(...) and compare it with the current one on the server, but I'd have to do that for every call, which doesn't seem right. Is there a better way to secure calls with the trusted user id?


Source: (StackOverflow)

Phonegap 2.9.0, Windows Phone 8, Durandal 2.0, XAP runtime issue

We've been trying to get our PhoneGap 2.9, Durandal 2.0 application working on Windows Phone 8. We've been able to follow the steps to deploy the application to the emulator and to the device via visual studio. However, we have a problem with the application when it is built in VS and then the finished .xap is deployed to the device using the Application Deployment tool. The splash screen loads but then a black screen is shown.

We have corrected the path to www as suggested in this blog post http://mikaelkoskinen.net/durandal-phonegap-windows-phone-8-tutorial/ which got the app working on the emulator but not on device.

We have also tried to build the xap using phonegap build since it now supports windows phone 8 in beta - http://phonegap.com/blog/2013/10/18/2013-10-18-phonegap-build-support-for-windows-phone-8/. This has returned a similar result.

We believe that the main.js and index.html files are being loaded fine but the issue is somehow with requirejs and durandal 2.

Is anyone else using this combination of tools (or more recent versions) successfully and if so do they know where we're going wrong.


Source: (StackOverflow)

ValidateAntiForgeryToken with SPA architecture

I am trying to set Register and Login for Hot Towel SPA applicantion. I have created SimpleMembershipFilters and ValidateHttpAntiForgeryTokenAttribute based on the asp.net single page application template.

How do you get the

 @Html.AntiForgeryToken()

code to work in the Durandal SPA pattern.

Currently I have a register.html

<section>
    <h2 data-bind="text: title"></h2>

    <label>Firstname:</label><input data-bind="value: firstName" type="text"  />
    <label>Lastname:</label><input data-bind="value: lastName" type="text"  />
    <label>Email:</label><input data-bind="value: emailAddress" type="text"  />
    <label>Company:</label><input data-bind="value: company" type="text"  />
    <br />
    <label>Password:</label><input data-bind="value: password1" type="password" />
    <label>Re-Enter Password:</label><input data-bind="value: password2" type="password" />
    <input type="button" value="Register" data-bind="click: registerUser" class="btn" />
</section>

register.js:

define(['services/logger'], function (logger) {
    var vm = {
        activate: activate,
        title: 'Register',
        firstName: ko.observable(),
        lastName: ko.observable(),
        emailAddress: ko.observable(),
        company: ko.observable(),
        password1: ko.observable(),
        password2: ko.observable(),
        registerUser: function () {
            var d = {
                'FirstName': vm.firstName,
                'LastName': vm.lastName,
                'EmailAddress': vm.emailAddress,
                'Company': vm.company,
                'Password': vm.password1,
                'ConfirmPassword': vm.password2
            };
            $.ajax({
                url: 'Account/JsonRegister',
                type: "POST",
                data: d ,
                success: function (result) {
                },
                error: function (result) {
                }
            });
        },
    };


    return vm;

    //#region Internal Methods
    function activate() {
        logger.log('Login Screen Activated', null, 'login', true);
        return true;
    }
    //#endregion
});

In the $ajax call how do I pass the AntiForgeryToken? Also how do I create the token as well?


Source: (StackOverflow)

Durandal 2.0 - Child routers intended for nested menus?

I've building an app, and wanting to show a 2-tier menu, with both tiers always available. Durandal 2.0 introduced their new router, which supports 'child routers', which allow for easier deeplinking.

My question - Can I have my 'child' navigation routes permanently loaded (and a sub menu rendered when the parent is not active), or is the 'child router' design intended to lazy-load them to evaluate them once a deeplink is to be evaluated?

The Durandal examples show main navigation register a splat route, then when that view model is loaded/activated, the child router is registered.

E.g.: In the example provided with Durandal 2.0, the mian nev is registered in shell.js

router.map([
                { route: ['', 'home'], moduleId: 'hello/index', title: 'Validation test', nav: true },
                { route: 'knockout-samples*details',    moduleId: 'ko/index',               title: 'Knockout Samples',  nav: true, hash: '#knockout-samples' }
            ]).buildNavigationModel()
              .activate();

And the ko/index.js view model then registers the children (on activate())

var childRouter = router.createChildRouter()
        .makeRelative({
            moduleId:'ko',
            fromParent:true
        }).map([
            { route: '',                moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro' },
            { route: 'helloWorld',      moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro',      nav: true},
            { route: 'clickCounter',    moduleId: 'clickCounter/index',     title: 'Click Counter',         type: 'intro',      nav: true}
        ]).buildNavigationModel();

Whereas I'm looking to define my routes in one place, e.g.:

 var routes = [
   { route: ['', 'home'], 
        moduleId: 'hello/index', 
        title: 'Validation test', 
        nav: true },
   { route: 'knockout-samples*details',    
        moduleId: 'ko/index',
        moduleRootId: 'ko', // Custom property to make child routes easier              
        title: 'Knockout Samples',  
        nav: true, 
        hash: '#knockout-samples',
        childRoutes: [
            { route: '',                moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro' },
            { route: 'helloWorld',      moduleId: 'helloWorld/index',       title: 'Hello World',           type: 'intro',      nav: true},
            { route: 'clickCounter',    moduleId: 'clickCounter/index',     title: 'Click Counter',         type: 'intro',      nav: true}
        ]}
   ])

And the part I'm struggling with is registering the child routes, and have them evaulate correctly when navigating to them. (Rendering the menu would come later...)

// Load routes              router.map(routes.navRoutes).buildNavigationModel().mapUnknownRoutes(function(instruction)
{
    logger.logError('No Route Found', instruction.fragment, 'main', true);
});

// Try load child routes...
$.each(routes.navRoutes, function(index, parentRoute) {
     if (!parentRoute.childRoutes) {
                return;
            }

            var childRouter = router.createChildRouter()
                .makeRelative({
                    moduleId: parentRoute.moduleRootId,
                    fromParent: true // also tried false + non-splat routes...
                }).map(parentRoute.childRoutes).buildNavigationModel();
        });

I've encountered various errors in getting this nav to render. Mostly internal router.js errors when trying to calculate the hash (either from a non-activated parent, or the child) - so all hashes have been defined.

Once I've got it to map the navigation, the child routes don't seem to be accessible - they just load the main splat page without error.

So I'm wondering if I'm going about this the right way at all? (Registering all child routes up front, with the goal of being about to render a 2-tier menu).

I'm thinking the fallback is using something like the Durandal 1.2 answer about subrouting, using a combination of flat routing registration, custom 'isSameItem' function & computed observables to render the 2-tier navigation.


Source: (StackOverflow)

How to set up login view (user authentication) in SPA HotTowel template?

Some of the Single Page Application (SPA) templates in VS2012 MVC4 have built-in authentication. HotTowel SPA Template does not.

What is the proper way to implement user authentication (login screen) in SPA HotTowel? HotTowel uses Durandal JS, so I guess the question is really how to implement user authentication with Durandal JS


Source: (StackOverflow)

Framework similar to Prism for Knockout js

Microsoft made Prism framework for Silverlight and WPF. It looks great with its RegionManager and other stuff.

Is there any similar framework for Knockout?

Thanks.


Source: (StackOverflow)

Durandal.js - composition vs widget

i want create one div ( basically it will containt listbox) , and i want to use the div in different pages,

which is the best option to use in duarandal.js?

Composition

http://durandaljs.com/documentation/Using-Composition/

Widget

http://durandaljs.com/documentation/Creating-A-Widget/


Source: (StackOverflow)

Use Twitter Bootstrap button group as radio select with knockout bindings

This is working:

view.html

<div><input type="radio" name="radioPriority" data-bind="checked: priority" value="want" style="margin-top: -3px; margin-right: 3px;" />I want to</div>
<div><input type="radio" name="radioPriority" data-bind="checked: priority" value="need"  style="margin-top: -3px; margin-right: 3px;"/>I need to</div>

controller.js

function feedbackViewModel() {
    var self = this;
    self.priority = ko.observable("want");
    //lots of other stuff
}

As expected, when you select the second radio the priority observable's value changes to "need". However, I'd like to use a Twitter Bootstrap button group as a radio. Here is the HTML I have, but it does not change the observable as expected:

<span class="btn-group" data-toggle="buttons-radio">
    <button data-bind="checked: priority" type="button" class="btn" value="want">I want to</button>
    <button data-bind="checked: priority" type="button" class="btn" value="need">I need to</button>
</span>

update I have a jsfiddle going here: http://jsfiddle.net/a8wa8/6/ "priority1" is the standard radio selects and "priority2" is the bootstrap buttons.


Source: (StackOverflow)

WebAPI Model Binding from JSON

I am creating an application using Durandal, with WebAPI as the server. I have a KendoUI grid that displays the data from the server correctly and functions properly until the POST or PUT methods are called. Here is my GET method: enter image description here

and you can see that that data binds to the UI (used the data-bind extensibility in Durandal to change to kendo bindings): enter image description here

Then I edit the data in the Grid and it passes the changes inside the request to the server as you can see in this Fiddler result: enter image description here

On the server side I cannot get the data that is passed from the client to bind to anything I place as a parameter for the method on the POST or PUT. enter image description here

I realize this is a couple different technologies to troubleshoot (e.g. Durandal, KnockoutJs, Kendo DataBinding, and WebAPI) but I think the fundamentals are working, the data is retrieved and bound to the UI and it is posted back when changed, but the WebAPI endpoint cannot bind to the data.

How can I get the passed "models" array to bind through the ModelBinding structure in WebAPI?

UPDATE- Here is the helpful JSFiddle that gave me the correct Content-Type to add: http://jsfiddle.net/Xhrrj/1/

new kendo.data.DataSource({ transport: { read: { type: "POST", url: "../cccs/service.svc/SupplierSearch", contentType: "application/json; charset=utf-8", dataType: 'json'...

this is coming from the Telerik forum here


Source: (StackOverflow)

What is the purpose of durandal?

I'm already familiar with Knockout, Angular, Sammy, jQuery, a little breeze, and a little ember. The tutorials and getting started for Durandal all seem to be saying... well first add jQuery and maybe knockout.

Does it handle something entirely different than all of these? What need does it address such that it is likely to be used with knockout?

Is it just a hodgepodge of client side routing and ui components?

What does it do on its own conceptually?


Source: (StackOverflow)

Integrate the koGrid with the Durandal/HotTowel template

I work on an asp.net solution with the Durandal template.

I try to use the koGrid (https://github.com/Knockout-Contrib/KoGrid) which is compatible with knockout. When inserting this grid in a test page managed by Durandal, it doesn't work: the grid seems to be there but not correctly displayed.

We noticed that if we resize the window, then the grid adjust correctly.

Does anyone already succeed integrate this koGrid in a Durandal/HotTowel template?

Steps to reproduce the problem:

  • Create a new ASP.NET MVC project and choose the Durandal template
  • Add the koGrid in the project (available in Nuget)
  • Place this grid on a view and add dummy data
  • Run and display the view containing the grid

Here is a zip containing a little ASP.NET MVC project to reproduce the problem: https://www.dropbox.com/s/15rphyhkqp1h8py/KOGrid-HotTowelTemplate.zip

Thanks for your help.


Source: (StackOverflow)