On August 14, 2017 the ASP.NET team announced the release of ASP.NET Core 2 (along with .NET Standard 2 and .NET Core 2).
As you might have noticed everybody jumped in and upgraded their projects or at least their pet/test projects to v2.0; naturally, I felt the same urge and I did so for my current project. So this post is to chronicle my fairly painless upgrade with a little hiccup mainly due to the limited documentation. Keep in mind that Core 2.0 is still in preview even though is a final preview and quite stable.
You can find all sorts of blogs and instruction on how to upgrade, like here or here and here. Following all this information I worked my way to 2.0 as follows.
Keep in mind that this is “my” journey and yours might be different. I updated a Web application on a Windows machine with Visual Studio 2017 Community edition.
1. Install .NET Core 2.0 SDK
You can find it here. The process is very simple just follow the installer instructions.
2. Install Visual Studio 2017 preview version 15.3
You can find it here, actually it wasn’t as clear to me that this was still a preview version and I spent quite a bit of time trying to update my current version of VS 2017 to 15.3 without success (obviously!). So, Core 2.0 is available with VS2017 in preview only.
Go ahead and install it, it can live side-by-side with your stable version of VS with no problems.
This new version of Visual Studio can automatically detect if a new SDK is available (you just install it in step 1) and will offer you the ability to target the new framework. You can read more about it here.
3. Install the Microsoft.AspNetCore.All meta package
You can do so by way of Nuget with the dependency management tool offered by VS 2017:
Your project probably have several AspNet Core packages but after installing Microsoft.AspNetCore.All
you can remove most of them as they are already included in the AspNet.All meta package. You can find a list of the included packages here.
4. Target .Net Core 2 in all the projects in your solution
This is pretty easy, right click on the project and select properties, in the application dialog select ASP.NET Core 2 as target. This is for the web projects, if you have any other data or business project to support the web app, they should target .NET Standard 2.0:
At this point all is set, rebuild the project and run it….. but there is always something not exactly right. Here is what I found:
Content Error
After the steps taken above the first error was the following:
Duplicate ‘Content’ items were included. The .NET SDK includes ‘Content’ items from your project directory by default. You can either remove these items from your project file, or set the ‘EnableDefaultContentItems’ property to ‘false’ if you want to explicitly include them in your project file. For more information, see https://aka.ms/sdkimplicititems. The duplicate items were: ‘wwwroot\img\anonimus.png’
So I checked the .csproj file and it was listing several files and folders part of the content directory (wwwroot):
I thought that this was odd. The project was created with VS 2017 which automatically detects files in your project folder, so there is no need to actually list them in the .csproj file. Anyway, I deleted those entry, and the error above was gone. Great! The first one is done.
Identity Error (Cookies)
The next series of errors were all due to the cookies settings I had under Identity. Here is what the error looked like:

I spent quite a bit of time to figure this out. Everything pointed to this article in the docs, but as the title says, it let you configure cookies in the case where you do not have Identity set up, instead I did have Identity set up. So I went into the docs to see how to set up Identity with cookies, but that is old code that doesn’t work anymore with Core 2.0. In fact the previous article about cookies without Identity is explicitly saying that cookies have been removed from Identity.
Finally this Stackoverflow answer pointed me to this Github announcement from the ASP.NET team which in turns pointed me in the right direction here. And finally I found the solution. You can read the details in the post linked above, but now cookies has its own configuration extension to be placed in the ConfigureService
method of the Startup class:
services.ConfigureApplicationCookie(conf => { conf.LoginPath = "/Auth/Login"; conf.Events = new CookieAuthenticationEvents() { OnRedirectToLogin = async ctx => { if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200) { ctx.Response.StatusCode = 401; } else { ctx.Response.Redirect(ctx.RedirectUri); } await Task.Yield(); } }; });
For the rest of the Identity configuration (pasword, etc.) I moved it under Configue<IdentityService>
:
services.Configure<IdentityOptions>(config => { config.User.RequireUniqueEmail = true; config.Password.RequiredLength = 8; });
Now all works perfectly as before.
One last piece of the puzzle is UseIdentity()
in the Configure()
method which is deprecated, as it was just calling UseCookie 4 times (as noted on the ASP.NET team post). Instead use UseAuthentication()
here is my Startup class (I removed unrelated code):
public class Startup { //Removed for brevity public void ConfigureServices(IServiceCollection services) { services.AddIdentity<CCMUser, IdentityRole>() .AddEntityFrameworkStores<CCMContext>() .AddDefaultTokenProviders(); services.AddMvc() .AddJsonOptions(opt => { opt.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); }); services.ConfigureApplicationCookie(conf => { conf.LoginPath = "/Auth/Login"; conf.Events = new CookieAuthenticationEvents() { OnRedirectToLogin = async ctx => { if (ctx.Request.Path.StartsWithSegments("/api") && ctx.Response.StatusCode == 200) { ctx.Response.StatusCode = 401; } else { ctx.Response.Redirect(ctx.RedirectUri); } await Task.Yield(); } }; }); services.Configure<IdentityOptions>(config => { config.User.RequireUniqueEmail = true; config.Password.RequiredLength = 8; }); } public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory, CCMSeedData seeder, IHttpContextAccessor httpContext) { //Removed for brevity app.UseStaticFiles(); app.UseAuthentication(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); routes.MapSpaFallbackRoute( name: "spa-fallback", defaults: new { controller = "Home", action = "Index" }); }); } } }
And this is it. I hope this helps someone else like me that had a bit of hard times fixing the cookies setting issue with Identity.