Proven Style

Visual Studio 2015, Windows Authentication, and IIS Express

I finally upgraded my Visual Studio to 2015 and the transition has been pretty smooth! However, today I had an issue that took me a little while to solve. An Asp.net MVC web app that uses Windows Authentication, had been working great, but was suddenly gave me the following error:

Access is denied.

Description: An error occurred while accessing the resources required to serve this request. 
The server may not be configured for access to the requested URL. 

Error message 401.2.: Unauthorized: Logon failed due to server configuration.  
Verify that you have permission to view this directory or page based on the credentials 
you supplied and the authentication methods enabled on the Web server.  Contact the Web 
server's administrator for additional assistance.

I learn several things trouble shooting this. The first is that IIS Express configuration has moved from C:\Users\YourUserName\Documents\IISExpress\config\applicationhost.config out of the My Documents IISExpress folder and into the new .vs/configuration folder.

The second thing I was reminded of is that there is another place to edit properties for your project. I almost never press f4 on my project. I right click and go down to properties, but that is a very different set of properties than you get when you press f4.

The solution to my authorization issue was to go into the f4 project properties and set the following:

Anonymous Authentication – Disabled

Windows Authentication – Enabled

Apparently these properties update the IIS applicationHost.config directly. It adds the following to the config.

<location path="Project.Name.Here">
    <system.webServer>
        <security>
            <authentication>
                <windowsAuthentication enabled="true" />
                <anonymousAuthentication enabled="false" />
            </authentication>
        </security>
    </system.webServer>
</location>

It is irritating that you can’t save these somewhere in the .csproj file instead, but not a big deal once you know it is there.

Asp.net Identity User Names

I’ve been working on the web site for the 2014 Dallas Tech Fest and it has been such a fun project! A huge part of that is because of Brandon Ward’s amazing designs.

One unexpected challange was using twitter for the authorization. After 30 people had already signed up on the site with no issue, there was one user that was stuck in an authentication loop. Everytime he authenticated with twitter, he was asked to log in again.

It turns out he was the first user on the site, that I know of, to have a user name starting with an underscore. By default Asp.net Identity will only accept alphanumeric user names, and I was using his twitter username as the username for the site. You would have the same issue if you tried to allow an email as the username.

To fix it, I went into the constructor for the Account controller and created a new UserValidator.

public AccountController(UserManager<ApplicationUser> userManager)
{
    UserManager = userManager;
    UserManager.UserValidator = 
        new UserValidator<ApplicationUser>(UserManager)
            {AllowOnlyAlphanumericUserNames = false};
}

FFMPEG: Analyzing Audio and Video Files

ffmpeg -i c:\temp\video.mpg

-i is the input argument. By specifying an input, but no output, FFMPEG will inspect the file and give you lots of information such as:

Video

  • Encoding
  • Streams
  • Bit Rate
  • Aspect Ratio
  • Frame Rate

Audio

  • Encoding
  • Bit depth
  • Sampling Frequency
  • Channels

Example Output

ffmpeg.exe -i "C:\temp\audio\image\VIDEO_TS\VTS_01_1.VOB"                                                                                                          
ffmpeg version N-42347-g299387e Copyright (c) 2000-2012 the FFmpeg developers                                          
built on Jul  8 2012 15:44:54 with gcc 4.7.1                                                                         
configuration: --enable-gpl --enable-version3 --disable-w32threads --enable-runtime-cpudetect --enable-avisynth --enable-bzlib --enable-frei0r -enable libass --enable-libcelt --enable-libopencore-amrnb --enable-libopencore-amrwb --enable-libfreetype --enable-libgsm --enable-libmp3lame --enable-libnut --enable-libopenjpeg --enable-librtmp --enable-libschroedinger --enable-libspeex --enable-libtheora --enable-libutvideo --enable-libvo-aacenc --enable-libvo-amrwbenc --enable-libvorbis --enable-libvpx --enable-libx264 --enable-libxavs --enable-libxvid --enable-zlib                         
    libavutil      51. 64.100 / 51. 64.100                                                                               
    libavcodec     54. 33.100 / 54. 33.100                                                                               
    libavformat    54. 15.102 / 54. 15.102                                                                               
    libavdevice    54.  1.100 / 54.  1.100                                                                               
    libavfilter     3.  1.100 /  3.  1.100                                                                               
    libswscale      2.  1.100 /  2.  1.100                                                                               
    libswresample   0. 15.100 /  0. 15.100                                                                               
    libpostproc    52.  0.100 / 52.  0.100                                                                               
[mpeg @ 01edf700] max_analyze_duration 5000000 reached at 5016000                                                      
Input #0, mpeg, from 'C:\temp\audio\image\VIDEO_TS\VTS_01_1.VOB':                                                      
Duration: 00:03:06.80, start: 0.500000, bitrate: 6265 kb/s                                                           
Stream #0:0[0x1e0]: Video: mpeg2video (Main), yuv420p, 720x480 [SAR 8:9 DAR 4:3], 104857 kb/s, 30 fps, 30 tbr, 90k tbn, 60 tbc                                                                                                            
Stream #0:1[0x1c0]: Audio: mp2, 48000 Hz, stereo, s16, 128 kb/s                                                    
At least one output file must be specified                                                                             

FFMPEG: Where Is the Documentation?

It seems like the version of FFMPEG that I am using on projects is never that same version covered in the documentation on the website. You can get version specific documentation with FFMPEG from the console with the -h argument.

ffmpeg -h

You can dump the ffmpeg documentation to a text file for easier reading and searching by redirecting the output.

ffmpeg -h > c:\temp\ffmpeg.txt

You can also view a list of the supported codecs for your version of FFMPEG ffmpeg -codec > c:\temp\supportedCodecs.txt

Durandal: Bundling Multiple Spas With Weyland

Durandal.js: Get Started

By default Weyland expects a configuration file called weyland-config.js This caused me problems when I added multiple SPA pages to my solution. I wanted to create two different bundled files. One for each SPA.

Its not in the documentation, but you can specify the config file as an optional parameter --config. To make this work I also had to use the trick of appending %~dp0 to the config file name to include the full path of the config file. More information on %~dp0 can be found by typing for /? into a command prompt and reading the help. If you don’t do this weyland will not find your config file and continue to look for the default config.

In the end this worked for me.

weyland build --config "%~dp0customConfigFile1.js"
weyland build --config "%~dp0customConfigFile2.js"

Important

I was also reminded the hard way that JavaScript is case sensitive. This mean that node is also case sensitive. So I spent several hours trying to figure out why my bundling was not excluding the files I told it to exclude. It turns out I had a mismatch in the casing of a directory name. On the file system its name was capitalized, and in the config file I had used lowercase. It was very frustrating, but looking on the bright side, I was forced to learn how to debug node application using the console.

Durandal.js: Get Started

Deploying SQL Server Compact

I wrote an application that stores information in a SQL Server Compact database. It worked on my machine, but when QA installed it they received the following error:

Exception occured while configuring the databaseSystem.ArgumentException: 
Unable to find the requested .Net Framework Data Provider.  It may not be installed.
    at System.Data.Entity.Infrastructure.SqlCeConnectionFactory.CreateConnection(String nameOrConnectionString)
    at System.Data.Entity.Internal.LazyInternalConnection.Initialize()
    at System.Data.Entity.Internal.LazyInternalConnection.get_ProviderName()
    at System.Data.Entity.Internal.LazyInternalContext.InitializeContext()
    at System.Data.Entity.Internal.InternalContext.CreateObjectContextForDdlOps()
    at System.Data.Entity.Database.Exists()

I had added references to the following dll’s and they were in my bin directory:

  • System.Data.SqlServerCe.dll
  • System.Data.SqlServerCe.Entity.dll

but SQL Server Compact has other dependencies of which I was not aware. Namely SQL Server Compact needs its own native components. These can either come from the GAC or from a local copy installed in the applications file path.

Reproducing the issue

I had installed SQL Server Compact 4.0 on my machine several months back and didn’t realize these libraries were installed in the Gac on my machine. To reproduce the issue all I had to do was uninstalled SQL Server Compact 4.0.

Possible Solutions

  1. Install SQL Server Compact on the target machine for my application.

  2. Include a local copy of the SQL Server Compact native components with my application.

I chose option two because the whole idea of using SQLCE on this project was so that the users did not have to install a database.

First I had to get the Microsoft SQL Server Compact files

I installed Microsoft SQL Server Compact 4 on my machine again and in the C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Private folder are all the files I needed to deploy SqlCE with my application. After I got the files I needed I uninstalled SqlCE again.

Next I had to add a post build event

This copies two processor specific folders into the bin directory

if not exist "$(TargetDir)x86" md "$(TargetDir)x86"
xcopy /s /y "$(SolutionDir)..\Lib\Microsoft\SqlServerCe\x86\*.*" "$(TargetDir)x86"

if not exist "$(TargetDir)amd64" md "$(TargetDir)amd64"
xcopy /s /y "$(SolutionDir)..\Lib\Microsoft\SqlServerCe\amd64\*.*" "$(TargetDir)amd64"

Then I had to configure my Data Provider

<system.data>
    <DbProviderFactories>
        <remove invariant="System.Data.SqlServerCe.4.0" />
        <add name="Microsoft SQL Server Compact Data Provider 4.0" invariant="System.Data.SqlServerCe.4.0" description=".NET Framework Data Provider for Microsoft SQL Server Compact" type="System.Data.SqlServerCe.SqlCeProviderFactory, System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91" />
    </DbProviderFactories>
</system.data>

Lastly I needed an assembly redirect

Here is the error I encountered.

Could not load file or assembly 'System.Data.SqlServerCe, Version=4.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91' or one of its dependencies. The located assembly's manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Assembly Redirect

<dependentAssembly>
    <assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845dcd8080cc91" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1" />
</dependentAssembly>

Also noteworthy

I had already configured Entity Frame work to use SqlCE

<configSections>
    <section name="entityFramework" type="System.Data.Entity.Internal.ConfigFile.EntityFrameworkSection, EntityFramework, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
</configSections>

<connectionStrings>
    <add name="lvsData" connectionString="Data Source=C:\temp\appData.sdf;Max Database Size=4000;" providerName="System.Data.SqlServerCe.4.0" />
</connectionStrings>

<runtime>    
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="EntityFramework" publicKeyToken="b77a5c561934e089" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-5.0.0.0" newVersion="5.0.0.0" />
        </dependentAssembly>      
    </assemblyBinding>
</runtime>

<entityFramework>
    <defaultConnectionFactory type="System.Data.Entity.Infrastructure.SqlCeConnectionFactory, EntityFramework">
        <parameters>
            <parameter value="System.Data.SqlServerCe.4.0" />
        </parameters>
    </defaultConnectionFactory>
</entityFramework>

Using Apply in JavaScript

Today I went a little deeper into JavaScript! The problem I was facing was:

“How do I call a function and provide the arguments as an array instead of a comma separated list?”

My arguments were not know until runtime and there could be 0 to 4 arguments.

Function.prototype.apply() to the rescue

The apply() method lets you invoke a function with arguments as an array.

Here I am making a service call to stopStreaming for every vehicle in my array. This service call returns a promise that I push into an array. I can then use $.when.apply(this, promises).always() to wait for all the calls to return before I resolve my deferred.

Here is the full code.

vm.stopAll = function () {
  var deferred = $.Deferred();
  var promises = [];
  for (var i = 0; i < streamingVehicles.selectedVehicles.length; i++) {
     var vehicle = streamingVehicles.selectedVehicles[i];
     var promise = stopStreaming(vehicle);
     promises.push(promise);
  }

  $.when.apply(this, promises).always(function() {
     deferred.resolve();
  });

  return deferred.promise();
};

Incidentally, this is also a nice demonstration of using the promise pattern and the jQuery Deferred object.

Durandal - system.js

The Durandal core is made up of 8 modules. The system.js module provides core functionality to Durandal and it is also useful for any custom modules we write in our own apps.

Features

  • Logging
  • Debug mode
  • Object Type Testing
  • noop function
  • console.log polyfill
  • Object.keys polyfill
  • gets and sets the __moduleId__ of an object
  • Creates seam to use your preferred promise implementation

Architecture

Dependencies

  • requireJs
  • jQuery
  • No other durandal dependencies
  • Every module in durandal depends on system

Debug mode

system.debug(true); 
  • turns debug mode on
  • logs to the console and throw errors

Debug is off by default

system.debug(false);
  • turns debug mode off
  • no logging and no error throwing
  • uses the noop function until turned on

Interesting uses of JavaScript

Reflection

Object.keys(obj);

Returns an array of strings representing all the enumerable property names of the object

Make shortcuts to native JavaScript functions

 var nativeKeys = Object.keys,
     hasOwnProperty = Object.prototype.hasOwnProperty,
     toString = Object.prototype.toString,
     nativeIsArray = Array.isArray,
     slice = Array.prototype.slice;

The noop function (No Operation)

 var noop = function() { };

 Define a function that does nothing and set it as a default 
 to be replaced later during configuration if desired.

Arguments and parameters

You can refer to a functions parameters by name or by using the arguments array

Test the number of arguments and take different actions.

if (arguments.length == 1) {};

Refer to arguments by index

var first = arguments[0];       

Accept n number of arguments in a function.

function(obj) {         

    //do something with obj

    var rest = slice.call(arguments, 1);    
    for (var i = 0; i < rest.length; i++) {
        var source = rest[i];

        if (source) {
            //do something with the rest of the arguments
        }
    }
}

Public Api

Official system.js documentation is here >>

My summary of the api

version - durandal version
noop - no operation function
getModuleId - gets \_\_moduleId\_\_
setModuleId - sets \_\_moduleId\_\_
resolveObject - returns either the object or news it up from a function
debug - turns debug mode on and off
log - logs to console. noop by default
error - noop by default
assert - throws and error only in debug mode
defer - wraps the jquery defer.  Lets you replace it with a different implementation
guid - simple guid
acquire - returns modules from requireJs
extend - copies properties from n number of functions onto an object and returns the extended object
wait - waits specified number of seconds and returns a promise
keys- polyfills the getKeys behavior

is Functions to test object types

isElement
isArray
isObject
isBoolean
isPromise
isArguments
isFunction
isString
isNumber
isDate
isRegExp

Registering ASP.NET in IIS

Every time I have set up a new development environment in the last three years I have forgotten to register Asp.net with IIS. When I was first learning it would derail me for a quite a while. I have done it so many times now that I recognize what is going on when I see the errors, but it is still irritating. What was that command again? I am putting it here so I never have to Google it again!

aspnet_regiis

“Not a recognized command!” you say? Yes, you have to change directories into the .net version that you are using.

cd C:\Windows\Microsoft.NET\Framework\v4.0.30319

Now run the command.

What? That didn’t do it either? Don’t forget to add the install flag.

aspnet_regiis -i

Still not working? Don’t forget to start your command prompt as admin, and yes now you have to cd directories all over again into your .net version.

Setting Permissions for Your App Pool

How the heck do you reference an IIS application pool user when you need to give it access to a directory? I never can remember either! I flounder around trying different combinations. I question whether it needs quotes. I look for the right stack overflow question and never seem to find it. So here it is for you and I to remember. Don’t worry about the spaces and no need for quotation marks.

IIS AppPool\application pool name