JavaScriptServices

Pass ASP.NET Core Appsettings Values to Angular via an API Call

There have been a few issues opened on the repo I have showing usage of Angular, Identity Server 4, and ASP.NET Core together that related to incompatibilities with the newer versions of Angular. In an effort to fix this issue the plan was to recreate the client application using the new Angular template from Microsoft which from what I read should address the issue.

The code before any changes can be found here, but in this case, the whole client application has been recreated so the starting point may not be super helpful.

The Problem

For the most part, this worked well, but the problem can when I needed to use some configuration values from ASP.NET Core in my new Angular application. The previous versions of the template used server-side rendering which I utilized to pass the configuration values. The new template doesn’t use server-side rendering by default and I wanted to find a way to solve the issue without requiring server-side rendering.

The other issue is that I want to be able to run this application in Azure and set the configuration values as environment variables. While Angular seems to have support for environment files finding a solution that used a systems environment variables turned out too not be simple.

Configuration API Endpoint

Since the configuration values I need to get to the client application are secret I decided to go the route of pulling them via an API call back to the same ASP.NET Core application that is hosting the Angular Application, which is the Client App project in the sample solution.

I added a ConfigurationController.cs class to the Controller directory with the following contents.

[Produces("application/json")]
[Route("api/Configuration")]
public class ConfigurationController : Controller
{
    private readonly IConfiguration _configuration;

    public ConfigurationController(IConfiguration configuration)
    {
        _configuration = configuration;
    }

    [HttpGet("[action]")]
    public IActionResult ConfigurationData()
    {
        return Ok(new Dictionary<string, string>
        {
            { "IdentityServerAddress", _configuration["IdentityServerAddress"] },
            { "ApiAddress", _configuration["ApiAddress"] }
        });
    }
}

This controller gets constructed with a reference to the application’s configuration which is then used to populate a dictionary with the values my Angular application needs. For completeness, the following is the contents of the application’s appsettings.json file.

{
  "Logging": {
    "LogLevel": {
      "Default": "Warning"
    }
  },
  "IdentityServerAddress": "http://localhost:5000",
  "ApiAddress": "http://localhost:5001/api/"
}

Angular Changes

This is the part that I really struggled to get right. I needed the configuration values from the API above to be available as soon as possible. Thankfully I came across this blog post by Juri Strumpflohner which covers using Angular’s APP_INITIALIZER.

The first thing I need was to create a class in Angular to get the configuration values from the API and serve to them the rest of the Angular application. To do this I added a configuration.service.ts into a new ClientApp/src/app/configuration directory. The full class follows.

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class ConfigurationService {

  private configuration: IServerConfiguration;

  constructor(private http: HttpClient) { }

  loadConfig() {
    return this.http.get<IServerConfiguration>('/api/Configuration/ConfigurationData')
      .toPromise()
      .then(result => {
        this.configuration = <IServerConfiguration>(result);
      }, error => console.error(error));
  }

  get apiAddress() {
    return this.configuration.ApiAddress;
  }

  get identityServerAddress() {
    return this.configuration.IdentityServerAddress;
  }

}

export interface IServerConfiguration {
  ApiAddress: string;
  IdentityServerAddress: string;
}

This class hits the API to get the configuration values in the loadConfig function and maps it to a class level field. It also provides properties to get the individual configuration values.

As I mentioned above, getting the application to get these configuration values in a timely matter was something I really struggled to do. The first step to using Angular’s APP_INITIALIZER to solve this issue is to change the import from @angular/core to include APP_INITIALIZER and to import the ConfigurationService.  All these changes are being made in the app.module.ts file.

import { NgModule, APP_INITIALIZER } from '@angular/core';
import { ConfigurationService } from "./configuration/configuration.service";

Next, we need to define a function that will call the ConfigurationService.loadConfig function.

const appInitializerFn = (appConfig: ConfigurationService) => {
  return () => {
    return appConfig.loadConfig();
  };
};

Finally, in the providers array add an element for the APP_INITIALIZER and the ConfigurationService.

providers: [
  ConfigurationService,
  {
    provide: APP_INITIALIZER,
    useFactory: appInitializerFn,
    multi: true,
    deps: [ConfigurationService]
  }]

 Wrapping Up

This is one of those things that turned out to be way more complicated than I expected. Thankfully with the above changes, I was able to get it working. I hope this saves you all some time. The code with all the changes can be found here.

Pass ASP.NET Core Appsettings Values to Angular via an API Call Read More »

Trying the New ASP.NET Core Angular Template with CLI Support

I got hit by the flu that has been going around and now that the fever has passed I thought it would be a good time to try out the new version of the Angular template for ASP.NET Core that works well with the Angular CLI.

Template Installation

Note that at the time of this writing the templates are in the release candidate stage and a new version could be available by the time you are reading this so make sure and check this page for potential updates.

Running the following command from a command prompt will install the RC version of the templates.

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.0.0-rc1-final

Project Creation

Create a directory for the project and navigate to it in a command prompt. Run the following command to create the new Angular project.

dotnet new angular

Next, if you have a solution you want to add the new project to that can be done with the following command adjusting for the naming of your project and solution.

dotnet sln "ASP.NET Core Basics.sln" add src\AngularWithCli\AngularWithCli.csproj

Installation of Angular CLI

From the command prompt run the following command to install the Angular CLI globally.

npm install -g @angular/cli

After the above, I got the following error trying to run any Angular CLI commands.

You seem to not be depending on “@angular/core”. This is an error.

The problem ended up being that I had not installed all the packages for the project. The issue was cleared up by the following command.

npm install

Angular CLI Usage

Navigate to the ClientApp directory and you can then use all the Angular CLI commands as you would in a stand along Angular application. Some of which can be found here. If you are looking for a quick command to verify all is work the following command works well by running a linter on your project.

ng lint

Wrapping Up

Having templates that are compatible with the Angular and React CLI is a big step forward. The CLIs provide a lot of functionality and by having a setup that doesn’t restrict their usages is a great move. Make note that server-side rendering is no longer enabled by default, but can still be enabled for Angular projects, but not React based projects.

I recommend you check out the official documentation which can be found here.

I hope we see these functionality moves to the other templates that are outside of the templates in this package in order to support Aurelia and Vue.

Trying the New ASP.NET Core Angular Template with CLI Support Read More »

Vue: Contact Detail

Last week’s post covered adding a Vue project to the ASP.NET Core Basics example solution. This post is going to cover adding a read-only view of a contact’s detail to being the Vue sample a step closer to being in line with the Angular, Aurelia and React samples. The code before any changes can be found here.

Contact Class

The Contact interface in the contactlist.ts file should be deleted. Add a contact.ts file to the ClientApp/components/contacts/ directory. This will hold the replacement for the interface we just deleted. The full class definition follows.

export class Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;

    constructor(data?: any) {
        if (data == null) return;
        (<any>Object).assign(this, data);
    }

    getAddress(): string {
        return `${this.address} ${this.city}, ${this.state} ${this.postalCode}`;
    }

}

This class is very simple and will be used later to show how a function call can be used as part of a view.

Contact Service

Since the application will now have two places that need to access the ASP.NET Core API lets to refactor the API access into a service. This is the same style used by the Aurelia, Angular and React applications. Add a contactService.ts file to the contacts directory. The service will provide functions to get all contacts or a single contact an ID. The following is the full class.

import { Contact } from './contact';

export class ContactService {
    private baseUrl = 'http://localhost:13322/api/contactsApi/';

    getAll(): Promise<Contact[]> {
        return fetch(this.baseUrl)
            .then(response => response.json() as Promise<Contact[]>)
            .then(contacts => Array.from(contacts, c => new Contact(c)));
    }

    getById(id: string): Promise<Contact> {
        return fetch(`${this.baseUrl}${id}`)
            .then(response => response.json())
            .then(contact => new Contact(contact));
    }
}

Now the API access in the ContactListComponent can be refactored to use the service. First, add imports for contact and service.

import { Contact } from './contact';
import { ContactService } from './contactService';

Next, replace the fetch call with a service call.

Before:
fetch('http://localhost:13322/api/contactsApi/')
    .then(response => response.json() as Promise<Contact[]>)

After:
let contactService = new ContactService();
contactService.getAll()

Contact Detail Component

Add a contactDetail.ts which will be the backing component for the contact detail view. The following is the full class. Pretty much all it is doing is using get contact service to get contact detail by ID when it is mounted.

import Vue from 'vue';
import { Component, Prop } from 'vue-property-decorator';
import { Contact } from './contact';
import { ContactService } from './contactService';

@Component
export default class ContactDetailComponent extends Vue {
    contact: Contact = new Contact();
    @Prop() id: string;

    mounted() {
        let contactService = new ContactService();
        contactService.getById(this.id)
            .then(data => {
                this.contact = data;
            });
    }
}

Now add a contactDetail.vue.html file for the UI bits of the contact detail. This is basically just HTML with the same binding syntax as before. Notice that the binding of address is a function call. The other Vue things to note are that the details will only show if contact is truthy using the v-if.

<template>
    <div>
        <h1>Contact Details</h1>
        <hr />
        <div v-if="contact">
            <dl class="dl-horizontal">
                <dt>ID</dt>
                <dd>{{ contact.id }}</dd>
                <dt>Name</dt>
                <dd>{{ contact.name }}</dd>
                <dt>Address</dt>
                <dd>{{ contact.getAddress() }}</dd>
                <dt>Phone</dt>
                <dd>{{ contact.phone }}</dd>
                <dt>Email</dt>
                <dd>{{ contact.email }}</dd>
            </dl>
        </div>
        <router-link to="/contactlist">Back to List</router-link>
        <hr />
    </div>
</template>

<script src="./contactDetail.ts"></script>

Routing with a Parameter

Finding the proper way to route with at parameter in Vue was not easy. The way it is done has evolved over time making find the right way a little challenging. The first step is to add a route for the contact detail by adding a new item to the routes array in the boot.ts file.

{ path: '/contactdetail/:id', component: require('./components/contacts/contactDetail.vue.html'), props: true }

The :id in the path denotes a parameter. The props: true bit is also key to getting the ID when in the contact detail component. The contactlist.vue.html needs to be updated to link to the contact detail route.

Before:
<td>{{ contact.id }}</td>

After:
<td>
  <router-link :to="'/contactdetail/' +  contact.id">{{ contact.id }}
  </router-link>
</td>

Finally, in the ContactDetailComponent we need to use the ID. To do so we need an import to allow the use of the Prop decorator.

import { Component, Prop } from 'vue-property-decorator';

Now all that is needed is to apply the decorator to a property of the class that matches the name of the parameter in the route.

@Prop() id: string;

Now the ID can be used to get the proper contact from the contact service. The following is code that was already shown, but the full context of how the prop decorator is used is important so I am repeating it here.

@Component
export default class ContactDetailComponent extends Vue {
    contact: Contact = new Contact();
    @Prop() id: string;

    mounted() {
        let contactService = new ContactService();
        contactService.getById(this.id)
            .then(data => {
                this.contact = data;
            });
    }
}

Wrapping Up

This brings the projects one step closer to being on the same level feature-wise. Look for one more post to get the Vue project features lined up with the other samples in the solution.

Keep in mind that this is my first look at Vue and my examples may or may not be idiomatic.

The code in a finished state can be found here.

Vue: Contact Detail Read More »

ASP.NET Core Basics: Vue with an API

In the past, I have done some exploration on Aurelia, Angular and React via the ASP.NET Core Basics series. This post is going to take a similar approach using Vue. The code for the project will be in the same repo as the previous basics examples and will be utilizing the same API to pull data. The code before adding the Vue project can be found here.

Project Creation

There is not a template for Vue built into Visual Studio, but there is a set of templates that can be used via the .NET CLI with the dotnet new that includes Vue (as well as Aurelia and Knockout). A full list of available templates can be found here. The template we need is Microsoft.AspNetCore.SpaTemplates and can be installed using the following command from a command prompt.

dotnet new -i "Microsoft.AspNetCore.SpaTemplates::*"

Create a Vue folder at the same level as the other projects, for the samples this would be in the src folder. In the command prompt navigate to the src/Vue/ directory. Run the following command to create the Vue project.

dotnet new vue

After the project generation completes run the following to get the needed npm packages installed.

npm  install

The last step is to get the new project added to the existing solution. Navigate the command prompt to your solution file. For the sample project, this is the root of the repo. Then run the following command (this could also be done through Visual Studio instead of using the CLI).

dotnet sln add src/Vue/Vue.csproj

Adding the Contact List

In the ClientApp/components directory add a new contacts directory to house all the awesome contact related functionality we will be adding. Next, add a new contactlist.ts. To this new file add the interface which defines what a Contact looks like.

interface Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;
}

Above the contact interface, add the following imports needed to create a Vue component.

import Vue from 'vue';
import { Component } from 'vue-property-decorator';

Finally, add the contact list component. This component maintains a list of contacts which gets filled from our existing API when the component is mounted (see the docs for more information on Vue’s lifecycle hooks).

@Component
export default class ContactListComponent extends Vue {
    contacts: Contact[] = [];

    mounted() {
        fetch('http://localhost:13322/api/contactsApi/')
            .then(response => response.json() as Promise<Contact[]>)
            .then(data => {
                this.contacts = data;
            });
    }
}

The following if the full component just to provide full context.

import Vue from 'vue';
import { Component } from 'vue-property-decorator';

@Component
export default class ContactListComponent extends Vue {
    contacts: Contact[] = [];

    mounted() {
        fetch('http://localhost:13322/api/contactsApi/')
            .then(response => response.json() as Promise<Contact[]>)
            .then(data => {
                this.contacts = data;
            });
    }
}

interface Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;
}

Next up is the UI for this contact list component. In the same directory add contactlist.vue.html.  The following is the full file.

<template>
    <div>
        <h1>Contact List</h1>
        <table v-if="contacts.length" class="table">
            <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
            </thead>
            <tbody>
            <tr v-for="contact in contacts">
                <td>{{ contact.id }}</td>
                <td>{{ contact.name }}</td>
            </tr>
            </tbody>
        </table>

        <p v-else><em>Loading...</em></p>
    </div>
</template>

<script src="./contactlist.ts"></script>

All of the above is pretty straightforward. All the Vue specific items have a v- prefix.

Add the Contact List to Navigation

The last bit needed to have a working contact list is adding it to navigation so the user can get to the list. The routes are defined in the boot.ts file in the routes array. Add the following line to the array to handle our contact list.

{ path: '/contactlist', component: require('./components/contacts/contactlist.vue.html') }

Now that the router knows to handle the contact list it needs to be added to the navigation UI. Open the /navmenu/navmenu.vue.html file and find the unordered list that is the navigation menu. Add a new list item to provide a link to the contact list.

<li>
    <router-link to="/contactlist">
        <span class="glyphicon glyphicon-list-alt"></span> Contact List
    </router-link>
</li>

Wrapping Up

Vue reminds me a lot of Aurelia in its simplicity so far which is awesome. Look for the same progression of posts for Vue that happened with React over the last few weeks.

The code in its final state can be found here.

ASP.NET Core Basics: Vue with an API Read More »

ASP.NET Core Basics: React with an API

In the past, I have done some exploration on Aurelia and Angular via the ASP.NET Core Basics series. This post is going to take a similar approach as I start doing some exploration with React. The code for the project will be in the same repo as the previous basics examples and will be utilizing the same API to pull data. The code before adding the React project can be found here.

This post is going to cover adding a React project to the existing using the React template that is now built into Visual Studio. The same thing can be accomplished using the .NET CLI so don’t feel like Visual Studio is required. The goal for the React project in this initial post will be to connect to the contacts API and download a list of contacts and render that to the screen. In future posts, I hope to expand this functionality to match that of the Aurelia and Angular projects.

Project Creation

Right-click and select Add > New Project.

In the Add New Project dialog select the ASP.NET Core Web Application. In the case of the sample, the project will be named React. Click OK to continue.

On the next screen make sure and select ASP.NET Core 2.0 and the React.js template. Then click OK.

The following is the resulting React project in the context of the full solution.

Next, make sure and run npm install from a command prompt in the React project’s directory to ensure all the npm packages get restored.

Adding the Contact List

Inside the ClientApp/components/ directory add a file name ContactList.tsx. TSX is the TypeScript version of the React JSX file type. The official docs on JSX can be found here. Since this is my first time working with React I took the FetchData.tsx file and copied the contents and used that as the starting point for my contact list. To lead with there is an interface for what should define a contact.

interface Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;
}

Next, we have an interface for the state of this component with contains a loading flag and an array of contacts.

interface ContactListState {
    contacts: Contact[];
    loading: boolean;
}

In the constructor for the component is where the data is pulled from the API using fetch. The data from the API is then saved to the state of the component using the setState function.

constructor() {
    super();
    this.state = { contacts: [], loading: true };

    fetch('http://localhost:13322/api/contactsApi/')
        .then(response => response.json() as Promise<Contact[]>)
        .then(data => {
            this.setState({ contacts: data, loading: false });
        });
}

Next, the component has a function named renderContactsTable which takes an array of contacts and returns how they should be rendered. In this case, the contacts are rendered to a table that displays the contact ID and Name.

private static renderContactsTable(contacts: Contact[]) {
    return <table className='table'>
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            {contacts.map(contact =>
                <tr key={contact.id}>
                    <td>{contact.id}</td>
                    <td>{contact.name}</td>
                </tr>
            )}
        </tbody>
    </table>;
}

Finally, there is the render function. As you can guess this is what gets called to render the component. In this case, either “Loading” or the contact list gets displayed depending on if the contact list data has been loaded or not.

public render() {
    let contents = this.state.loading
        ? <p><em>Loading...</em></p>
        : ContactList.renderContactsTable(this.state.contacts);

    return <div>
        <h1>Contact List</h1>
        {contents}
    </div>;
}

The following is the full file for reference.

import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import 'isomorphic-fetch';

interface ContactListState {
    contacts: Contact[];
    loading: boolean;
}

export class ContactList extends React.Component<RouteComponentProps<{}>, ContactListState> {
    constructor() {
        super();
        this.state = { contacts: [], loading: true };

        fetch('http://localhost:13322/api/contactsApi/')
            .then(response => response.json() as Promise<Contact[]>)
            .then(data => {
                this.setState({ contacts: data, loading: false });
            });
    }

    public render() {
        let contents = this.state.loading
            ? <p><em>Loading...</em></p>
            : ContactList.renderContactsTable(this.state.contacts);

        return <div>
            <h1>Contact List</h1>
            {contents}
        </div>;
    }

    private static renderContactsTable(contacts: Contact[]) {
        return <table className='table'>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                </tr>
            </thead>
            <tbody>
                {contacts.map(contact =>
                    <tr key={contact.id}>
                        <td>{contact.id}</td>
                        <td>{contact.name}</td>
                    </tr>
                )}
            </tbody>
        </table>;
    }
}

interface Contact {
    id: number;
    name: string;
    address: string;
    city: string;
    state: string;
    postalCode: string;
    phone: string;
    email: string;
}

Add Contact List to Navigation

Now that we have the contact list component it needs to be added to the navigation menu. The first step is to add it to the application’s router. This can be found in the routes.tsx file. The file is short so I am going to include the full content. Lines 7 and 13 are the ones added to handle our contact list.

import * as React from 'react';
import { Route } from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import { FetchData } from './components/FetchData';
import { Counter } from './components/Counter';
import { ContactList } from './components/ContactList';

export const routes = <Layout>
    <Route exact path='/' component={Home} />
    <Route path='/counter' component={Counter} />
    <Route path='/fetchdata' component={FetchData} />
    <Route path='/contactlist' component={ContactList} />
</Layout>;

The last change is to add a navigation link to the NavMenu found in the NavMenu.tsx file. As I am sure most of us are used to adding an item to the nav menu is just adding a new li, but with the React specific NavLink bit.

<li>
  <NavLink to={'/contactlist'} activeClassName='active'>
      <span className='glyphicon glyphicon-th-list-alt'></span> Contact List
  </NavLink>
</li>

Wrapping Up

React is different than both Aurelia and Angular. Don’t take that as a good or bad thing. I don’t plan to pick on a side on the Angular vs React debate I just want to get a good feel for the different frameworks. So far the React experience has been pretty nice and I look forward to doing more exploration.

You can find the finished code for this post here.

ASP.NET Core Basics: React with an API Read More »

Pass ASP.NET Core Appsettings Values to Angular

As part of getting my set of Identity Server 4 sample applications to run in Azure, I needed a way in the Client Application to pass some configuration values from appsettings.json to the Angular front end that could be used both during server-side rendering and client-side rendering. This application is using JavaScriptServices. This solution may need tweaking if your application isn’t using JavaScriptServices. The code for the client application can be found here.

Settings

In this example, we need to pass the address of our Identity Server and API from appsettings.json to Angular. The following is the settings file for this example.

{
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  },
  "IdentityServerAddress": "http://localhost:5000",
  "ApiAddress": "http://localhost:5001/"
}

Providing Configuration Data to Angular

In this application, Angular is loaded from the index action of the home controller. This view can be found in the Views/Home folder in the Index.cshtml file. The following is the file before any changes.

@{
    ViewData["Title"] = "Home Page";
}

<app asp-prerender-module="ClientApp/dist/main-server">Loading...</app>

<script src="~/dist/vendor.js" asp-append-version="true"></script>
@section scripts {
    <script src="~/dist/main-client.js" asp-append-version="true"></script>
}

The first change needed is to inject the configuration data using ASP.NET Core’s DI system. Add the following two lines at the top of the file.

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration

Now the configuration data from the application is available to this view. Next, we need to pull a couple of values out of the configuration data and pass it to the Angular application. To do this we are going to use the asp-prerender-data tag helper. You can read more about it in the official docs. The idea is you construct an object which is then serialized and stored in params.data. In our example, we are passing the URLs for the Identity and API Applications.

<app asp-prerender-module="ClientApp/dist/main-server"
     asp-prerender-data='new {
    apiUrl = Configuration["ApiAddress"],
    identityUrl = Configuration["IdentityServerAddress"]
}'>Loading...</app>

The above is creating a new object with an apiUrl property and an identityUrl property. The following is the full completed view for reference.

@using Microsoft.Extensions.Configuration
@inject IConfiguration Configuration
@{
    ViewData["Title"] = "Home Page";
}

<app asp-prerender-module="ClientApp/dist/main-server"
     asp-prerender-data='new {
    apiUrl = Configuration["ApiAddress"],
    identityUrl = Configuration["IdentityServerAddress"]
}'>Loading...</app>

<script src="~/dist/vendor.js" asp-append-version="true"></script>
@section scripts {
    <script src="~/dist/main-client.js" asp-append-version="true"></script>
}

Angular Server-Side Boot

When Angular gets prerendered on the server-side it runs the code in the boot.server.ts file. This is where we will set up the providers needed on for the server side prerender. This is the bit that I missed for the longest time when trying to get this example going. I kept trying to find a way to add the providers in the app.module.server.ts file. Add any providers you need to the providers constant. For example, the following is passing URLs for an API and Identity Server in addition to the defaults provided by JavaScriptServices.

const providers = [
    { provide: INITIAL_CONFIG, useValue: { document: '<app></app>', url: params.url } },
    { provide: APP_BASE_HREF, useValue: params.baseUrl },
    { provide: 'BASE_URL', useValue: params.origin + params.baseUrl }
    { provide: 'API_URL', useValue: params.data.apiUrl },
    { provide: 'IDENTITY_URL', useValue: params.data.identityUrl }
];

Lower in the same file we can pass through the configuration values to the client side render as globals on the window object. To do this add a globals property to the object being passed to the resolve call.

return new Promise<RenderResult>((resolve, reject) => {
    zone.onError.subscribe((errorInfo: any) => reject(errorInfo));
    appRef.isStable.first(isStable => isStable).subscribe(() => {
        // Because 'onStable' fires before 'onError', we have to delay slightly before
        // completing the request in case there's an error to report
        setImmediate(() => {
            resolve({
                html: state.renderToString(),
                globals: {url_Config: params.data}
            });
            moduleRef.destroy();
        });
    });
});

The above will have the URLs as part of a single object, but you could have each URL as its own property if you prefer.

Angular Client-Side

Now that the server-side has providers for API URL and Identity URL we need to provide the client-side with the same capabilities. These changes will be in the app.module.browser.ts file. The first step is to add providers for each.

providers: [
    { provide: 'ORIGIN_URL', useFactory: getBaseUrl },
    { provide: 'API_URL', useFactory: apiUrlFactory },
    { provide: 'IDENTITY_URL', useFactory: identityUrlFactory },
    AppModuleShared
]

Next, we need functions to return the URLs from the url_Config property of the window object which the following two functions do.

export function apiUrlFactory() {
    return (window as any).url_Config.apiUrl;
}

export function identityUrlFactory() {
    return (window as any).url_Config.identityUrl;
}

Wrapping Up

With the above, you can now use your configuration values from ASP.NET Core and pass them through to your Angular application. In hindsight, the process is pretty simple, but getting to that point took me much longer to figure out than I would like to admit. I hope this post saves you some time!

Pass ASP.NET Core Appsettings Values to Angular Read More »

JavaScriptServices: What happen to Aurelia, Vue, and Knockout Templates

With the release of Visual Studio 2017 version 15.3 there are now built in web application templates for Angular, React, and React and Redux.

This is an awesome addition and makes creating new applications with the most popular frameworks simple. What do you do if your framework isn’t one of the top 3 options? JavaScriptServices can help out here and has provided templates for Aurelia, Vue, and Knockout in the past.

Where have they gone?

This is where it gets a little tricky as the templates still exist and are still being maintained, but finding them is a little harder at the moment for some reason. Yeoman was how JavaScriptServices was used in the past, but that has now transitioned to using the .NET CLI and can be added using the following.

dotnet new --install Microsoft.AspNetCore.SpaTemplates::*

After that is complete you will see a list of templates that are now available.

Now you can create an Aurelia project using the following command.

dotnet new aurelia

Wrapping up

I was very happy to see that support for the other frameworks hadn’t been dropped. There are a ton of other templates available for dotnet new which can be found here.

 

JavaScriptServices: What happen to Aurelia, Vue, and Knockout Templates Read More »

Identity Server: Sample Exploration and Initial Project Setup

This post will be a continuation of my exploration around Identity Server which was started with this post which was more of an overview of the space and my motivations for learning about Identity Server. There were a lot of things that were unclear to me as I first started looking through the samples so this post is going to communicate so of those issues and hopefully clear them up for you as well.

After this post, the follow-up post should be more focused on one thing instead of trying to cover so much information in on go.

The following are all the posts in this series.

Identity Server: Introduction
Identity Server: Sample Exploration and Initial Project Setup (this post)
Identity Server: Interactive Login using MVC
Identity Server: From Implicit to Hybrid Flow
Identity Server: Using ASP.NET Core Identity
Identity Server: Using Entity Framework Core for Configuration Data
Identity Server: Usage from Angular

Typical Sample Solution Structure

I started my exploration with the IdentityServer4.Sample repo specifically in the Quickstarts folder. For me, this was a mistake as I didn’t have a good enough grasp on the larger concepts for the code to provide proper guidance. Big surprise here, but using the docs and actually walking through the project creation was very helpful.

The code associated with this blog can be found here. The solution contains three projects.

  • ApiApp – Backend for the application and is a resource that is will require authorization to access. The API will be an ASP.NET Core Web API.
  • ClientApp – Frontend application that will be requesting authorization. This is an ASP.NET Core application that is hosting an Angular (4) app.
  • IdentityApp – This is ASP.NET Core application that is the IdentityServer and will end up authorizing users and issuing tokens for resources.

Identity Application

For the Identity application, create an ASP.NET Core Web Application using the empty template targeting at least ASP.NET Core 1.1. Next, using NuGet install the IdentityServer4 NuGet package.

Now that the IdentityServer4 NuGet package is installed open up the Startup class and add the following to the ConfigureServices function.

public void ConfigureServices(IServiceCollection services)
{
    services.AddIdentityServer()
        .AddTemporarySigningCredential()
        .AddInMemoryApiResources(Config.GetApiResources())
        .AddInMemoryClients(Config.GetClients());
}

The above registers IdentityServer with ASP.NET Core as a service available via dependency injection using temporary and in-memory components as a stand in for testing. The Config class used here will be added a bit later.

Next, the Configure function should look like the following.

public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env, 
                      ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole();

    if (env.IsDevelopment())
    {
        app.UseDeveloperExceptionPage();
    }

    app.UseDeveloperExceptionPage();
    app.UseIdentityServer();
}

The above is a basic Configure function. app.UseIdentityServer() is the only the only bit related to IdntityServer and it is adding it to the application’s pipeline.

The final part of this application is the Config class which is used to define the in memory test resources for this application. As you can see below it is defining both API resources and Clients. In the future theses, items would be pulled from a datastore.

public class Config
{
    public static IEnumerable<ApiResource> GetApiResources()
    {
        return new List<ApiResource>
        {
            new ApiResource("apiApp", "API Application")
        };
    }

    public static IEnumerable<Client> GetClients()
    {
        return new List<Client>
        {
            new Client
            {
                ClientId = "clientApp",

                // no interactive user, use the clientid/secret for authentication
                AllowedGrantTypes = GrantTypes.ClientCredentials,

                // secret for authentication
                ClientSecrets =
                {
                    new Secret("secret".Sha256())
                },

                // scopes that client has access to
                AllowedScopes = { "apiApp" }
            }
        };
    }
}

API Application

For the API application, create an ASP.NET Core Web Application using the Web API template targeting at least ASP.NET Core 1.1. Next, using NuGet install the IdentityServer4.AccessTokenValidation NuGet package.

Ater the above NuGet package installed open up the Startup class. In the Configure function, the IdentityServer middleware needs to be added to the application pipeline before MVC using the app.UseIdentityServerAuthentication function. The following is the full Configure function.

public void Configure(IApplicationBuilder app, 
                      IHostingEnvironment env, 
                      ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

    app.UseIdentityServerAuthentication(new IdentityServerAuthenticationOptions
    {
        Authority = "http://localhost:5000",
        RequireHttpsMetadata = false,
        ApiName = "apiApp"
    });

    app.UseMvc();
}

Notice that the address of the of the authority must be specified (this will need to be the address the Identity Application is running on) as well as the ApiName matches the API Resource we added in the Config class of the Identity Application.

Next, in following the IdentityServer quickstart docs add a new IdentityController to the project. Just to be 100% clear this is just a test endpoint to show how to require authorization on a controller and isn’t something that is required to use IdentityServer. The controller has a single Get that returns the type and value of all the user’s claims.

[Route("api/[controller]")]
[Authorize]
public class IdentityController : Controller
{
    [HttpGet]
    public IActionResult Get()
    {
        return new JsonResult(from c in User.Claims select new { c.Type, c.Value });
    }
}

The [Authorize] attribute on the class is the bit that requires calls to this endpoint to have authorization. Keep in mind that the same attribute can be left off the class level and added to specific functions if the whole controller doesn’t require authorization.

Adding the [Authorize] attribute means that the IdentityServer middleware we added in the Startup class will validate the token associated with the request to make sure it is from a trusted issues and that it is valid for this API.

Client Application

For the Client application, I deviated from the samples a bit. Instead of just creating a new MVC application I used JavaScriptServices to generate an Angular (4) application. If you want detail on how that is done you can check out this post (yes it says Angular 2, but the newest version of JavaScriptServices now outputs Angular 4 and the steps haven’t changed). An Angular application is my end goal and why I made this deviation from the samples.

After the Client application has been created use NuGet to add the IdentityModel package. This package is to make interacting with the Identity Application simpler.

For this first go instead of actually interacting with the Identity Application from Angular I will be using it from MVC instead. The detail of interaction from Angular will come in a later post. The IdentityController is what does the interaction with both the Identity Application and the API Application interactions in this version of the client application. The following is the full IdentityController class.

public async Task<IActionResult> Index()
{
  var discovery = 
      await DiscoveryClient.GetAsync("http://localhost:5000");

  var tokenClient = new TokenClient(discovery.TokenEndpoint, 
                                    "clientApp", 
                                    "secret");
  var tokenResponse = 
      await tokenClient.RequestClientCredentialsAsync("apiApp");

  ViewData["tokenResult"] = tokenResponse.IsError 
                            ? tokenResponse.Error 
                            : tokenResponse.Json.ToString();

  var client = new HttpClient();
  client.SetBearerToken(tokenResponse.AccessToken);

  var apiResponse = 
      await client.GetAsync("http://localhost:5001/api/identity");
 
  ViewData["apiResult"] = apiResponse.IsSuccessStatusCode 
                          ? await apiResponse.Content.ReadAsStringAsync() 
                          : apiResponse.StatusCode.ToString();

  return View();
}

In the above, you can see the IdentityModel in action. Using the DiscoveryClient means the client application only needs to know about the root address of the Identity Application. TokenClient is being used to request a token from the Identity Application for the clientApp using the client secret which in this case is actually the word secret. Keep in mind in a real application secrets should be kept using the ASP.NET Core Secrets manager, see this related post. Also, take note that clientApp and secret are the values that were defined in the Config class of the Identity application.

The rest of the code is taking the token response and making a call to the API application with the response from both of those calls being stored in ViewData for display on the view associated with the controller.

The view is just an Index.cshtml file in the path Views/Identity. The following is the full view.

@{
    ViewData["Title"] = "Identity";
}

@ViewData["tokenResult"]
@ViewData["apiResult"]

It isn’t pretty, but the whole point of this controller and view is just for verification that the three applications are properly communicating with each other.

URL Configuration

In this setup, it is important that the URL for the Identity Application and API Application be fixed so they can be accessed by the client. In a more production level application, these values would at a minimum need to be in configuration. The following is the setup used for this solution.

  • Identity Application – http://localhost:5000
  • API Application – http://localhost:5001
  • Client Application – http://localhost:5002

There are a couple of ways to configure test values. The first is to open the project properties and select the Debug tab and set the App URL.

The second option is to go to the Program class for each project and add a UseUrls to the WebHostBuilder like the following.

public static void Main(string[] args)
{
    var host = new WebHostBuilder()
        .UseKestrel()
        .UseUrls("http://localhost:5002")
        .UseContentRoot(Directory.GetCurrentDirectory())
        .UseIISIntegration()
        .UseStartup<Startup>()
        .Build();

    host.Run();
}

Wrapping up

After going through the above process I now have a much better understanding of how the very basic setup using Identity Server should work. I hope if you made this far you found some helpful bits.

There is a bit of strangeness using Visual Studio to try and launch all three applications and can result in an error message if multiple of the projects are run in debug mode. For the most part, this can be worked around by only debugging one application at a time. It is a bit annoying at the beginning stages, but once an applications gets past that point I imagian that the Identity Application won’t require much debugging.

If there are any questions please leave a comment and I would be happy to try and help. The finished code can be found here. This basic example will be expanded over time and all the related entries can be found in the IdentityServer category.

Identity Server: Sample Exploration and Initial Project Setup Read More »

Setting Up Visual Studio Code for Debugging ASP.NET Core

Visual Studio Code is a cross-platform source code editor from Microsoft. Out of the box, Code’s language support includes JavaScript, TypeScript, and Node. Using Codes extension system support is available for almost any language you want to use including C#, F#, Elixir, SQL, Swift, and Java. As of this writing, there are 734 language extensions available.

I have been using VS Code since it was first released after Build in 2015, but I have only been using it as an editor never taking advantage of the Debugging capabilities it has available. In this post, I am going to walk through everything that is needed to get a new ASP.NET Core with an Angular front end to run via VS Code’s debugger.

Test application

The first thing I did was to create a new application using JavaScriptServices specifically for this post. For instructions on how to use JavaScriptServices to generate an application check out this post.

On Windows, after the application has been generated and you are in the application directory you can use the following command to open the directory in VS Code.

code .

I am sure there is something similar on Linux and Mac, but I don’t have the environments to try on.

VS Code Overview

When VS Code opens you will see a view close to the following.

The icons down the left side of the screen are for Explorer (shows currently open directory and files), Seach, Source Control (git support is built in), Debug, and Extensions.

Debug

The Debug tab will be our focus so click on it which will take you to the following view.

Using the gear with red circle select .NET Core as the environment for the project.

If you don’t see .NET Core listed click More… and click install for the C# option.

After selecting an environment VS Code will add a launch.json file to the project. This file defines what happens when the start button is clicked in the debugger. At this point clicking the start button to run the application using the debugger will result in an error that Could not find the preLaunchTask ‘build’.

Next, click the Configure Task Runner option and select .NET Core.

This will add a task.json file with a build command that the launch.json is looking for. At this point, I had to restart VS Code to get it to properly pick up the new files. This seems to be an issue that will be fixed with the next release of VS Code and can be tracked using this issue.

After restart and trying to run the debugger again I ran into the error Run ‘Debug: Download .NET Core Debugger’ in the Command Palette or open a .NET project directory to download the .NET Core Debugger.

I ended up having to uninstall and reinstall the C# extension and then opening a C# file to get the debugger to download. If you are having this problem make sure and open a C# file before going as far as reinstalling the C# extension.

Hitting run in the debugger now give the error launch: launch.json must be configured. Change ‘program’ to the path to the executable file that you would like to debug.

To fix this issue click Open launch.json and you will find two places with the following.

"program": "${workspaceRoot}/bin/Debug/<target-framework>/<project-name.dll>"

Change both places to point to the dll your application builds. In the case of my project named DebugTest the final version ended up being the following.

"program": "${workspaceRoot}/bin/Debug/netcoreapp1.1/DebugTest.dll"

Wrapping up

Debugging now works! Based on this post it would seem like debugging in VS Code is a big pain, but really after you get it set up once it just works. For new projects, you just have to let it add the

For new projects, you just have to let it add the launch.json and tasks.json and then set the path to your project’s assembly in launch.json. After that, you are ready to go.

I wait too long to figure this process out. I hope this helps you get started with debugging in VS Code.

Setting Up Visual Studio Code for Debugging ASP.NET Core Read More »

Upgrading a JavaScript Services Application

As part of the ASP.NET Core Basics series of posts, JavaScript Services was used to create a couple of front end for a basic contacts API using Aurelia and Angular 2. Theses applications were created a few months ago and JavaScript Services has kept moving since then. This post is going to look at one strategy for taking an application created on an older version of JavaScript Services and update it to match the current version. This post will be following the upgrade of the Angular project from ASP.NET Core Basics repo with the starting point of the code being from this release.

The strategy

One of the considerations when doing this upgrade was getting the changes that happen on the ASP.NET Core side of the application and not just the JavaScript bits. In order to make sure that nothing was missed I decided to use JavaScript Services to generate a new application and use that to compare with the implementations in the existing application.

Create comparison application

This is going to assume JavaScript Services is already installed. If it isn’t this page has instructions or this post has sections that deal with creating a new application using JavaScript Services.

The update

Following is the files that changed during this update. This is also the list of files I would check anytime an upgrade needs to be done.

Angular.csproj
ClientApp/boot-client.ts
ClientApp/boot-server.ts
Program.cs
package.json
webpack.config.js
webpack.config.vendor.js

There were a fair amount of changes in the files listed above and instead of posting the code the differences can be found here. The previous diff didn’t contain the webpack.config files and those diffs can be found here and here.

After all the files have been updated make sure to run the following command from a command prompt in your project directory to make sure webpack has vendor related items regenerated.

webpack --config webpack.config.vendor.js

Wrapping up

This post is a lighter on the details that I do most of the time, but this type of upgrade would just have been a wall of code and not been overly useful and the commits on GitHub are a much better guide to what the upgrade looked like. My feeling is that over time the number of changes going forward may end up being smaller and easier to integrate.

Both the Aurelia and Angular projects have been upgraded and the final version of the code can be found here.

Upgrading a JavaScript Services Application Read More »