Freitag, 17. Oktober 2014

strange behaviour: bootstrap.css vs. site.css

Trying to apply some specific bootstrap layouts turned into strange results. For example I simple wanted to horizontally centering an input box, or one of these special composite bootstrap controls combining an Input box and a button left or right side, within a md-12 row and got a layout result that aligns the Input box left side and the button right side. The Level of strangeness depends on the current size of the viewport e.g. mobile phone vs. desktop monitor.

To resolve this issue I did a lot of stackoverflow but without any result.

I ended up with a simple approach: Remove the site.css file from spa template completely and andapt the bündle.config then.

This "tweak" works for me and did not result in any new layout issues ;-): The bootstrap Composite controls are now aligned/centered as expected. 

Donnerstag, 16. Oktober 2014

ASP.NET MVC5: Organizing large solutions with areas

A working example by code snob:

http://codesnob.wordpress.com/2014/03/06/mvc-area-in-an-external-assembly/

and the source code (vs solution):

https://github.com/drydenmaker/PMMA-MVC


Advice:
Perhaps if you are encountering an jquery error on executing too then please check the _Layout.cshtml file. Scroll to bottom of file and look for this stuff:

 
@Scripts.Render("~/bundles/jquery")

@Scripts.Render("~/bundles/bootstrap")

@RenderSection("scripts", required: false)


If  the line @Scripts.Render("~/bundles/jquery"

) is missing then please insert this code snippet right before  
@Scripts.Render("~/bundles/bootstrap")

Then it will work properly !

Thanks.


Mittwoch, 5. März 2014

Radar: Using inheritance patterns to organize large jquery applications

Blog post by Alex Sexton

https://alexsexton.com/blog/2010/02/using-inheritance-patterns-to-organize-large-jquery-applications/

Radar: How to manage large jquery apps

Slides by Alex Sexton:

http://de.slideshare.net/SlexAxton/how-to-manage-large-jquery-apps

Quote: Script Loader RequireJS and curl.js

Addy Osmani:

"There are a number of great loaders for handling module loading in the AMD and CommonJS formats, but my personal preferences are RequireJS and curl.js. Complete tutorials on these tools are outside the scope of this book, but I can recommend reading John Hann's article about curl.js and James Burke's RequireJS API documentation for more."

http://msdn.microsoft.com/en-us/magazine/hh227261.aspx

Source: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modularjavascript


Quote: Developers fall back on variations of the module or object literal

Addy Osmani:

"Unlike some more traditional programming languages however, the current iteration of JavaScript (ECMA-262) doesn't provide developers with the means to import such modules of code in a clean, organized manner. It's one of the concerns with specifications that haven't required great thought until more recent years where the need for more organized JavaScript applications became apparent.
Instead, developers at present are left to fall back on variations of the module or object literal patterns, which we covered earlier in the book. With many of these, module scripts are strung together in the DOM with namespaces being described by a single global object where it's still possible to incur naming collisions in our architecture. There's also no clean way to handle dependency management without some manual effort or third party tools."
 
 

Quote: backbone.js vs. knockout.js

Addy Osmani:

"To conclude, I personally find KnockoutJS more suitable for smaller applications whilst Backbone’s feature set really shines when building anything non-trivial. That said, many developers have used both frameworks to write applications of varying complexity and I recommend trying out both at a smaller scale before making a decision on which might work best for your Project."

Source: http://addyosmani.com/resources/essentialjsdesignpatterns/book/#detailmvvm

Samstag, 1. März 2014

WebDeploy: Successfully registered and logged in a new user using VS2013 SPA template with local IIS 7.x

1. Try a Login with user: demo and password: demodemo
 
 
 
2. Register with user:demo and password: demodemo
 
 
 
3. Displaying the Home welcome page after logged in successfully
 
 
 
4. Showing the data Schema with some user data that was entered automatically during registering process
 
 
 

WebDeploy: Now working with local IIS 7.x on root deployment

Actually there still exists a Problem - for me - to get a proper solution working with a URL that directs to a IIS subfolder. This problem is currently addressed solely to forementioned "UNKNOWN ERROR OCCURED" error, when a user sends a request to http://localhost/VS2013SPATemplateOriginal.


I did a simple workaround then. Deploying the whole stuff to the IIS root folder "Default Websites" the VS2013 SPA template works properly. A user sends a request by entering http://localhost and the stuff is up and running as expected.

Therefore I will skip further investigations and proceed examining the VS2013 SPA template en detail from now.

Working steps for web deployment by using VS2013 Publishing functionality:

1.  Publishing Connection
 
 

2. Publishing settings 
 
 
 
...and the Folder structure within IIS 7.x
 
 
 
...and the folder structure on disk by Windows Explorer
 
 
 
 
 
...and the output by Visual Studio during publishing that ends successfully:
 
1>------ Erstellen gestartet: Projekt: VS2013SPATemplateDemo, Konfiguration: Release Any CPU ------
1> VS2013SPATemplateDemo -> C:\Daten\Projekte\VS2013\WebApp\VS2013SPATemplateDemo\VS2013SPATemplateDemo\bin\VS2013SPATemplateDemo.dll
2>------ Veröffentlichungsvorgang gestartet: Projekt: VS2013SPATemplateDemo, Konfiguration: Release Any CPU ------
2>"Web.config" wurde mithilfe von "C:\Daten\Projekte\VS2013\WebApp\VS2013SPATemplateDemo\VS2013SPATemplateDemo\Web.Release.config" in "obj\Release\TransformWebConfig\transformed\Web.config" transformiert.
2>Alle Dateien werden in das unten genannte temporäre Verzeichnis zum Packen/Veröffentlichen kopiert:
2>obj\Release\AspnetCompileMerge\Source.
2>C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v / -p C:\Daten\Projekte\VS2013\WebApp\VS2013SPATemplateDemo\VS2013SPATemplateDemo\obj\Release\AspnetCompileMerge\Source -u C:\Daten\Projekte\VS2013\WebApp\VS2013SPATemplateDemo\VS2013SPATemplateDemo\obj\Release\AspnetCompileMerge\TempBuildDir
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Deploy\Microsoft.Web.Publishing.MSDeploy.Common.targets(55,5): Warnung : Die angegebene DACPAC-Datei ist bereits vorhanden und wird überschrieben.
2>MSDeploy.dbDacFx (MSDeploy.dbDacFx) wird hinzugefügt.
2>Die Datenbank (C:\Daten\Projekte\VS2013\WebApp\VS2013SPATemplateDemo\VS2013SPATemplateDemo\obj\Release\AutoScripts\DefaultConnection_IncrementalSchemaOnly.dacpac) wird hinzugefügt.
2>Die automatische "ConnectionString" hat "obj\Release\AspnetCompileMerge\TempBuildDir\Areas\HelpPage\Views\Web.config" in "obj\Release\CSAutoParameterize\transformed\Areas\HelpPage\Views\Web.config" transformiert.
2>Die automatische "ConnectionString" hat "obj\Release\AspnetCompileMerge\TempBuildDir\Views\Web.config" in "obj\Release\CSAutoParameterize\transformed\Views\Web.config" transformiert.
2>Die automatische "ConnectionString" hat "obj\Release\AspnetCompileMerge\TempBuildDir\Web.config" in "obj\Release\CSAutoParameterize\transformed\Web.config" transformiert.
2>Alle Dateien werden in das unten genannte temporäre Verzeichnis zum Packen/Veröffentlichen kopiert:
2>obj\Release\Package\PackageTmp.
2>sitemanifest (sitemanifest) wird hinzugefügt.
2>Die Datenbank (data source=.\SQLExpress;initial catalog=VS2013SPATemplateDemoOriginalDB;integrated security=True;connect timeout=30) wird hinzugefügt.
2>Die Datei (Default Web Site\bin\App_global.asax.compiled) wird aktualisiert.
2>Die Datei (Default Web Site\bin\App_global.asax.dll) wird aktualisiert.
2>Die Datei (Default Web Site\PrecompiledApp.config) wird aktualisiert.
2>ACLs für den Pfad (Default Web Site) werden hinzugefügt.
2>ACLs für den Pfad (Default Web Site) werden hinzugefügt.
2>Die Veröffentlichung war erfolgreich.
2>Die Website wurde erfolgreich veröffentlicht http://localhost/
========== Erstellen: 1 erfolgreich, 0 fehlerhaft, 0 aktuell, 0 übersprungen ==========
========== Veröffentlichung: 1 erfolgreich, 0 Fehler, 0 übersprungen ==========
 
 

 

UnknownError: Hosting the VS2013 SPA template not in IIS root but subfolder

After deploying the VS2013 SPA template application including performed database schema changes the login resp. register form shows "unknown error occured" or "Unbekannter Fehler".
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
Because the deployment process was successful I tried then to dissect this issue: 
 
 

Freitag, 28. Februar 2014

SQLExpress: Grant priviliges to IIS / SQLExpress

SQLServer Express script for registering a specific user and connect it with IIS
Source: http://www.asp.net/mvc/tutorials/deployment/visual-studio-web-deployment/deploying-to-iis


use VS2013SPATemplateDemoOriginalDB
go
IF NOT EXISTS (SELECT name FROM sys.server_principals WHERE name = 'IIS APPPOOL\DefaultAppPool')
BEGIN
CREATE LOGIN [IIS APPPOOL\DefaultAppPool]
FROM WINDOWS WITH DEFAULT_DATABASE=[master],
DEFAULT_LANGUAGE=[us_english]
END
GO
CREATE USER [VS2013SPATemplateDemoOriginalDBUser]
FOR LOGIN [IIS APPPOOL\DefaultAppPool]
GO
EXEC sp_addrolemember 'db_owner', 'VS2013SPATemplateDemoOriginalDBUser'
GO
 


    

SQLServer Express: Default Instance Name

http://stackoverflow.com/questions/3586196/default-instance-name-of-sql-server-express

WebDeploy: LocalDB, SQLServer Express, ISS 7.x

After some research I came to conclusion that LocalDB that is per default provided with VisualStudo 2013 "built-in" storage does not work in conjunction with WebDeploy resp. IIS 7.x at all.

The VisualStudio 2013 auto-generated <magiccrypticnaming>.mdf database file is deployed successfully to IIS App_Data Folder without any database settings in the publishing dialog but it seems that is not loadable by the IIS infrastructure solely. I am a naif.

There it is, in black and white:

"LocalDB is not designed to work in IIS, so for your test environment you need to have SQL Server Express installed. If you are using Visual Studio 2010 SQL Server Express is already installed by default. If you are using Visual Studio 2012, you have to install it."

[Tom Dykstra, ASP.NET Web Deployment using Visual Studio: Deploying to Test ]

 

Otherwise using the database settings within publishing dialog and the deployment fails spitting out:
 
 
2>Die Datenbank (data source=(LocalDB)\v11.0;attachdbfilename=C:\inetpub\wwwroot\Demo\App_Data\aspnet-VS2013SPATemplateDemo-20140228031558.mdf;integrated security=True;connect timeout=30) wird hinzugefügt.        
2>C:\Program Files (x86)\MSBuild\Microsoft\VisualStudio\v12.0\Web\Microsoft.Web.Publishing.targets(4255,5): Fehler ERROR_EXCEPTION_WHILE_CREATING_OBJECT: Fehler des Webbereitstellungstasks. (Fehler beim Erstellen des Typs "Microsot.SqlServer.Dac.DacServices".  Weitere Informationen unter:
http://go.microsoft.com/fwlink/?LinkId=221672#ERROR_EXCEPTION_WHILE_CREATING_OBJECT.)        
2>Veröffentlichungsfehler der Bereitstellung.        
      


and additionally comparing to the windows event log:
 
 
 

Excursion: Prepareing IIS on WIN7 for use with VS2013 SPA Template

Steps:
1) Install IIS using Windows control Panel
2) Install WebDeploy 3.x for x64 for web deployment via VS2013 "publish" funcionality
Source Scott Guthries blog:
 
 
a) run cmd.exe as administrator
b) > net start msdepsvc
c) > cd: “c:\Program Files\IIS\Microsoft Web Deploy V3”
d) > msdeploy –verb:dump –source:appHostConfig,computername=localhost
 
Some output comes on cmd window. When there is "red output" check correct spelling of d) in Windows text editor because some quotation marks could appear on scene.

Set the current 4.0 Framework for Application Pool:

calling the IIS 7.x Panel:

> cmd.exe inetmgr

Click on ApplicationPool and set Framework 2.0 to 4.0

If you got an error like: error 500.19

then try this:


Performing

> cmd aspnet_regiis -i

does the trick for me ;-)

Diagram: VS2013 SPA template client side js startup sequence until app.initialize()

It's not visible at a glance how and in what kind of order the client side startup process of the web application comes up exactly when a user wants to start the VS2013 SPA template web application the first time with his user agent resp. browser.
 


As a basic principle the startup order is controlled by loading order specifications within the html stream that is sent as response from web server to requesting browsers. Once specified by the developer and stored in the corresponding Index.cshtml and subsequent html files e.g. _Login.cshtml, _Home.cshtml etc. the server side rendering process merges all information together in one single html output stream defining amongst others how requesting user agents e.g. IE11 should load relevant script and style libraries.

Under the hood the browser is probably trying to convert the html stream into an internal data structure that resides in browser's working memory. From that point the browser tries to parse and extract information to build a DOM (= Document Object Model) from the HTML markup specification and creates URL collections of loadable JavaScript and CSS Files etc. When the browser states ready with gathering and validating all relevant information the JavaScript Interpreter is invoked and will try to perform executeable code that he has detected within <script>-tags whether inline or by loadable JavaScript - libraries. Some sources stated that browsers perform execution of java script code as they proceed with parsing, that is to say, the parsing process pauses until a inline <script>[JavaScriptCode]</script> Code has been performed. On code return the parsing process proceeds.

Due to performance issues the browser first checks for existing resp. cached JS-files that matches the requested libraries. If there are no cached libraries available the browser exactly tries to load the required files in the specified order and populates step by step the execution stack within the runtime sandbox for the specific web application.

Further sources about Java Script code loading and execution:

http://stackoverflow.com/questions/8996852/load-and-execute-order-of-scripts
http://stackoverflow.com/questions/1795438/load-and-execution-sequence-of-a-web-page?rq=1
http://www.compuware.com/en_us/application-performance-management/products/ajax-free-edition/overview.html



 

Donnerstag, 27. Februar 2014

Diagram: Visual Studio 2013 SPA Template JS Library Declaration And Calling Stack

The calling stack of JavaScript based libraries e.g. jQuery, knockout.js and the template specific "app" js files is depending on the bundle order configuration in BundleConfig.cs and the declaration order within the markup of Index.cshtml.
 
Please find the attached diagram helpful showing this correlation:
  


 

Diagram: knockout.js MVVM in conjunction with ASP.NET Razor View architecture

Understanding the base structure of the knockout.js MVVM system in conjunction with the ASP.NET RazorEngine semi-static views.
 
MVVM consists of a View, ViewModel and (Data)Model approach where the DataModel is represented by the app.datamodel.js respectively ASP.NET controller/model concept, the ViewModel located in several app.XYZViewModel.js files e.g. app.LoginViewModel.js. The views are realized by razor engine based semi-static html files.
 


Please keep in mind that the diagram solely shows the logical correlation concerning the MVVM architectural pattern and does not reflect the deployment on runtime. The HTML content consisting of the HTML code of Index.cshtml and the partial HTML codes is assembled and rendered together into one single HTML Output stream and sent out to the requesting browser. The browser then collects the stream and builds a so called DOM model of it. DOM is the abbreviation for Document Object Model. The Dom is a hierarchical node structur that amongst others represents the loaded HTML stream. All subsequent automation actions operate on this DOM via JavaScript, jQuery and additional JS based librareis e.g. knockout.js.

knockout.js MVVM: ko.computed() widely used in template's js files

Manageing subsequent view models e.g. LoginViewModel, HomeViewModel etc. ko.computed() appears on the Scene amongst others.

 self.loading = ko.computed(function () {
        return self.view() === self.Views.Loading;
    });


 // Data
    self.Views = {
        Loading: {} // Other views are added dynamically by app.addViewModel(...).
    };

    self.view = ko.observable(self.Views.Loading);

    self.loading = ko.computed(function () {
        return self.view() === self.Views.Loading;
    });


    // Other operations
    self.addViewModel = function (options) {
        var viewItem = {},
            navigator;

        // Add view to AppViewModel.Views enum (for example, app.Views.Home).
        self.Views[options.name] = viewItem;

        // Add binding member to AppViewModel (for example, app.home);
        self[options.bindingMemberName] = ko.computed(function () {
            if (self.view() !== viewItem) {
                return null;
            }

            return new options.factory(self, dataModel);
        });

        if (typeof (options.navigatorFactory) !== "undefined") {
            navigator = options.navigatorFactory(self, dataModel);
        } else {
            navigator = function () {
                self.errors.removeAll();
                self.view(viewItem);
            };
        }

        // Add navigation member to AppViewModel (for example, app.NavigateToHome());
        self["navigateTo" + options.name] = navigator;
    };

knockout.js MVVM: ko.mapping.fromJS - advanced mapping technique not found in template's code

According to the knockout.js tutorial there is an advanced mapping technique available via plugin (knockout.mapping.js) to automatically map JSON based data that is retrieved/sent by AJAX calls to/from knockout viewmodel.

Tutorial: http://knockoutjs.com/documentation/plugins-mapping.html
Download: https://github.com/SteveSanderson/knockout.mapping/tree/master/build/output

This key word was not found yet within the template's code base. Therefore it is not used for now. The mapping is done "manually".

Code snippet from knockout.js tutorial.
var viewModel = ko.mapping.fromJS(data);

The creation of a viewmodel object is done explicitily in template:
var app = new AppViewModel(new AppDataModel());

Mittwoch, 26. Februar 2014

knockout.js MVVM: .extend keyword in several SPA template js files found

The implementation of knockout.js MVVM pattern uses the .extend - functionality e.g. in login.viewmodel.js on behalf of the knockout validation plugin. (knockout.validation.js). This plugin script also resides within the Visual Studio SPA template in Folder scripts.

Please refer to: https://github.com/Knockout-Contrib/Knockout-Validation


self.userName = ko.observable("").extend({ required: true });

unction LoginViewModel(app, dataModel) {
    // Private state
    var self = this,
        validationTriggered = ko.observable(false);

    // Private operations
    function initialize() {
        dataModel.getExternalLogins(dataModel.returnUrl, true /* generateState */)
            .done(function (data) {
                self.loadingExternalLogin(false);
                if (typeof (data) === "object") {
                    for (var i = 0; i < data.length; i++) {
                        self.externalLoginProviders.push(new ExternalLoginProviderViewModel(app, data[i]));
                    }
                } else {
                    self.errors.push("Unbekannter Fehler.");
                }
            }).fail(function () {
                self.loadingExternalLogin(false);
                self.errors.push("Unbekannter Fehler.");
            });
    }

    // Data
    self.userName = ko.observable("").extend({ required: true });
    self.password = ko.observable("").extend({ required: true });
    self.rememberMe = ko.observable(false);
    self.externalLoginProviders = ko.observableArray();
    self.validationErrors = ko.validation.group([self.userName, self.password]);

    // Other UI state
    self.errors = ko.observableArray();
    self.loadingExternalLogin = ko.observable(true);
    self.loggingIn = ko.observable(false);
...

Afte some CTRL-H search through the template's code it seems that there is no custom ko.extenders - instruction set found. According to the knockout.js tutorial it is possible to create custom extender functionality:

http://knockoutjs.com/documentation/extenders.html

knockout.js MVVM: No advanced "subscribe" concept In SPA template js files

When comparing the knockout.js tutorials to the template's js-files there is no "subscribe" key word detected. This is stated as "advanced" by the ko - tutorial.

Excursion: MVVM Pattern using knockout.js

http://knockoutjs.com/documentation/observables.html#mvvm_and_view_models

Sequence-Diagram: User is already logged in and refreshes the browser - (2)

Kind a weird the workflow in debug mode goes when authentication was successfully done and an apparently simply looking instruction "self.navigateToHome is called". The very first sequence of that shows some "magic" infrastructure diagram boxes that are "used" or called through the way down showing the home screen. I have to dissect this apparently knockout.js - based stuff in next Iteration.
 



Diagram: How UserAgent Interacts with OWIN authentication middleware (Draft)

 
 The interaction between an user agent e.g. ie11 and an OWIN authentication middleware enabled web server depends on the specific Controller that is called by the user agent.
 
When the OWIN authentication middleware detects an request to a Web.API based Controller that has no cookie resp. a cookie without any bearer token Information it sends back a 401 unauthorized status code to the browser that handles this issue with it's client side code.
 
If there is a call to an ASP.NET MVC Controller the 401 unauthorized status code is converted into 302 that is sent back to the browser with the URL for the login page.
 
Please refer to this excellent description published by Microsoft:
 
 
 

Sequence-Diagram: User wants to login with his credentials (username, password)

An "401 unauthorized" HTTP status code is sent back from server to browser, if there is no so called "bearer token" detected by OWIN cookie based middleware when the user tries to connect to the server the first time or did a logoff and refreshes his browser. The user agents client side code then will handle this issue and navigates the user to the login page. Because the authentication is working together with Web.API based AccountController in conjunction with a specific server side configuration there is no classic "302 - Redirect" HTTP status code like in ASP.NET MVC.

Because of the Single-Page-Application (SPA) - architecture a classic redirect to a new page is not appropriate but showing the container on the same page that contains all the login stuff to the user. This is actually controlled by JQuery resp. JavaScript.

At this point the user is enabled to perform a login with his credentials.

The sequence diagram shows the login process then:
 
 

Sequence-Diagram: User is already logged in and refreshes the browser - (1)

The attached simple sequence diagram shows the several steps when user that is already logged in refreshes his browser.
 
 

Draft: Refactoring app.Initialize() of app.viewmodel.js

When a user does his first attempt to connect to the SPA or refreshes his browser one of the first hookups is the call of self.initialize() of app.viewmodel.js by  app.initialize() within _run.js.

Some examination of the initialization code in conjunction with the corresponding AccountController on the server side made it clear to me that it is entirley about local or external authentication and some navigation instructions when the user tried an unauthorized access or is already logged in.

The very first draft tries to extract and encapsulate the authentication code and make the code more readable in terms of workflow processing.

file: app.viewmodel.js

var app = new AppViewModel(new AppDataModel());

function AppViewModel(dataModel) {

// Private state
var self = this

//-- register authentication management
var authentication = AppAuthentication;  

//Navigation behaviour when it comes to access denied authentication
function NavigationBehaviourAccessDenied(data) {
      self.navigateToLogin();
}

//Navigation behaviour when it comes to already logged in authentication
function NavigationBehaviourAlreadyLoggedIn(data) {
   if (data.userName) {
      self.navigateToLoggedIn(data.userName);
   } else {
      self.navigateToLogin();
   }
}  

authentication.OnAlreadyLoggedIn = NavigationBehaviourAlreadyLoggedIn;
authentication.OnAccessDenied = NavigationBehaviourAccessDenied;
//-- end of register authentication Management

...

self.initialize = function () {
    Authenticate();
}

function Authenticate() {
   var loginType = sessionStorage["associatingExternalLogin"];
   var fragment = AppAuthentication.GetFragment();
   

   if (typeof (loginType) === "undefined") {
        authentication.AuthenticateLocal();
   }

   if (loginType) {
        AuthenticateExternal();
   }

}
...
}


file: app.authentication.js

//application authentication
var AppAuthentication = {
    OnAlreadyLoggedIn: null,
    OnAccessDenied: null,  

    AuthenticateLocal: function()
    {
        var userInfoUrl = "/api/Account/UserInfo";
        var authenticateUser = function (accessToken) {
                    var headers;
                    if (typeof (accessToken) !== "undefined") {
                        headers = {
                            "Authorization": "Bearer " + accessToken
                        };
                    } else {
                        headers = AppAuthenticationHelper.GetSecurityHeaders();
                    }            
            $.ajax(userInfoUrl, {
                cache: false,
                headers: headers
            }).done(AppAuthentication.OnAlreadyLoggedIn).fail(AppAuthentication.OnAccessDenied);
        }; 
        return authenticateUser();    
    }};


file: app.authentication.helper.js

//application authentication helper
var AppAuthenticationHelper = { 
 GetFragment:  function ()
 {
  return GetFragmentItem();

  function GetFragmentItem() {
   if (window.location.hash.indexOf("#") === 0) {
    return AppAuthenticationHelper.ParseQueryString(window.location.hash.substr(1));
   } else {
    return {};
   }
  }
 },

 GetSecurityHeaders: function() {
  var accessToken = sessionStorage["accessToken"] || localStorage["accessToken"];
  if (accessToken) {
  return { "Authorization": "Bearer " + accessToken };
  }
  return {};
 },

 ParseQueryString: function (queryString) {
     var data = {},
         pairs, pair, separatorIndex, escapedKey, escapedValue, key, value;

     if (queryString === null) {
         return data;
     }

     pairs = queryString.split("&");

     for (var i = 0; i < pairs.length; i++) {
         pair = pairs[i];
         separatorIndex = pair.indexOf("=");

         if (separatorIndex === -1) {
             escapedKey = pair;
             escapedValue = null;
         } else {
             escapedKey = pair.substr(0, separatorIndex);
             escapedValue = pair.substr(separatorIndex + 1);
         }

         key = decodeURIComponent(escapedKey);
         value = decodeURIComponent(escapedValue);

         data[key] = value;
     }

     return data;
 }
};

JavaScript Design Patterns

Knowing design patterns help architecting larger JavaScript code structures. Helpful link about "Learning JavaScript Design Patterns" by Addy Osmani:

http://addyosmani.com/resources/essentialjsdesignpatterns/book/#modulepatternjavascript

e.g. object literal notation

var myObjectLiteral = {
 
  variableKey: variableValue,
  functionKey: function () {
  // ...
  }
};

Dienstag, 25. Februar 2014

~/Scripts/app/app.bindings.js

in file BundleConfig.cs in folder App_Start the item "~/Scripts/app/app.bindings.js" is configured but physically not existent in folder Scripts/app. Therefore I removed it from the bundles.Add routine.

The SPA still works fine after that micro refactoring.

before:
   
bundles.Add(new ScriptBundle("~/bundles/app").Include(
"~/Scripts/app/ajaxPrefilters.js",
"~/Scripts/app/app.bindings.js",
"~/Scripts/app/app.datamodel.js",
"~/Scripts/app/app.viewmodel.js",
"~/Scripts/app/home.viewmodel.js",
"~/Scripts/app/login.viewmodel.js",
"~/Scripts/app/register.viewmodel.js",
"~/Scripts/app/registerExternal.viewmodel.js",
"~/Scripts/app/manage.viewmodel.js",
"~/Scripts/app/userInfo.viewmodel.js",
"~/Scripts/app/_run.js"));

after:

bundles.Add(new ScriptBundle("~/bundles/app").Include(
"~/Scripts/app/ajaxPrefilters.js",
"~/Scripts/app/app.datamodel.js",
"~/Scripts/app/app.viewmodel.js",
"~/Scripts/app/home.viewmodel.js",
"~/Scripts/app/login.viewmodel.js",
"~/Scripts/app/register.viewmodel.js",
"~/Scripts/app/registerExternal.viewmodel.js",
"~/Scripts/app/manage.viewmodel.js",
"~/Scripts/app/userInfo.viewmodel.js",
"~/Scripts/app/_run.js"));