ASP.NET 5 project content and beta8

This is the third post in a series about building Wedding Planner Tools Web App with ASP.NET 5, MVC 6 and Entity Framework 7. The previous post was about deploying the web app to Azure and CI. This is the first post of the series.

I decided to go through the project files and make some changes. The root solution folder has a file called global.json. This file sets the source code folders and the sdk to use. I went in here to change the sdk version to beta8 which is the latest version at the time of writing. I also want to change the runtime to CoreCLR -which is the new open source, cross-platform runtime- and architecture to x86. Visual Studio will ask you to download the new sdk when you save the file. If Visual Studio does not ask you to do that you can run:

dnvm install 1.0.0-beta8 -a x86 -r coreclr -OS win
dnvm list #to check installed runtimes

global.json

{
  "projects": [ "src", "test" ],
  "sdk": { 
    "version": "1.0.0-beta8", //changed this to beta8
    "runtime": "coreclr", //and this to coreclr
    "architecture": "x86"
  }
}

I’ve updated all the dependencies to beta8 also. Microsoft.AspNet.Server.IIS is no longer supported after beta7. I’ve added Microsoft.AspNet.Server.Kestrel https://github.com/aspnet/KestrelHttpServer instead of Microsoft.AspNet.Server.WebListener and Microsoft.AspNet.IISPlatformHandler http://wildermuth.com/2015/10/20/Upgrading_from_ASP_NET_5_Beta_7_to_Beta_8 instead of Microsoft.AspNet.Server.IIS. You need to do dnu restore after changing versions. I’ve also removed dnx451 from the frameworks list as I don’t want to support the old framework.

project.json

{
  "webroot": "wwwroot",
  "userSecretsId": "removed",
  "version": "1.0.0-*",

  "dependencies": {
    "EntityFramework.SqlServer": "7.0.0-beta8",
    "EntityFramework.Commands": "7.0.0-beta8",
    "Microsoft.AspNet.Mvc": "6.0.0-beta8",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-beta8",
    "Microsoft.AspNet.Authentication.Cookies": "1.0.0-beta8",
    "Microsoft.AspNet.Authentication.Facebook": "1.0.0-beta8",
    "Microsoft.AspNet.Authentication.Google": "1.0.0-beta8",
    "Microsoft.AspNet.Authentication.MicrosoftAccount": "1.0.0-beta8",
    "Microsoft.AspNet.Authentication.Twitter": "1.0.0-beta8",
    "Microsoft.AspNet.Diagnostics": "1.0.0-beta8",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-beta8",
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-beta8",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8", //new web server instead of WebListener
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-beta8", //instead of Microsoft.AspNet.Server.IIS
    "Microsoft.AspNet.StaticFiles": "1.0.0-beta8",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-beta8",
    "Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta8",
    "Microsoft.Framework.Configuration.Json": "1.0.0-beta8",
    "Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta8",
    "Microsoft.Framework.Logging": "1.0.0-beta8",
    "Microsoft.Framework.Logging.Console": "1.0.0-beta8",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta8"
  },

  "commands": {
    "web": "Microsoft.AspNet.Server.Kestrel", //this also changes to fire up Kestrel instead of WebListener
    "ef": "EntityFramework.Commands"
  },

  "frameworks": { //only using .net core
    "dnxcore50": { }
  },

  "exclude": [
    "wwwroot",
    "node_modules",
    "bower_components"
  ],
  "publishExclude": [
    "node_modules",
    "bower_components",
    "**.xproj",
    "**.user",
    "**.vspscc"
  ],
  "scripts": {
    "prepublish": [ "npm install", "bower install", "gulp clean", "gulp min" ]
  }
}

Doing this will break your project into a million places as it seems they’ve changed some core stuff from beta5 to 8 without backwards compatibility. Hey it’s in beta! And to be fair it’s only in 37 places. Let’s have a look at the problems I needed to fix. You can ignore any errors in the Migrations folder and just delete for now. I had to rebuild the migrations files as they were no longer matching the identity context in beta8 (see below). http://www.elanderson.net/2015/10/migration-from-asp-net-5-beta-7-to-beta-8/

  • Microsoft.Data.Entity.Relational.Migrations namespace is gone. Use Microsoft.Data.Entity.Migrations instead.
  • Microsoft.Data.Entity.Relational.Migrations.Builders is gone. It’s Microsoft.Data.Entity.Migrations.Operations.Builders now.

In account controller

  • _signInManager.SignOut() changes to _signInManager.SignOutAsync()
  • replace context.Database.AsRelational().ApplyMigrations(); with context.Database.Migrate();
  • replace Context.User.GetUserId() with HttpContext.User.GetUserId()

In manage controller

  • replaced Context.User with HttpContext.User

In startup.cs

  • replace FacebookAuthenticationOptions with FacebookOptions
  • replace MicrosoftAccountAuthenticationOptions with MicrosoftAccountOptions
  • replace app.UseErrorPage(ErrorPageOptions.ShowAll); with app.UseDeveloperExceptionPage();
  • replace app.UseErrorHandler(“/Home/Error”); with app.UseExceptionHandler(“/Home/Error”);
  • replace Microsoft.Framework.Runtime with Microsoft.Dnx.Runtime;
  • replace ConfigurationBuilder(appEnv.ApplicationBasePath) with ConfigurationBuilder().SetBasePath(appEnv.ApplicationBasePath)

And after all that effort I deleted the existing database on my dev machine then hit F5. I lunched it using the web command not IISExpress. I tried to register a user and got a nasty database error.

error : [Microsoft.AspNet.Diagnostics.ExceptionHandlerMiddleware] An unhandled exception has occurred: Value cannot be null.
Parameter name: key
System.ArgumentNullException: Value cannot be null.
Parameter name: key
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at Microsoft.Data.Entity.Migrations.Internal.MigrationsAssembly.c__DisplayClass3_0.b__0()
at Microsoft.Data.Entity.Internal.LazyRef`1.get_Value()
at Microsoft.Data.Entity.Migrations.Internal.MigrationsAssembly.get_Migrations()
at Microsoft.Data.Entity.Migrations.Internal.Migrator.d__13.MoveNext()
at Microsoft.Data.Entity.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.Data.Entity.RelationalDatabaseFacadeExtensions.Migrate(DatabaseFacade databaseFacade)
at WeddingPlannerTools.Controllers.AccountController.EnsureDatabaseCreated(ApplicationDbContext context) in C:\Work\Wedding Planner Tools\WeddingPlannerTools\src\WeddingPlannerTools\Controllers\AccountController.cs:line 448
at WeddingPlannerTools.Controllers.AccountController.d__10.MoveNext() in C:\Work\Wedding Planner Tools\WeddingPlannerTools\src\WeddingPlannerTools\Controllers\AccountController.cs:line 106
--- End of stack trace from previous location where exception was thrown ---
...rest removed for brevity...

Looking in the database I can see the database created but there’s not tables in it and no migrations have ran. I get this error while trying to update the database manually running the migration:

C:\Work\Wedding Planner Tools\WeddingPlannerTools\src\WeddingPlannerTools>dnx ef database update
Using context 'ApplicationDbContext'.
Using database 'removed' on server '(localdb)\mssqllocaldb'.
System.ArgumentNullException: Value cannot be null.
Parameter name: key
at System.Collections.Generic.Dictionary`2.Insert(TKey key, TValue value, Boolean add)
at System.Linq.Enumerable.ToDictionary[TSource,TKey,TElement](IEnumerable`1 source, Func`2 keySelector, Func`2 elementSelector, IEqualityComparer`1 comparer)
at Microsoft.Data.Entity.Migrations.Internal.MigrationsAssembly.c__DisplayClass3_0.b__0()
at Microsoft.Data.Entity.Internal.LazyRef`1.get_Value()
at Microsoft.Data.Entity.Migrations.Internal.MigrationsAssembly.get_Migrations()
at Microsoft.Data.Entity.Migrations.Internal.Migrator.d__13.MoveNext()
at Microsoft.Data.Entity.Migrations.Internal.Migrator.Migrate(String targetMigration)
at Microsoft.Data.Entity.Design.MigrationsOperations.UpdateDatabase(String targetMigration, String contextType)
at Microsoft.Data.Entity.Commands.Program.UpdateDatabase(String migration, String context)
at Microsoft.Data.Entity.Commands.Program.c__DisplayClass7_2.b__5()
at Microsoft.Dnx.Runtime.Common.CommandLine.CommandLineUtilsExtensions.c__DisplayClass0_0.b__0()
at Microsoft.Dnx.Runtime.Common.CommandLine.CommandLineApplication.Execute(String[] args)
at Microsoft.Data.Entity.Commands.Program.Main(String[] args)
Value cannot be null.
Parameter name: key

The migrations generated under beta5 where no longer matching the identity tables in beta8. So I removed the migrations folder and regenerated the initial migrations. http://aspnetmvc.readthedocs.org/projects/mvc/en/latest/tutorials/mvc-with-entity-framework.html. The commands seem to be a bit different in beta8:

dnx ef migrations add Initial
dnx ef database update

I can now see the database tables look as they should and the migration was successfully applied. I can also register and login with a new user in the web app. Hurray! Join us next time for the CI and deploying beta8 to azure adventure:)

links
* ASP.NET 5
* MVC 6
* Entity Framework 7
* previous post
* first post
* CoreCLR
* https://github.com/aspnet/KestrelHttpServer
* http://wildermuth.com/2015/10/20/Upgrading_from_ASP_NET_5_Beta_7_to_Beta_8
* http://www.elanderson.net/2015/10/migration-from-asp-net-5-beta-7-to-beta-8/
* http://aspnetmvc.readthedocs.org/projects/mvc/en/latest/tutorials/mvc-with-entity-framework.html
* http://davidfowl.com/diagnosing-dependency-issues-with-asp-net-5/
* http://www.codeproject.com/Articles/1005145/DNVM-DNX-and-DNU-Understanding-the-ASP-NET-Runtime
* https://github.com/aspnet/EntityFramework/wiki/Design-Meeting-Notes–August-20,-2015#relationship-api-naming
* https://msdn.microsoft.com/en-us/library/bb386947(v=vs.110).aspx

Leave a comment