Web API

ASP.NET Core Project with Angular 2, Aurelia and an API

I have been exploring Aurelia and more recently Angular 2 and while doing so I thought it might be nice to run both frameworks from the same project.  My first crack at this can be found in this repo on Github.

Content

  • Contact model, a simplified version of the one used in previous blogs
  • ContactsController and related razor views created using Visual Studio’s scaffolding tools based on the contact mode
  • ContactsApiController is the end point for the Angular 2 and Aurelia applications
  • Angular 2 application that closely match the one from last week’s post
  • Aurelia application is currently just a proof that Angular 2 and Aurelia could run in the same project. This application will be updated to connect to the project’s web API.

Getting Started

Ensure that node and jspm are install.

After acquiring the code open the solution. If using Visual Studio the npm based packages will be restored automatically. If not using Visual Studio then run  npm install from the console. This will handle all the files needed by Angular 2.

Next run the jspm install -y  command to install the Aurelia related packages.

Make sure the database is created and up to date with the following two commands.

dnx ef database update -c ApplicationDbContext
dnx ef database update -c ContactsDbContext

In wwwroot open the config.js file and verify the paths section looking like the following. Jspm install seems to rewrite the github and npm portions of the paths section which removed the “../”. This is more than likely a configuration issue that I hope to fix in the future.

paths: {
  "*": "../Aurelia/*",
  "github:*": "../jspm_packages/github/*",
  "npm:*": "../jspm_packages/npm/*"
}

Finally run the angular2 gulp task from the task runner. The application should now run with no issues.

First Run

Make sure to register a new user as both the contacts controllers require an authorized user and filter down the contacts to display based on the logged in user.

The menu bar will contain links for Angular 2, Aurelia and Razor. Use the razor link to create some data. This is the generated razor views mentioned above. It is also the only way to add data through the application currently.

The Angular 2 link will of course launch the Angular 2 application that will display a list of contacts for the current user.

The  Aurelia like will launch the Aurelia application which just contains the very basic application from the getting started guide.

Going Forward

The plan is to develop the Angular 2 and Aurelia applications together. The Aurelia application will be the first to get some time to get up to the same level as the Angular 2 application.

It is also my hope that having this project will be a good reference for you when reading the examples in future blog posts.

Angular 2 with ASP.NET Core Web API

Updated version of this post can be found here.

This post will be expanding on the basic Angular 2 application from last week’s post to download data from an ASP.NET Core web API. This is the same contacts API used in all of my Aurelia and Web API posts.

Contact Interface

First add a contacts.ts typescript file in the Angular2 folder to hold an interface that defines a contact. This will be used as a definition of what the application expects a contact to look like. A class could be used instead of an interface if some sort of functionality was need on a contact.

export interface Contact {
    Id: number;
    Name: string;
}

Contact Service

This is the service that will be used to connect to the web API and retrieve a list of contacts.

import {Injectable} from 'angular2/core';
import {Http} from 'angular2/http';
import {Contact} from './contact';
import {Observable} from 'rxjs/Observable';

@Injectable()
export class ContactService {
    private _url = 'http://localhost:38218/api/contacts/';

    constructor(private http: Http) { }
    
    getContacts() {
        return this.http.get(this._url)
            .map(responce => <Contact[]>responce.json())
            .catch(error => {
                console.log(error);
                return Observable.throw(error);
            });
    }
}

The @Injectable() is required for typescript to output the proper metadata for Angular to know what need to be injected into the service. For more information on Angular’s dependency injection look here.

Http from angular2/http is a library used for http interactions. Http interaction is not included in the core of Angular and will require a dependency on a new file.

Contact is just a reference to the contact interface from above.

Observable is a reference to a rxjs type. Rxjs is a set of libraries that help with async programming and is used heavily by Angular 2.

The service’s  constructor get a reference to the http library and saves it to a http variable.

Here is just the getContacts() from above.

getContacts() {
    return this.http.get(this._url)
        .map(responce => <Contact[]>responce.json())
        .catch(error => {
            console.log(error);
            return Observable.throw(error);
        });
}

http.get returns an rxjs observable which is then processed with the rxjs map function. Map takes the json data from the http response and maps it to a contact array.

The url used here will need to be moved to configuration at some point.

App.component Changes

Imports

import {Component, OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {Contact} from './contact';
import {ContactService} from './contact.service';
import 'rxjs/Rx';

A couple of notes on the imports. OnInit is an Angular lifecycle hook that will be used to get a list of contacts. rxjs/Rx import the full set of rxjs libraries and is added here so they will be available to the full application level. rxjs is a fairly sizable and this should be replace with only the parts needed, but for this example the full set of libraries is easier.

AppComponent

The AppComponent class has been expanded and will server as the view model for the contact list. New properties were added for a title and an array of contacts.

A constructor was added to allow the injection of the ContactService.

Notice the class now implements OnInit and a ngOnInit function has been added. This is taking advantage of Angular’s lifecycle hooks. On initialization the class will call getContacts on the ContactService and subscribe to the returned observable and assign the values to the local contacts array.

export class AppComponent implements OnInit {
    public title = 'Contact List';
    public contacts: Contact[];

    constructor(private _contactService: ContactService) { }

    ngOnInit() {
        this._contactService.getContacts()
            .subscribe(
            contacts => {
                console.log(contacts);
                this.contacts = contacts;
            },
            error => alert(error));
    }
}

@Component

The template has expanded to display the title and contact data.

{{title}} binds the title property of the AppComponent class.

The array of contacts is shown in an unordered list. The list items are created used *ngFor which loops each item in the contacts array. When inside the li element items can be bound using {{contact.PropertyName}} as one would expect.

@Component({
    selector: 'my-app',
    template: `
              <h1>{{title}}</h1>
              <ul class="list-unstyled">
                <li *ngFor="#contact of contacts">
                  <span class="badge">{{contact.Id}}</span> {{contact.Name}}
                </li>
              </ul>
              `,
    providers: [
        HTTP_PROVIDERS,
        ContactService
    ]
})

The providers section is new and is a list of items that will be available for injection to this component and any of its child components.

app.component.ts

Here is the full app.companent.ts all together for reference.

import {Component, OnInit} from 'angular2/core';
import {HTTP_PROVIDERS} from 'angular2/http';
import {Contact} from './contact';
import {ContactService} from './contact.service';
import 'rxjs/Rx';

@Component({
    selector: 'my-app',
    template: `
              <h1>{{title}}</h1>
              <ul class="list-unstyled">
                <li *ngFor="#contact of contacts">
                  <span class="badge">{{contact.Id}}</span> {{contact.Name}}
                </li>
              </ul>
              `,
    providers: [
        HTTP_PROVIDERS,
        ContactService
    ]
})
export class AppComponent implements OnInit {
    public title = 'Contact List';
    public contacts: Contact[];

    constructor(private _contactService: ContactService) { }

    ngOnInit() {
        this._contactService.getContacts()
            .subscribe(
            contacts => {
                console.log(contacts);
                this.contacts = contacts;
            },
            error => alert(error));

    }
}

ASP.NET View

The Angualr2.cshtml view that contains the angular application needs the following new script tag for the new http library.

<script src="~/Angular/http.dev.js"></script>

Gulp

The gulpfile.js needs also needs to change to move the new http.dev.js file to wwwroot as part of the angualr2:moveLibs task.

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",
            "node_modules/angular2/bundles/http.dev.js"
        ])
        .pipe(gulp.dest(paths.webroot + "Angular"));

});

Running the application should now display the list of contact returned by the web API.

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.

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.

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

Add and Delete from an API

A few weeks ago I covered creating a basic API to retrieve contacts. In this post I am going to expand on that example by adding the ability to create and delete contacts. Before starting it would be a good idea to review my post on API basics as well as make sure you have a tool such as Postman to exercise your API.

First is the function for the creation of a new contact which will be an http post that accepts a contact, does some validation and inserts the contact to the database.

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

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

    _dbContext.Add(contact);
    await _dbContext.SaveChangesAsync();

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

First thing to notice is the HttpPost attribute that says this function only handles HTTP posts. Next notice the FromBody attribute on the contact parameter of the function call. This tells ASP to bind the contact object to the data provided by the request body so that the function has a hydrated contact object to work with.

Both if statements are doing validation. The first is making sure that contact has a value. The second if is a bit of magic provided by ASP. ModelState contains information about the state of the model, a contact in this case, after it is bound to the values from the HTTP request. The contact model has data annotations which will cause ModelState.IsValid to return false if the model fails to validate against any of the data annotations. Both set of variations return a HttpBadRequest, but the ModelState version passes back the ModelState to the client since it contains details of all failed validation.

If all validation passed then the new contact is added to the controller’s dbContext and the dbContext saves changes inserts the new contact into the database.

Finally a route to the newly inserted contact is returned to the client. CreatedAtRoute takes a route name, route values and a value. In this case it is saying run the “GetById” route for the contacts controller with the ID of the new contact.

In order to get CreatedAtRoute to work the Get overload that takes an ID needed a name which is provided as part of the HttpGet attribute.

[HttpGet("{id}", Name = "GetById")]
public async Task Get(int id)

Now to add a contact with the API using Postman. First click Get which will drop down a list of HTTP verb to choose from. For adding a new contact we need to use Post.

postmanHttpVerb

After selecting post the body tab will be enabled. On the body tab select raw from the radio buttons. Next click the drop down that says text and select JSON (application/json) since the data for the contact will be sent to the API as JSON.

postmanBodyTypeFinally enter the appropriate JSON and click send. All that is required to create a new contact with my API is a name so the follow JSON is what I used to test.

{"Name" : "John McTest"}

At this point if all went well you will find John McTest in database. If all went well Postman will give the option to view the response which would include the Id which was set when dbContext.SaveChangesAsync was called.

The delete function is much simpler. It just needs the HttpDelete attribute and takes the ID of the contact to be deleted.

[HttpDelete("{id}")]
public async Task Delete(int id)
{
    var contact = await GetContacts()
                          .Where(c => c.Id == id).FirstOrDefaultAsync();

    if (contact == null) return;

    _dbContext.Remove(contact);
    await _dbContext.SaveChangesAsync();
}

Using the dbContext the contact is retrieved for the ID passed in. If the contact is not found the function just returns since the contact has already been removed from the database. If the contact is found then the remove function of the dbContext is used to mark the contact for delete and then save changes of dbContext is used to send the delete command to the database.

To test with Postman select delete from the list of HTTP verbs, this is the same drop down that was used to select post above. Next enter the ID to be deleted in the URL box and click send. In the screenshot below the API will be told to delete the contact with the ID of 108.

postmanDelete

Check out the ASP.NET 5 docs for a great API example that uses Fiddler instead of Postman.

Aurelia with ASP.NET 5 and Web API

Update: A series of posts has been made covering this same topic with the RTM versions of both ASP.NET Core and Aurelia. The first post in the series can be found here.

Now that I have a web API for my contacts I wanted to go back and add a front end to view them. I decided this would also be a good time to try out one of the single-page application frameworks instead of using razor. The number of choices for a spa framework is almost over whelming. Angular, Ember, Meteor, etc. In the end I decided to try out Aurelia mostly based on the fact that Rob Eisenberg is behind it.

To get going I highly recommend going through Aurelia’s get started guide. In addition to being a great introduction to Aurelia I also had to pull at least one file out of the sample project to get up and running in my ASP.NET project.

A couple more resources I recommend reading before getting started are a couple of blog post by Scott Allen. The first covers getting jspm going in ASP.NET 5 and the second is a guide to get started with Aurelia in ASP.NET 5.

Now to get started. The first step is to install jspm which is yet another package manager. It can be installed using with the following npm command.

npm install -g [email protected]

jspm utilizes GitHub in some cases to install packages so it is recommended that jspm be configured with a login or api token for GitHub to avoid any anonymous API request limits.

jspm registry config github

The remaining commands should be run from the project directory that contains the project.json file.

Next run jspm’s init command. This command will ask a series of questions. The default is fine for most of them. The exceptions being the server baseURL should be ./wwwroot and I chose to use Babel as my transpiler.

jspm init

Now to install all the Aurelia bits that will be need to get an application up and hit a web API.

jspm install aurelia-framework
jspm install aurelia-bootstrapper
jspm install aurelia-fetch-client

Next add an html file (any name is fine) to the wwwroot folder. This html file will be how the Aurelia application is accessed and the file does not have a lot in it. If you read either Aurelia’s getting started or Scott’s blog the following contents will look very similar.

<!doctype html>
<html>
<head>
    <title>Hello from Aurelia</title>
</head>
<body aurelia-app>
    <script src="jspm_packages/system.js"></script>
    <script src="config.js"></script>
    <script>
        System.import("aurelia-bootstrapper");
    </script>
</body>
</html>

When the above page loads Aurelia kicks in and looks for app.js and app.html. My app.js is based on the users.js from the getting started guide.

import {inject} from 'aurelia-framework';
import {HttpClient} from 'jspm_packages/github/aurelia/[email protected]/aurelia-fetch-client.js';
import 'fetch';

@inject(HttpClient)
export class App{
    heading = 'Contacts';
    contacts = [];

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

        this.http = http;
    }

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

This class acts as the view model for my contact list. In the constructor function an http client is set up with a base url that matches the base url for the project’s web API which is http://localhost:14830/api/ in this case. The activate function is called by Aurelia and is where the contacts API is called using http.fetch. The import to fetch is the file I had to copy out of the Aurelia get started application into the wwwroot folder. You may also notice that the other imports are referencing specific folders with specific versions. This is not something that should be done for anything other than a short demo. I need to do some learning on gulp and what exactly Aurelia requires to get that fixed.

The following is the app.html.

<template>
    <section>
        <h2>${heading}</h2>
        <div repeat.for="contact of contacts">
            <p>${contact.Name}</p>
            <div repeat.for="emailaddress of contact.EmailAddressModels">
                <p>${emailaddress.Address}</p>
            </div>
        </div>
    </section>
</template>

The ${heading} is binding the value that will be displayed to the heading property defined in the app class. Next notice the repeat.for which will repeat the element it is defined on and its children foreach in the container to the right of the of statement. For example the above is going to print the name of each contact and all that contact’s email address contained in the contacts property of the app class. The resulting page is ugly, but the point is to prove Aurelia running and displaying the proper data.

At this point to remove some complexity I removed the authorize attribute off of the contacts controller and ran a test. As you may have guessed the test failed.

The failure was caused by the API returning a single object that then contain all the contacts instead of an array of contacts. The cause of this issue is the changes I made to work around serialization issue I was having with circular references  from my entity framework navigation properties.

The fix was to remove the following from the ConfigureServices function of the Startup class.

services.ConfigureMvcJson(options =>
{
    options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
});

Then in all the contact related classes I added the JsonIgnore attribute to the property that pointed back to the contact model.

public class ContactEmailModel
{
    public int ContactId { get; set; }
    public int Id { get; set; }
    [EmailAddress]
    public string Address { get; set; }

    [JsonIgnore]
    public ContactModel Contact {get; set;}
}

With those two changes everything started working. At this point I am not sure if that is the proper way to handle my issue or not. I have a feeling it will be something I will end up revisiting as I continue to learn more.

Web API with Get Filter and Security

This is a slight extension on the web API contacts controller from last week.

The first change is to the get that returns all contacts. Getting all contacts is great, but it would be helpful to be able to filter the data down. The following code is all the changes to the get function.

// GET: api/values
[HttpGet]
public async Task Get(string filter = null)
{
  var contacts = GetContacts();

  if (!string.IsNullOrWhiteSpace(filter))
  {
    contacts = contacts
         .Where(c => c.Name.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1 ||
                     c.AddressModels.Exists(a => a.Address.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1 ||
                                                 a.City.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1 ||
                                                 a.Country.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1 ||
                                                 a.PostalCode.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1 ||
                                                 a.State.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1) ||
                     c.EmailAddressModels.Exists(e => e.Address.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1) ||
                     c.PhoneModels.Exists(p => p.Number.IndexOf(filter, 0, StringComparison.CurrentCultureIgnoreCase) > -1));
  }

  return await contacts.ToListAsync();
}

The get function call now has an optional string for filter. If the filter has a value then a linq statement checks to see if any contact fields matches the filter. In the past I had used the contains function, but during tested I noticed that contains function was dong a case-sensitive matching and I wanted case-insensitive so I switch to the IndexOf function of the string class.

The filter is passed via a query string which seem to the be more restful way of doing filtering type stuff instead of creating a different get function. Keep in mind I am new to web API and rest so if I have any of this wrong please let me know.

The second thing I changed this round was to require authorization to use the API.

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

As you can see the only thing I did was add the authorize attribute to the controller class. That is all that is required and now the API will require the user be logged in. This is using ASP’s authorization and means that the user must be logged in via the web site and then use that same session to hit the API.

Requiring the user to already be logged may or may not be what you are looking for with your API. If you are using the API for run a SPA that could be fine, but if your API is being used to back another scenario than authorization will need to be fleshed out more.

I hope to address both the SPA and other authorization type in a future blog post so stay tuned.

Basic Web API with ASP.NET 5

I am going to create basic web API access to the contacts data I have been using in previous posts. To start with I added an API folder to my project to hold my API controller. Next I added a contacts controller to the API folder by right clicking on the folder and selecting add new item.

AddNewItem

From the add new item under DNX selected Web API Controller Class, entered a name and clicked add.

AddNewItemDialog

From the resulting code I removed all the actions except for two get functions.

[Route("api/[controller]")]
public class ContactsController : Controller
{
    private readonly ContactsDbContext _dbContext;

    public ContactsController(ContactsDbContext dbContext)
    {
        _dbContext = dbContext;
    }

    // GET: api/values
    [HttpGet]
    public async Task<IEnumerable<ContactModel>> Get()
    {
        return await GetContacts().ToListAsync();
    }

    // GET api/values/5
    [HttpGet("{id}")]
    public async Task<ContactModel> Get(int id)
    {
        return await GetContacts()
                     .Where(c => c.Id == id).FirstOrDefaultAsync();
    }

    private IQueryable GetContacts()
    {
        var contacts = from c in _dbContext.ContactModels
                                 .Include(c => c.AddressModels)
                                 .Include(c => c.EmailAddressModels)
                                 .Include(c => c.PhoneModels)
                       select c;
        return contacts;
    }
}

The above code contains a lot of new concepts I am going to break it down more.

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

The first thing to notice is the route attribute on the class declaration. The route attribute is how the routing engine determines where to send requests. Using [controller] tells the routing engine to use the class name minus the word controller. For example the above route handles api/contacts.

private readonly ContactsDbContext _dbContext;

public ContactsController(ContactsDbContext dbContext)
{
    _dbContext = dbContext;
}

The constructor takes the DbContext needed to access contacts. Note that the context is being automatically injected via the constructor thanks to the fact that ASP.NET 5 now comes with dependency injection out of the box.

// GET: api/values
[HttpGet]
public async Task<IEnumerable<ContactModel>> Get()
{
    return await GetContacts().ToListAsync();
}

// GET api/values/5
[HttpGet("{id}")]
public async Task<ContactModel> Get(int id)
{
    return await GetContacts()
                 .Where(c => c.Id == id).FirstOrDefaultAsync();
}

First get function returns all contacts and the second returns a specific contact based on the contact’s ID.

private IQueryable<ContactModel> GetContacts()
{
    var contacts = from c in _dbContext.ContactModels
                             .Include(c => c.AddressModels)
                             .Include(c => c.EmailAddressModels)
                             .Include(c => c.PhoneModels)
                   select c;
    return contacts;
}

Note that the query contains three includes and each of the included classes contain a navigation property back to the main contact. For example here is the email address model.

public class ContactEmailModel
{
    public int ContactId { get; set; }
    public int Id { get; set; }
    [EmailAddress]
    public string Address { get; set; }

    public ContactModel Contact {get; set;}
}

All of the above compiles and seems to run fine, but will not provide a response. The navigation property for contact creates a circular reference that the response serializer throws an exception trying to serialize.

Thankfully the framework has a configuration option to work around this problem. In the ConfigureServices function of the Startup class add the following.

services.ConfigureMvcJson(options =>
{
    options.SerializerSettings.PreserveReferencesHandling = PreserveReferencesHandling.All;
});

The above options marks the Contact property as a reference and does not try to circularly serialize it.

Now by running the project and going to http://localhost:port/api/contacts/1 in the browser I get all the contact data related to the contact with an ID of 1. I recommend using something like Postman to make the result more readable if you don’t have a front end to display the data.