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"));