ASP.NET 5

Angular 2 Quickstart with ASP.NET Core

Updated version of this post can be found here.

After working with Aurelia over last couple of months it seemed prudent to try out Angular 2. This post is going to cover the installation of Angular 2 and launching a basic Angular 2 application from an ASP.NET Core (the new name for ASP.NET 5) controller. Make sure to check out the official quickstart guide here.

Installation

Open the package.json file and add the following dependencies and devDependencies. This project is using gulp and is using the typescript based version of the quickstart guide which is why the gulp and typescript references are there.

  "dependencies": {
    "angular2":"2.0.0-beta.1",
    "systemjs": "0.19.16",
    "es6-promise": "^3.0.2",
    "es6-shim": "^0.33.3",
    "reflect-metadata": "0.1.2",
    "rxjs": "5.0.0-beta.0",
    "zone.js": "0.5.10"
  },
  "devDependencies": {
    "gulp": "3.9.0",
    "gulp-concat": "2.6.0",
    "gulp-cssmin": "0.1.7",
    "gulp-uglify": "1.5.1",
    "gulp-typescript": "2.10.0",
    "rimraf": "2.5.0",
    "typescript": "1.7.5"
  }

If inside Visual Studio 2015 the proper packages will be restored when package.js is saved, but outside of Visual Studio open a command prompt to the same directory as the package.js file and run npm install  which will download the required packages.

Typescript Configuration

Next add a tsconfig.json file to the project. This file marks the root of a typescript project and contains configuration setting for that project. Details on configuration options can be found here.

{
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "module": "system",
    "moduleResolution": "node",
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5"
  },
  "exclude": [
    "node_modules"
  ]
}

Angular 2 Bootstrap and Basic App

Create an Angular folder in the project’s root folder. Next add a app.component.ts file which is used to manage a view. This component is super simple and was pulled from the official quickstart guide.

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: '<h1>My First Angular 2 App</h1>'
})
export class AppComponent { }

Next add boot.ts which is used to bootstrap Angular 2.

import {bootstrap}    from 'angular2/platform/browser'
import {AppComponent} from './app.component'

bootstrap(AppComponent);

Gulp Tasks

This is the project that was the inspiration for the gulpjs introduction post. The first task is to move the Angular 2 dependencies from the node_modules folder to an Angular folder in wwwroot  so they will be available to be served.

gulp.task("angular2:moveLibs", function () {
    return gulp.src([
            "node_modules/angular2/bundles/angular2-polyfills.js",
            "node_modules/systemjs/dist/system.src.js",
            "node_modules/systemjs/dist/system-polyfills.js",
            "node_modules/rxjs/bundles/Rx.js",
            "node_modules/angular2/bundles/angular2.dev.js"
        ])
        .pipe(gulp.dest(paths.webroot + "Angular"));

});

The next task move the js files created by the typescript compiler when a ts file is saved from the Angular folder in the root of the project to wwwroot/Angular.

gulp.task("angular2:moveJs", function () {
    return gulp.src(["Angular/**/*.js"])
        .pipe(gulp.dest(paths.webroot + "Angular/app/"));

});

The last task just runs both of the previous tasks.

gulp.task("angular2", ["angular2:moveLibs", "angular2:moveJs"])

ASP.NET Controller

The Angular application is going to be run from the ASP.NET’s HomeController. Here is the new action that will load the yet to be created view.

public IActionResult Angular2()
{
    return View();
}

ASP.NET View

This is the view that when loaded kicks off the Angular 2 application. Add a new file called Angular2.cshtml in the Views/Home folder.  In the following first Angular related scripts are loaded. Then system.js is configured and the boot module is imported and the app is rendered inside of the my-app tag.

<html>
<head>
    <title>Angular 2 QuickStart</title>

    <script src="~/Angular/angular2-polyfills.js"></script>
    <script src="~/Angular/system.src.js"></script>
    <script src="~/Angular/Rx.js"></script>
    <script src="~/Angular/angular2.dev.js"></script>

    <script>
        System.config({
            packages: {
                '../Angular': {
                    format: 'register',
                    defaultExtension: 'js'
                }
            }
        });
        System.import('../Angular/app/boot')
              .then(null, console.error.bind(console));
    </script>

</head>

<body>
    <my-app>Loading...</my-app>
</body>

</html>

This is where the trouble started for me. It took a bit of searching, but the problem turned out to be with the system.js configuration. Since the view is in the HomeController it gets rendered out of as Home/Angular2.html and this project’s Angular files are up a directory so in order for system.js to find the Angular files the package configuration needed to be set to look up one folder.

This issue took longer to find than I would like to admit, but that is the danger is using libraries one is not familiar with. System.js was not my first thought since it was used in my Aurelia without issue. If you run into an issue check out the docs for system.js configuration.

Finally add the new view to main application’s nav bar. In Views/Shared/_Layout.cshtml add a link to Angular 2 on using the Home controller.

<div class="navbar-collapse collapse">
    <ul class="nav navbar-nav">
        <li><a asp-controller="Home" asp-action="Index">Home</a></li>
        <li><a asp-controller="Home" asp-action="Angular2">Angular 2</a></li>
        <li><a asp-controller="Home" asp-action="About">About</a></li>
        <li><a asp-controller="Home" asp-action="Contact">Contact</a></li>
    </ul>
    @await Html.PartialAsync("_LoginPartial")
</div>

Follow Up

This is a very basic Angular 2 application. Expect a follow up post in the new few weeks with this application build out more to utilize the same contacts web API as my Aurelia posts.

Update

If you are having issues upgrading beta 7 check out this post for a solution.

Angular 2 Quickstart with ASP.NET Core Read More »

Introduction to gulpjs

Working on a future blog post I hit some problems involving files that needed to be moved around as part of build process. This is one of the problems that gulp solves.

What is gulp?

Gulp is a task runner that utilizes node. The core idea behind task runners is automation. Have less that needs compiled into css, minified and output into the proper directory? That is a great use case for a task runner.

Gulp is not the only task runner out there. Grunt is another option and has actually been around longer. I am using gulp because it is the default in Visual Studio 2015. Google gulp vs grunt and decide which is right for you.

Installation

  1. Install node if needed from this site.
  2. From the console install gulp using npm install gulp -g

Project setup

Next add a gulpfile.js the root of the project where gulp is to be used. If using ASP.NET 5 this file will already exist and will include a few prebuilt tasks. If you are not using ASP.NET 5 the following is a mimimum gulpfile from the official getting started guide.

var gulp = require('gulp');

gulp.task('default', function() {
  // place code for your default task here
});

Also add gulp to the devDependencies section of the project’s package.json file. Since Visual Studio handles edits to package.json so nicely (intellisense and automatic package restore) I tend to edit the file manually instead of using npm.

 "devDependencies": {
    "gulp": "3.9.0"
  }

Plugins

The base gulp API only contains 4 functions (src, dest, task and watch) and doesn’t do a whole lot on its own. This is where plugins come in. Gulp has a ton of plugins that do all sorts of useful things. For example, the default gulpfile.js provided by Visual Studio has a min:js task that used gulp-concat and gulp-uglify to combine javascript files and then minify the result.

Example gulpfile for minification of javascript

The following is a full gulpfile based on the default file generated by Visual Studio stripped down to just the bits needed for the min:js task.

"use strict";

var gulp = require("gulp"),
    concat = require("gulp-concat"),
    uglify = require("gulp-uglify");

var paths = {
    webroot: "./wwwroot/"
};

paths.js = paths.webroot + "js/**/*.js";
paths.minJs = paths.webroot + "js/**/*.min.js";
paths.concatJsDest = paths.webroot + "js/site.min.js";

gulp.task("min:js", function () {
    return gulp.src([paths.js, "!" + paths.minJs], { base: "." })
        .pipe(concat(paths.concatJsDest))
        .pipe(uglify())
        .pipe(gulp.dest("."));
});

The above will pull all the javascript files from wwwroot/js and its subfolders and combine them and output the results to site.min.js in the wwwroot/js folder.

Introduction to gulpjs Read More »

Refactor Round 2

In last week’s post accessing a web API was refactored to a central service in an Aurelia application instead of being spread across the application. In this post we will push the refactor even further. The service will change from a pass through to the backing web API to be the data provider for the Aurelia application.

The first set of changes is to the service, which may be a bad name with the changes that are being made. GetAll will now keep a copy of the contact retrieved for the web API.

Before:
GetAll() {
    return this.http.fetch('contacts')
        .then(response => response.json())
        .catch(error => console.log(error));
}
After:
GetAll() {
    return this.http.fetch('contacts')
        .then(response => response.json())
        .then(contacts => this.contacts = contacts)
        .catch(error => console.log(error));
}

As an example of the implications of this change we will look at the Get function which require a contact ID. Instead of hitting the web API to pull the details of contact the information is pull from the service’s local copy that was cached in the GetAll function above.

Before:
Get(id) {
    return this.http.fetch(`contacts/${id}`)
        .then(response => response.json())
        .catch(error => console.log(error));
}
After:
Get(id) {
    return new Promise((resolve) => {
        resolve(this.contacts.filter(contact => contact.Id == id)[0])
    });
}

With the above changes the view model for the contact list contains very little code. With the binding of the contact list now bound to the service changes to contacts are automatically reflected in the contact list. This removed the need for the event aggregator. The full code for the list view model follows.

import {inject} from 'aurelia-framework';
import {ContactService} from 'Aurelia/contactService';

@inject(ContactService)
export class List {

    constructor(contactService) {
        this.contactService = contactService;
        this.contactService.GetAll()
             .then(() => this.contacts = this.contactManager.contacts);
    }
}

All the view models had similar reductions in the amount of code required. There are many more options on the best way to factor this code. A next step could be to keep the web API access separate from the a new business class used to manage and cache the contact data once it has been retrieved.

Refactor Round 2 Read More »

Refactor of ASP.NET 5 Web API Access from Aurelia

This post is going to cover refactoring of client side code based in Aurelia to centralize access to an ASP.NET 5 web API. This will remove the need for the fetch and configuration APIs in most classes which will be replaced by access via a contact service. This is of course based on the same contacts application I have been using in most of my previous posts. I am going to limit the examples to what is need to display a contact list, but the same concepts would apply to all aspects of contact interaction.

To begin I created a new ContactService.js file which will be used to handle all interactions with the ASP.NET 5 web API.

import {inject} from 'aurelia-framework';
import {HttpClient, json} from 'aurelia-fetch-client';
import 'fetch';
import {EventAggregator} from 'aurelia-event-aggregator';
import {Configure} from 'aurelia-configuration';
import {ContactUpdatedMessage} from 'Aurelia/ContactUpdatedMessage';

@inject(HttpClient, EventAggregator, Configure)
export class ContactService {

    constructor(http, eventAggregator, configAurelia) {
        http.configure(config => {
            config
                .useStandardConfiguration()
                .withBaseUrl(configAurelia.get('api.baseUrl'));
        });

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

    GetAll() {
        return new Promise((resolve) => {
            resolve(this.http.fetch('contacts')
                .then(response => response.json(),
                    err => console.log(err)));
        });
    }
}

The above class utilizes the configuration for the API base URL as explained in this post. The event aggregator is also included and would be used to notify of changes on a contacts. The event aggregator is not actually used in the shown code but example usage can be found here.

Note that the GetAll function returns a promise which is built off of the promise that the http fetch returns. Promises help with async operations are needed and are what enabled the then() function that makes reacting when an async operation is completed very simple. They are not the subject of this post but I wanted to make special note of them because they are new in the latest version of JavaScript.

Next are the changes to the list class which is the view model for the contact list. All the http related imports get removed and an import for the contactService is added. For classes don’t need notification of contact updates the EventAggregator and ContactUpdatedMessage could be removed as well.

Before:
import {inject} from 'aurelia-framework';
import {HttpClient} from 'aurelia-fetch-client';
import {EventAggregator} from 'aurelia-event-aggregator';
import 'fetch';
import {ContactUpdatedMessage} from 'Aurelia/ContactUpdatedMessage';
import {Configure} from 'aurelia-configuration';
After:
import {inject} from 'aurelia-framework';
import {EventAggregator} from 'aurelia-event-aggregator';
import {ContactUpdatedMessage} from 'Aurelia/ContactUpdatedMessage';
import {ContactService} from 'Aurelia/contactService';

In the inject decorator HttpClient and Configure are replaced with ContactService.

Before:
@inject(HttpClient, EventAggregator, Configure)
After:
@inject(EventAggregator, ContactService)

Next the constructor changed to remove http related items and to save a reference to the ContactService.

Before:
constructor(http, eventAggregator, configAurelia){
    http.configure(config => {
        config
          .useStandardConfiguration()
          .withBaseUrl(configAurelia.get('api.baseUrl'));
    });

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

Finally the direct call to the web API is replaced with a call to the ContactService.

Before:
created(){
    return this.http.fetch('contacts')
      .then(response => response.json())
      .then(contacts => this.contacts = contacts);
}
After:
created(){
    return this.contactService.GetAll()
      .then(contacts => this.contacts = contacts);
}

Following the above example, the remaining locations where the web API is accessed directly can be replaced with the ContactService.

Update

Something hit me when reading this post today. Aurelia’s fetch client returns a promise so there is no need to create a new promise in the ContactService. Here is the GetAll function from above updated to not declare a new promise.

Before:
GetAll() {
    return new Promise((resolve) => {
        resolve(this.http.fetch('contacts')
            .then(response => response.json(),
                err => console.log(err)));
    });
}
After:
GetAll() {
    return this.http.fetch('contacts')
        .then(response => response.json())
        .catch(error => console.log(error));
}

There maybe case where creating is a new promise is the correct thing to do, but in this case it was unnecessary.

Refactor of ASP.NET 5 Web API Access from Aurelia Read More »

Basic Configuration with Aurelia

If you have been following my Aurelia posts using an ASP.NET 5 web API then you will have noticed that I have been hardcoding the API url. In this post I am going to cover the basics of configuration in Aurelia which will allow the API url to be in a single location instead of spread all over the application.

Configuration will be done using the Aurelia-Configuration plugin. To install open a console window and navigate to the folder that contains the application’s package.json file and run the following command.

jspm install aurelia-configuration

If you are using Visual Studio to find your package.json make sure to click the show all files button in the solution explorer. With the release of RC1 package.json is hidden by default.

First code change is in the html file that kicks off Aurelia. The changed part is on the first line with aurelia-app which changed to aurelia-app=”main”.

<div aurelia-app="main">
    <script src="../jspm_packages/system.js"></script>
    <script src="../config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");
    </script>
</div>

Next add a main.js file in the wwwroot folder. This file will be called when Aurelia is bootstrapped and will control how Aurelia is bootstrapped. Everything in this file is the default Aurelia bootstrapping process other than “.plugin(‘aurelia-configuration’)” which is the part that needs to be added for configuration to work.

export function configure(aurelia) {
  aurelia.use
    .standardConfiguration()
    .developmentLogging()
    .plugin('aurelia-configuration');

  aurelia.start().then(a => a.setRoot());
}

By default the configuration plugin looks for an application.json inside of a config directory in the root directory. This tripped me up a bit as I was expecting this to be a config directory inside of wwwroot, but that is not exactly the case. Root in the case means root for the Aurelia application context. In my case my Aurelia app is launched from a HomeController which means the application.json file needed to be in wwwroot/Home/config. Here is my application.json file with the base url for my test API.

{
	"api": {
		"baseUrl": "http://localhost:18907/api/"
	}
}

Now to get access to the configuration information. First add an import for configuration.

import {Configure} from 'aurelia-configuration';

Add Configure to the inject decorator.

@inject(HttpClient, Router, EventAggregator, Configure)

And to the constructor.

constructor(http, router, eventAggregator, configAurelia)

Now the actual usage of a config value with a before and after for comparison.

Before:
.withBaseUrl('https://localhost:18907/api/');

After:
.withBaseUrl(config.get('api.baseUrl'));

Here is all of the above together for reference.

import {Configure} from 'aurelia-configuration';

@inject(HttpClient, Router, EventAggregator, Configure)
export class Detail{

    constructor(http, router, eventAggregator, configAurelia){
        http.configure(config => {
            config
              .useStandardConfiguration()
              .withBaseUrl(configAurelia.get('api.baseUrl'));
        });

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

That is all there is for basic configuration with Aurelia. Check out the plugin’s site for examples of how set up configurations for different environments, setting the config directory as well as filename.

Basic Configuration with Aurelia Read More »

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.

ASP.NET 5 Web API Put Read More »

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.

Migration from ASP.NET 5 Beta 8 to RC1 Read More »

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

Adding Authorize to a Web API Read More »

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

Aurelia Routing with a Parameter Read More »

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.

Migration from ASP.NET 5 Beta 7 to Beta 8 Read More »