In last week’s post I covered creating a new ASP.NET Core project and then adding in Aurelia. The Aurelia application did nothing except output hello world. This week I am going to take an existing contacts API and the Aurelia project from last week use them together to make the Aurelia application display the name of the contacts from the API.
Part 1 – Add Aurelia to an ASP.NET Core Project
Part 2 – Aurelia with an ASP.NET Core API (This Post)
Part 3 – Aurelia with an ASP.NET Core API: Modeling and Displaying Data in Aurelia
Part 4 – Aurelia with ASP.NET Core: Host Aurelia from a Controller
Github repo with the code for all of the parts with a release to go with each post
Starting point overview
When you download a copy of the repo you will find an ASP.NET Core solution that contains two projects. The Aurelia project, obviously, contains the Aurelia application.
The Contacts project has a bit more going on. It has a set of razor views and a controllers to go with them that support standard CRUD operations, which at the moment is the best way to get contact information in the database. It also contains the ContactsApiController which will be the controller used to feed contacts to the Aurelia application.
Multiple startup projects in Visual Studio
In order to test this application both the Contacts and Aurelia projects to startup when the solution is run. Visual Studio provides an easy way to accomplish this. In the Solution Explorer window right click on the Solution and click Set StartUp Projects.
This will launch the Solution Property Pages dialog. Looks for the Startup Project page under Common Properties.
Match the screenshot above by selecting the radio button for Multiple startup projects. Then using the arrows on the right to make sure that Contacts project will start first. Also set the Action on Contacts to be start without debugging since that project will just be feeding data and won’t need to be debugged at the moment.
Then on the Aurelia project set the Action to Start. Click OK and now both projects will start up when solution is run from Visual Studio.
Accessing Data from the API
In order to get data from the API we will need away to talk HTTP from Aurelia. Aurelia provides two libraries that provide this functionality which you can read about here. For this post I will be using Aurelia’s fetch client which based on the experimental Fetch API. The Fetch API isn’t supported by all browsers at point so if you need it there a polyfill can be found here.
Installing the Aurelia Fetch Client
If you started with the project from GitHub repo linked about then the fetch client will already be included in the projects dependencies, but if not I wanted to cover getting it installed. Using a command prompt run the following npm command in the project’s directory.
npm install aurelia-fetch-client -save
Alternately add the following line to the dependencies section of the project’s package.json file and when the file is saved Visual Studio will automatically restore the new package.
"aurelia-fetch-client": "^1.0.0"
The last step to making sure the fetch client available in the client application is to make sure it is included in the vendor-bundle.js that is created by the Aurelia CLI’s build process. To do this open the aurelia.json file found in the aurelia_project folder. In the bundles section look for the bundle named vendor-bundle.js and in its dependencies section add “aurelia-fetch-client”. The following an abbreviated example from my file to to make it clear where the new line should go.
"name": "vendor-bundle.js", "prepend": [ "node_modules/bluebird/js/browser/bluebird.core.js", "wwwroot\\scripts/require.js" ], "dependencies": [ "aurelia-binding", "aurelia-bootstrapper", "aurelia-dependency-injection", "aurelia-event-aggregator", "aurelia-fetch-client",
Create a client side service
It is important to not spread HTTP across the whole application and in order to achieve this goal it is a good idea to create a service that encapsulates the HTTP actions. For this example a contact service will be created that will handle all interactions with the ASP.NET Core API and the rest of the Aurelia application will just interact with the contact service.
To start create a services folder inside the src folder which contains the Aurelia client side application and added a new file to contain the new service called contactService.js.
The contact service will use the Aurelia fetch client to get all the contacts from the ASP.NET Core API. To do so it needs a constructor to allow injection and configuration of a HTTP client as well as a single function to get all the contacts. The following is the complete service.
import { HttpClient } from 'aurelia-fetch-client'; export class ContactService { static inject() { return [HttpClient] }; constructor(http) { this.http = http; this.http.configure(config => { config .useStandardConfiguration() .withBaseUrl('https://localhost:13322/api/contactsApi/'); }); } GetAll() { return this.http.fetch('') .then(response => response.json()) .catch(error => console.log(error)); } }
A future post will come back to this code and make it more robust, but this post is just about getting data for the Aurelia application so the service is being kept as simple as possible.
Using the Contact Service
Again to keep the code as simple as possible the contact servers will be utilized directly in existing the existing app.js file. The following is the class before any changes.
export class App { constructor() { this.message = 'Hello World!'; } }
The following is the class after the changes to import and inject the contact service via the constructor as well as using the contact service to download and show the name of each contact.
import { ContactService } from './services/contactService'; export class App { static inject() { return [ContactService] }; constructor(contactService) { this.message = 'Hello World!'; contactService.GetAll() .then(result => { this.message = `Contact Results: ${result.map((contact) => contact.name)}`; }); } }
Does it work?
At this point I used Visual Studio to launch both projects. In the Aurelia MVC application I navigated to http://localhost:37472/index.html which is the page that contains the Aurelia client application. Instead of being greeted by a list of contact names the application output “Hello World!”. That means that the Aurelia client application was running, but the contact service had failed for some reason. The console in the Chrome developer tools show the following error.
Fetch API cannot load http://localhost:13322/api/contactsApi/. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:37472’ is therefore not allowed access. If an opaque response serves your needs, set the request’s mode to ‘no-cors’ to fetch the resource with CORS disabled.
The work around
Turns out that having two projects caused an issue I hadn’t considered. I now have to worry about cross-origin resource sharing. Not a topic that will be covered in this post. In order to work around this issues the Contacts project can be changed to added the following to the Configure function of the Startup class.
app.UseCors(builder => { builder.AllowAnyHeader(); builder.AllowAnyMethod(); builder.AllowAnyOrigin(); } );
I am in no way saying that the above is the proper way to fix this issue. CORS is a subject I haven’t dug in to yet. The above is only meant to get this sample working. Please make sure to locate other resources on CORS for anything that is more than a demo.
Final thoughts
Running at this point will return the names of contacts as expected. Future posts will expand this application more. I want to get Angular 2 up as a new project in this same solution. When this solution has projects that contains the basics for MVC/razor, Aurelia and Angular 2 it will be in a good replacement the ASP.NET SPAs comparison reference application. Having each type of front end in a different project should make it easier to follow how each is set up. The code for today’s post can be found here.