ASP.NET 5 Web API Put

As part of last week’s post on Aurelia’s Event Aggregator I needed a way to update existing contacts. This was a hole in my existing API and it was time to fill it.  See last week’s post for usage on the client side this post will only be covering the server side.

First off here is the code I added to the ContactsController in the API folder of my project. I thought the overview would be helpful a helpful context as we break down the different parts of the function.

[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] Contact updatedContact)
{
    if (updatedContact == null || updatedContact.Id != id)
    {
        return HttpBadRequest();
    }

    var contact = await GetContacts()
                        .Where(c => c.Id == id).FirstOrDefaultAsync();

    if (contact == null)
    {
        return HttpNotFound();
    }

    if (!ModelState.IsValid)
    {
        return new BadRequestObjectResult(ModelState);
    }

    _dbContext.Entry(contact).State = EntityState.Detached;
    _dbContext.Update(updatedContact);
    updatedContact.UserId = User.GetUserId();  
    await _dbContext.SaveChangesAsync();

    return CreatedAtRoute("GetById",
                          new
                          {
                              controller = "Contacts",
                              id = updatedContact.Id
                          },
                          updatedContact);
}

First off the Update function is decorated to only handle HttpPut actions with an ID. The function itself of course requires an ID. The FormBody attribute on the updatedContact parameter tells the framework to build a contact object from the request body.

[HttpPut("{id}")]
public async Task<IActionResult> Update(int id, [FromBody] Contact updatedContact)

Next if the updatedContact was unable to be built from the request body or if the ID passed to the update function doesn’t match the ID in the updatedContact then a bad request status is returned.

if (updatedContact == null || updatedContact.Id != id)
{
    return HttpBadRequest();
}

Next I query the database for a matching contact. This query is limited to the current users so it should help prevent a contact for the wrong user being updated. If no matching contact is found then not found status is returned.

var contact = await GetContacts()
                    .Where(c => c.Id == id).FirstOrDefaultAsync();

if (contact == null)
{
    return HttpNotFound();
}

Next check to see if the mode state is valid and return bad request object result if it is not.

if (!ModelState.IsValid)
{
    return new BadRequestObjectResult(ModelState);
}

This next bit was a little bit of a challenge. Since entity framework was queried to see if the updated contact already exists I was getting an error when trying to use the DB context’s update function. One way to address this error would have been to update the contact pulled from the database with the values from the updated contact from the request body. If I had of gone this route something like automapper would have made the job fairly easy. Instead I used the DB context entry on the contact returned from the database to set its state to detached which tells the context to stop tracking that item. After that the context’s update function worked like a charm and I could save changes based on the updatedContact parameter.

_dbContext.Entry(contact).State = EntityState.Detached;
_dbContext.Update(updatedContact);
updatedContact.UserId = User.GetUserId();
await _dbContext.SaveChangesAsync();

Finally I returned the client the updated contact. This is the same thing I did for post and may or may not be the best thing to do on a put.

return CreatedAtRoute("GetById",
                      new
                      {
                          controller = "Contacts",
                          id = updatedContact.Id
                      },
                      updatedContact);

I am not sure how much of this is the “correct” way to handle a put. After seeing how some of this is handled when using razor with anti-forgery tokens and the ability to only allow certain fields to be updated this implementation seems lacking. This is a jumping off point, but I need to do more research on how to properly secure an API.

Aurelia’s Event Aggregator

Aurelia’s event aggregator is a lightweight pub/sub messaging system which I am going to make use of to update my contact list with edits to a contact are saved.

I started by creating the class that would be used to publish messages to the event aggregator. In this case the message is for notification that a contact was updated and will contain the contact that was updated.

export class ContactUpdatedMessage {
    constructor(contact) {
        this.contact = contact;
    }
}

Detail.js is the view model for editing of contacts needs imports for the new ContactUpdatedMessage and Aurelia’s event aggregator. The ContactUpdatedMessage is in the Aurelia folder of the application’s wwwroot which is why it has “Aurelia/” and not just ContactsUpdatedMessage in the from portion of the import statement.

import {EventAggregator} from 'aurelia-event-aggregator';
import {ContactUpdatedMessage} from 'Aurelia/ContactUpdatedMessage';

Add EventAggregator to the inject decorator of the details class. Next the constructor needs to be changed for injection of the event aggregator. Ignore the fact that the web API url is hardcoded. I know there is a better way to handle the url, but I have not had time to look into it yet. In the next to last line a reference to the injected event aggregator is saved.

@inject(HttpClient, EventAggregator)
export class Detail{

    constructor(http, eventAggregator){
        http.configure(config => {
            config
              .useStandardConfiguration()
              .withBaseUrl('https://localhost:18907/api/');
        });

        this.http = http;
        this.eventAggregator = eventAggregator;
    }

When a user clicks save on a contact the submit function is called. The call to the web API using fetch is an existing part of the submit function. The new bit is the call to the eventAggregator’s publish function with new ContactUpdatedMessage using the edited contact.

submit() {
    this.http.fetch('contacts/' + this.contact.Id, 
                    { method: 'put', 
                      body: json({id: this.contact.Id, 
                                  name: this.contact.Name}) })
             .then(response => response.json())
             .then(contact => this.contact = contact)
             .catch(e => {
                    console.log(e);
                    this.postResult = e.status + '-' + e.statusText;
                    });

    this.eventAggregator.publish(new ContactUpdatedMessage(this.contact));
}

List.js needs to be a subscriber for the ContactsUpdateMessage. The class needs the same new imports and injection of the event aggregator as the detail class. In the list class instead of saving a reference to the event aggregator its subscribe function will be used to listen for the contact updated messages. The second part of the subscribe function takes a function to be called when a contact updated message is received. In this example when a contact updated message is received the function finds the proper contact and replaces it with the updated version.

import {EventAggregator} from 'aurelia-event-aggregator';
import {ContactUpdatedMessage} from 'Aurelia/ContactUpdatedMessage';

@inject(HttpClient, EventAggregator)
export class List{
    contacts = [];

    constructor(http, eventAggregator){
        http.configure(config => {
            config
              .useStandardConfiguration()
              .withBaseUrl('https://localhost:18907/api/');
        });

        this.http = http;
        eventAggregator.subscribe(ContactUpdatedMessage, message => {
            let updated = this.contacts
                              .filter(contact => contact.Id == message.contact.Id)[0];
            Object.assign(updated, message.contact);
        });
    }

}

With the above changes any edits to a contact will be reflected in the contact list as soon as the contact is saved.

Aurelia Beta and the Unexpected Token

Aurelia hit beta on November 16th. The team kicked off the beta the following five days of blog post.

Day 1 – The Beta is Here!
Day 2 – Plugins
Day 3 – Documentation
Day 4 – Ecosystem
Day 5 – Aurelia Interface

ASP.NET 5 hit release candidate 1 two days after Aurelia hit beta and writing the migration from beta 8 to rc1 was my priority and then I took Thanksgiving week off. To get back in the swing of things I rebuild my contacts application with ASP.NET RC1.

After getting the ASP.NET parts done and moved on to rebuilding the Aurelia portions. Using my original blog on getting started with Aurelia and the new Aurelia getting started guide I got everything installed.

As you may have guessed it was a no go. I kept getting an unexpected token on @inject on any view model that was using dependency injection. I did a lot of comparing the working version to the non-working version but the files were identical.

After a quick google I found the answer on stack overflow. The problem was the babel options which can be found in config.js in the wwwroot folder. Here is the section in question from my pre-beta application.

babelOptions: {
  "optional": [
    "runtime",
    "optimisation.modules.system"
  ],
  "stage": 0
}

And the new version.

babelOptions: {
  "optional": [
    "runtime",
    "optimisation.modules.system"
  ]
}

As Jeremy Danyow points out in the above stack overflow answer either es7.decorators needs added to the optional section or to set the stage option to 0. I ended up with the following based on the new samples from the Aurelia team, which also matches the answer from Jeremy.

babelOptions: {
  "optional": [
    "es7.decorators",
    "es7.classProperties",
    "runtime",
    "optimisation.modules.system"
  ]
}

 

Migration from ASP.NET 5 Beta 8 to RC1

ASP.NET 5 release candidate 1 was released on November 18th. Read the announcement here.  The announcement happened during Connect where Microsoft talk about a ton of cool stuff. Hanselman did a great summary here.

One of the big things (for some people) is that with RC1 ASP.NET 5 now has a go live license which means Microsoft will provide support. One thing to note about the go live license is if a RC2 is released the support will immediately drop for RC1 and any application will need to be upgraded to RC2 before getting support. Once the final release is out it will be supported for years it is only the go live license that ends support as soon as the next version with a go live license is released.

To get all the new bits installed, including tooling updates for Visual Studio, head over to https://get.asp.net/. This is one of my favorite parts of the RC. The site will show you the appropriate links for install for the OS you are running on. Just make sure you hit the ASP.NET 5 RC install and not ASP.NET 4.6. The install link will kick you over to the install page of the docs site which provides step by step instructions in addition to the download link for the update.

After completing the install open global.json and update the sdk version to rc1-final.

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-rc1-final"
  }
}

Next is project.json the dependencies section as usual. In addition to the change from beta8 to rc1-final a few packages have changed names.

  "dependencies": {
    "EntityFramework.Commands": "7.0.0-rc1-final",
    "EntityFramework.MicrosoftSqlServer": "7.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Cookies": "1.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Facebook": "1.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Google": "1.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.MicrosoftAccount": "1.0.0-rc1-final",
    "Microsoft.AspNet.Authentication.Twitter": "1.0.0-rc1-final",
    "Microsoft.AspNet.Diagnostics": "1.0.0-rc1-final",
    "Microsoft.AspNet.Diagnostics.Entity": "7.0.0-rc1-final",
    "Microsoft.AspNet.Identity.EntityFramework": "3.0.0-rc1-final",
    "Microsoft.AspNet.IISPlatformHandler": "1.0.0-rc1-final",
    "Microsoft.AspNet.Mvc": "6.0.0-rc1-final",
    "Microsoft.AspNet.Mvc.TagHelpers": "6.0.0-rc1-final",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-rc1-final",
    "Microsoft.AspNet.StaticFiles": "1.0.0-rc1-final",
    "Microsoft.AspNet.Tooling.Razor": "1.0.0-rc1-final",
    "Microsoft.Extensions.CodeGenerators.Mvc": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.FileProviderExtensions": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.Json": "1.0.0-rc1-final",
    "Microsoft.Extensions.Configuration.UserSecrets": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Console": "1.0.0-rc1-final",
    "Microsoft.Extensions.Logging.Debug": "1.0.0-rc1-final",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-rc1-final"
  }

EntityFramework.SqlServer is not EntityFramework.MicrosoftSqlServer. Configuration and Logging moved from Mircosoft.Framework to Microsoft.Extensions.

Startup.cs had another set of changes this round. First up some namespace changes which are mostly the move from Microsoft.Framework to Microsoft.Extenstions.

Before:
using Microsoft.Dnx.Runtime;
using Microsoft.Framework.Configuration;
using Microsoft.Framework.DependencyInjection;
using Microsoft.Framework.Logging;

After:
using Microsoft.Extensions.PlatformAbstractions;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;

In the Configure function I was able to enable browser link and it be useable and a slight change to the UseDatabaseErrorPage call.

Before:
if (env.IsDevelopment())
{
    //app.UseBrowserLink();
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage(DatabaseErrorPageOptions.ShowAll);
}

After:
if (env.IsDevelopment())
{
    app.UseBrowserLink();
    app.UseDeveloperExceptionPage();
    app.UseDatabaseErrorPage();
}

Finally, a static void main was added for the entry point of the application. Pretty sure the app will still run without this change, but it is included when adding a new application with the updated templates.

// Entry point for the application.
public static void Main(string[] args) => WebApplication.Run<Startup>(args);

Entity framework 7 only had a couple of breaking issue which seem to be the team finishing up some API tweaks. Here are the renames I hit this version.

Migration related renames
Old New
Index HasIndex
ForeignKey HasForeignKey
Annotation HasAnnotation

Something else I hit was an unexpected port when I ran the application. There is a new launchSettings.json file in the Project folder which is where things like port can be changed. It also has settings for IIS and IIS Express.

Finally make sure and check out the release page and the breaking changes page for this release.

Combine Views with Aurelia

In my contacts sample application, I wanted to combine the list and detail views for a better user experience. Turns out that Aurelia’s contact sample application does this and a few other things I want to try out in the future so I used it as a guide.

Starting with the my app.html with the nav related markup.

<template>
    <require from="lib/bootstrap/dist/css/bootstrap.css"></require>
    <require from="Aurelia/list" as="contact-list"></require>

    <div class="page-host">
        <contact-list class="col-md-4"></contact-list>
        <router-view class="col-md-8"></router-view>
    </div>
</template>

The require statement tells Aurelia to load the specified resource. The as attribute of require is optional and defines how the imported resource will be accessed. By using the as attribute what would have been a list custom element is now a contact-list custom element.

The other change to this file was to render the contact-list element in addition to the router-view. Columns classes were assigned to both since they will be sharing view space now.

In app.js the configuration of the routes had to be adjusted. Before the blank route rendered the list view, but now the list view is rendered outside of the router so the detail route needed to be rendered for the blank route. The original route with an id still exists and is used to load the proper details when an item is selected from the contact list.

export class App {
    configureRouter(config, router) {
        config.title = 'Contacts';
        config.map([
            {
                route: ['', 'detail/:id'],
                name: 'detail',
                moduleId: './Aurelia/detail',
                nav: false,
                title: 'Detail'
            }
        ]);

        this.router = router;
    }
}

After the above changes I tried a test and got a detail view but no list view. After some digging I found out that the activate function was not being called on the list class. Turns out that since list view is being rendered outside of a router that the activate portion of the lifecycle does not happen. Since activate is where I was hitting my ASP.NET 5 web api no contacts were being loaded. The fix was to use the created portion of the lifecycle instead of activate.

created(){
    return this.http.fetch('contacts')
       .then(response => response.json())
       .then(contacts => this.contacts = contacts);
}

After that change all worked as I hoped it would. This is just a basic example of what is a very powerful concept. The more I learn about Aurelia the more I like it.

Community

This is a departure from the types of post I normally do so please bear with me.

Early in my career I followed some bad advice that steered me away from the great development community that Nashville has to offer. Following that advice is the thing I regret most in my career. That advice is what lead me down the path of the dark matter developer that I mention in the about page for this site.

I spent a lot of years working very hard at my job with my only interaction with other developers being my co-workers. It was comfortable and the easy thing to do. I did not realize how much I was limiting myself. Limiting my growth as a developer, but more so limiting my personal development.

Thankfully this is not where the story ends. A lot of life happened and I ended up being exposed to a group of people who loved being involved with the Nashville development community. They were excited by what they do and involved at levels I had never seen. It was a breath of fresh air and a turning point for me. I am a shy and introverted person but exposure to the community helped me to start getting passed my shyness.

To start I began attending the local .Net User Group. For me this user group was a great place to start. I could listen to the speaker and slip out after the talk was over without too much interaction with others. Over time interactions got easier and I met a ton of great people. User groups are a great for learning new things, but I have come to realize that the connections made with other people are by far the most valuable benefit. I have even expanded to some social only events like the Geek Social.

If you are not involved with the community in your area I encourage you to start. Get to know your fellow developers. They are the greatest resource to be found.

If you need more convincing check out this content from Scott Hanselman and Rob Conery.

Adding Authorize to a Web API

In the post Aurelia with ASP.NET 5 and Web API I removed the authorize attribute from the contacts API controller to reduce complexity. That change simplified some things but it also effectively made the API useless for multiple users.

In this post I am going to add back in authorization as well as making sure a user identifier is used in contact creation and retrieval. Also note that this authorization is taking place in the web application not via the API so the user must logged in via the main site before access to the API is allowed.

All the changes are in the controller class that needs to be protected. First add two new namespaces.

using Microsoft.AspNet.Authorization;
using System.Security.Claims;

Microsoft.AspNet.Authorization is where the Authorize attribute is found and System.Security.Claims contains an extension method on to the User class to make it easy to get the user ID.

Next add the Authorize attribute to the class level if the whole class should require authorization or at the function level if only some functions need authorization.

[Authorize]
[Route("api/[controller]")]
public class ContactsController : Controller

Next add a filter to the query for contacts to makes sure a user only sees their contacts. User is provided by the Controller base class and the GetUserId is the extension method from System.Security.Claims namespace referenced above.

private IQueryable<Contact> GetContacts()
{
    var contacts = from c in _dbContext.Contacts
                             .Include(c => c.Addresses)
                             .Include(c => c.EmailAddresses)
                             .Include(c => c.PhoneNumbers)
                   where c.UserId == User.GetUserId()
                   select c;
    return contacts;
}

In the create function, which handles HTTP post, the contact user ID must be set based on the current user before the contact is added to the DB context.

[HttpPost]
public async Task Create([FromBody] Contact contact)
{
    if (contact == null)
    {
        return HttpBadRequest();
    }

    if (!ModelState.IsValid)
    {
        return new BadRequestObjectResult(ModelState);
    }

    contact.UserId = User.GetUserId();

    _dbContext.Add(contact);
    await _dbContext.SaveChangesAsync();
    return CreatedAtRoute("GetById",
                          new
                          {
                              controller = "Contacts",
                              id = contact.Id
                          },
                          contact);
}

Aurelia Routing with a Parameter

A post covering the same concepts but with updated versions of ASP.NET and Aurelia can be found here.

I have spent some time building out the client side of my contacts application using Aurelia. For a starting point with Aurelia check out my previous post on Aurelia with ASP.NET 5 and Web API and Start Aurelia from an ASP.NET 5 Controller. In this post I am going to cover passing a parameter via routing.

Keep in mind I am serving this application from ASP.NET 5 and all the Aurelia related files are in the wwwroot folder of my ASP.NET 5 project. App.html and app.js in wwwroot with the remaining Aurelia files in an Aurelia folder.

project

In app.js a new route was added for the detail view. Make special note that the new route expects an id parameter.

import 'lib/bootstrap/dist/js/bootstrap';

export class App {
    configureRouter(config, router) {
        config.title = 'Contacts';
        config.map([
            {
                route: ['', 'list'],
                name: 'list',
                moduleId: './Aurelia/list',
                nav: true,
                title: 'List'
            },
            {
                route: 'add',
                name: 'add',
                moduleId: './Aurelia/add',
                nav: true,
                title: 'Add'
            },
            {
                route: 'detail/:id',
                name: 'detail',
                moduleId: './Aurelia/detail',
                nav: false,
                title: 'Detail'
            }
        ]);

        this.router = router;
    }
}

In list.html the contacts need to be rendered with an anchor that will lead to the proper detail view. To accomplish this Aurelia has a route-href custom attribute that can be used with an anchor.

<template>
    <div>
        <ul class="list-group">
            <li repeat.for="contact of contacts" class="list-group-item">
                <h4 class="list-group-item-heading">
                    <a route-href="route: detail; 
                                   params.bind: {id:contact.Id}">
                        ${contact.Name}
                    </a>
                </h4>
                <p repeat.for="emailaddress of contact.EmailAddresses"
                   class="list-group-item-text">
                    <a href="mailto:${emailaddress.Address}">
                        ${emailaddress.Address}
                    </a> 
                </p>
            </li>
        </ul>
    </div>
</template>

With route-href route, set to detail above, defines the name of the route from the route config. Parms.bind creates an object with an id property which is bound to the id defined on the route. Any property on the object that does not have a in the route definition will be added to the query string.

When one of the routing links is clicked then on activation detail.js queries the Web API for the contact details based on the id in the parms.

import {inject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import 'fetch';

@inject(HttpClient)
export class Detail{
    contact = '';

    constructor(http){
        http.configure(config => {
            config
              .useStandardConfiguration()
              .withBaseUrl('https://localhost:13102/api/');
        });

        this.http = http;
    }

    activate(params) {
        return this.http.fetch('contacts/' + params.id)
          .then(response => response.json())
          .then(contact => this.contact = contact);
    }
}

No real new concepts in the above. On active the Web API is called and the resulting json is used to populate a contact property.

The detail view then uses the contact property to bind to the contact information.

<template>
    <div>
        <div class="row">
            <label class="label label-info">${contact.Id}</label>
        </div>
        <div class="row">
            <label class="col-sm-1 control-label">Name</label>
            <div class="col-sm-11">
                <p class="control-label">${contact.Name}</p>
            </div>
        </div>
        <div class="row">
            <label class="col-sm-1 control-label">Addresses</label>
            <div class="col-sm-11">
                <p repeat.for="address of contact.Addresses"
                   class="list-group-item-text">
                    ${address.City}, ${address.State}
                </p>
            </div>
        </div>
        <div class="row">
            <label class="col-sm-1 control-label">Email Addresses</label>
            <div class="col-sm-11">
                <p repeat.for="emailaddress of contact.EmailAddresses"
                   class="list-group-item-text">
                    <a href="mailto:${emailaddress.Address}">${emailaddress.Address}</a>
                </p>
            </div>
        </div>
        <div class="row">
            <label class="col-sm-1 control-label">Phone Numbers</label>
            <div class="col-sm-11">
                <p repeat.for="phone of contact.PhoneNumbers"
                   class="list-group-item-text">
                    ${phone.Number}
                </p>
            </div>
        </div>
    </div>
</template>

The above results in the following view.

contactDetailView

Migration from ASP.NET 5 Beta 7 to Beta 8

ASP.NET 5 beta 8 was released on October 15th. Read the main announcement here and the entity framework 7 specific announcement here.

The tooling update can be found here. The relevant files are either DotNetVersionManager-x64.msi or DotNetVersionManager-x86.msi depending on what your system supports and WebToolsExtensionsVS14.msi.

The above gets everything needed for use inside Visual Studio for more details on other options check out Microsoft’s documentation for getting started with Windows, Mac or Linux.

After completing the upgrade open global.json and update the sdk version to beta 8.

{
  "projects": [ "src", "test" ],
  "sdk": {
    "version": "1.0.0-beta8"
  }
}

Next up is project.json which has more changes than other migrations due to the move from hosting in Helios to Kestrel. First update beta7 to beta8 in the dependencies section.

  "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.IISPlatformHandler": "1.0.0-beta8",
    "Microsoft.AspNet.Server.Kestrel": "1.0.0-beta8",
    "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.Framework.Logging.Debug": "1.0.0-beta8",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0-beta8"
  }

Note that Microsoft.AspNet.Server.IIS and Microsoft.AspNet.Server.WebListener have been removed. Microsoft.AspNet.IISPlatformHandler and Microsoft.AspNet.Server.Kestrel have been added.

In the commands section the web command has been updated to use Kestrel.

Before:
"web": "Microsoft.AspNet.Hosting --config hosting.ini"

After:
"web": "Microsoft.AspNet.Server.Kestrel"

As a result of the move to Kestrel both hosting.ini and wwwroot\bin\AspNetLoader.dll can be deleted. In wwwroot the web.config file changed to the following.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <system.webServer>
    <handlers>
      <add name="httpPlatformHandler" 
           path="*" 
           verb="*" 
           modules="httpPlatformHandler" 
           resourceType="Unspecified"/>
    </handlers>
    <httpPlatform processPath="%DNX_PATH%" 
                  arguments="%DNX_ARGS%" 
                  stdoutLogEnabled="false" 
                  startupTimeLimit="3600"/>
  </system.webServer>
</configuration>

Startup.cs had a few changes. First in the constructor the application’s base path moved out of the constructor of ConfigurationBuilder to the SetBasePath function.

Before:
var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath);

After:
var builder = new ConfigurationBuilder()
                .SetBasePath(appEnv.ApplicationBasePath);

In ConfigureServices the setup for third-party authentication has been removed. For example the following has been removed.

services.Configure<FacebookAuthenticationOptions>(options =>
{
    options.AppId = Configuration["Authentication:Facebook:AppId"];
    options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
});

Third party authentication options are now set in the Configure function. Here is an example with Facebook.

app.UseFacebookAuthentication(options =>
{
    options.AppId = Configuration["Authentication:Facebook:AppId"];
    options.AppSecret = Configuration["Authentication:Facebook:AppSecret"];
});

Also in the Configure function app.UseErrorPage is now app.UseDeveloperExceptionPage and app.UserErrorHandler is now app.UseExceptionHandler.

Before:
app.UseErrorPage();
app.UseErrorHandler("/Home/Error");

After:
app.UseDeveloperExceptionPage();
app.UseExceptionHandler("/Home/Error");

Add the platform handler to the request pipeline before app.UseStaticFiles.

// Add the platform handler to the request pipeline.
app.UseIISPlatformHandler();

// Add static files to the request pipeline.
app.UseStaticFiles();

In AccountController.GetCurrentUserAsync and ManageController.GetCurrentUserAsync Context is now HttpContext.

Before:
return await _userManager.FindByIdAsync(Context.User.GetUserId());

After:
return await _userManager.FindByIdAsync(HttpContext.User.GetUserId());

Next up are the changes related to entity framework 7. EF7 had a lot of API changes with this release. I am covering the ones related to the app I am working with and others can be found by looking at the commits related to this issue.

The designer.cs that goes with migrations drop the override of Id in favor of a migration attribute instead. The new attribute can be found in Microsoft.Data.Entity.Migrations.

[DbContext(typeof(ApplicationDbContext))]
[Migration("00000000000000_CreateIdentitySchema")]
partial class CreateIdentitySchema
Migration related renames
Old New
Key HasKey
Reference HasOne
InverseCollection WithMany
ConcurrencyToken IsConcurrencyToken
isNullable nullable

After all the above changes my project built, but would error because entity framework was trying to run migrations that had already been applied. After some digging I found that the table used to check if a migration has been applied or not had been renamed from MigrationHistory to EFMigrationsHistory. The following SQL will move the migrations that have been applied from the old table to the new one.

INSERT INTO dbo.__EFMigrationsHistory (MigrationId, ProductVersion) 
SELECT MigrationId, ProductVersion FROM dbo.__MigrationHistory

After fixing the migration issue the app ran with no problems. Make sure and check out the release page and the breaking changes page for this release.

Also note that the ASP.NET 5 project templates for Visual Studio have been open sourced and can be found here. The templates are a great resource which I used to work through a couple of issues when doing the migration to beta 8.

Configuration in ASP.NET 5

ASP.NET 5 offer a lot of options for loading configuration data such as json files, ini files, XML files, in memory collections, command line arguments, user secrets and environment variables.

The following has at least one example of each type of configuration. Configurations are setup in the constructor of the Startup class.

public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
    // Setup configuration sources.
    var builder = new ConfigurationBuilder(appEnv.ApplicationBasePath)
        .AddJsonFile("config.json")
        .AddJsonFile($"config.{env.EnvironmentName}.json", optional: true)
        .AddIniFile("config.ini", optional: true)
        .AddInMemoryCollection(new Dictionary<string, string="">
        {
            {
            "AppSettings:TagLine",
            "InMemoryCollection"
            }
        })
        .AddXmlFile("config.xml", optional:true);

    if (env.IsDevelopment())
    {
        builder.AddUserSecrets();
    }
    builder.AddEnvironmentVariables();
    Configuration = builder.Build();
}

As you can see from the example all the different configuration sources can be used together without any issues. A critical thing to keep in mind is if a configuration option is set in multiple places the last configuration source’s value will be used. For example, using the code above, if the title of a site was sent in config.json and config.ini then the value from config.ini would be used.

An example I have seen the ASP.NET team use many times is to use user secrets for API key when in development and then store the keys in environment variables for production.

Here are the relevant lines from the dependencies section of the project.json file.

"Microsoft.Framework.Configuration.Abstractions": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Json": "1.0.0-beta7",
"Microsoft.Framework.Configuration.UserSecrets": "1.0.0-beta7",
"Microsoft.Framework.Configuration.Xml" : "1.0.0-beta7"

Another great feature is being able to load an object with the values from a configuration section. The following is a class created to hold the settings for an application.

public class AppSettings
{
    public string Title { get; set; }
    public string TagLine { get; set; }
}

Then in the ConfigureServices function this is all that is needed to load the class.

services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));

Now instead of directly accessing the configuration classes in the HomeController the AppSettings class can be used instead. Here is an example of using ASP.NET 5’s built-in dependency to automatically get a reference to AppSetting via constructor injection.

private readonly IOptions _appSettings;

public HomeController(IOptions appSettings)
{
    _appSettings = appSettings;
}

And then using the _appSettings in the index action to pass values to the view.

public IActionResult Index()
{
    ViewData["Title"] = $"{_appSettings.Options.Title} - " +
                        $"{_appSettings.Options.TagLine}";
    return View();
}

The above is using C# 6’s new interpolated string feature.  The dollar sign before the string is what triggers the feature and allow use variables when wrapped in curly braces.

Check out this github repo for the internals of configuration in ASP.NET 5 .

I also recommend checking out the new Introduction to ASP.NET 5 course on Microsoft Virtual Academy. It covers a lot of good information including live.asp.net which is a production site used to for the ASP.NET 5 community stand up.