Send form input via an Angular 2 component to ASP.NET Core Web API

So far we’ve set up a basic Angular 2 and .NET Core web application and made it retrieve the weather for London which is then displayed via an Angular 2 component.

However, unless all of your users live in London, you’ll want to let people choose a different city.

We’ll keep it simple for now and just present a text input field for them to type in the city name.

Pass the chosen city to Web API

The weather component currently calls off to our web api and always requests the weather for London. We need to change this so it takes a user input.

Here’s the component as it stands before we make any changes.

export class WeatherComponent {
    public weather: Weather;
    constructor(http: Http) {
        http.get('/api/weather/city/London').subscribe(result => {
            this.weather = result.json();

Now change it to look like this…

export class WeatherComponent {
    public weather: Weather;

    constructor(private http: Http) {

    public getWeather(chosenCity: string) {
        this.http.get('/api/weather/city/' + chosenCity).subscribe(result => {
            this.weather = result.json();

We’ve added a getWeather function that takes in a city (as a string) and then makes an http get request to our .NET Core Web Api.

We only want to request the weather when the user enters a city so we’ve removed the initial http call from the constructor.

The constructor has one interesting addition, the private keyword. As before, we are bringing the http service into our component (so we can use it to make calls to our web api) but we’re also registering it as a private field. This ensures the getWeather function is able to access the http service via this.http.

Add a city textbox to the weather page

It’s not much use accepting a city for our weather check if our users can’t type one in so now we turn our attention back to the component’s html template.

Time to modify weather.component.html

<h1>Weather check</h1>

<label for="city">City</label>
<input type="text" id="city" [(ngModel)]="chosenCity" />
<input type="button" value="Get Weather" (click)="getWeather(chosenCity)" />

<div *ngIf="weather">
    <h3>Weather for {{weather.city}}</h3>

    <table class="table table-bordered table-striped">

We’ve added a regular html textbox and button.

The [(ngModel)] attribute indicates to Angular that it should bind whatever is typed into this textbox to a field called chosenCity.

By adding a (click) attribute to the button we indicate that any click of the button should call the getWeather method we defined in our weather component, passing in the chosenCity (which will always reflect the contents of the textbox).

Now if you try running this you’ll get an error indicating…

Can’t bind to ‘ngModel’ since it isn’t a known property of ‘input’.

This is slightly cryptic but it turns out NgModel is part of the Angular Forms module which we haven’t included in our application yet.

Head on over to app.module.ts and make these changes.

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { FormsModule } from '@angular/forms';
import { UniversalModule } from 'angular2-universal';

import { AppComponent } from './components/app/app.component'
import { NavMenuComponent } from './components/navmenu/navmenu.component';
import { HomeComponent } from './components/home/home.component';
import { FetchDataComponent } from './components/fetchdata/fetchdata.component';
import { CounterComponent } from './components/counter/counter.component';
import { HelloWorldComponent } from './components/helloworld/helloworld.component';
import { WeatherComponent } from './components/weather/weather.component';

    bootstrap: [ AppComponent ],
    declarations: [
    imports: [
        UniversalModule, // Must be first import. This automatically imports BrowserModule, HttpModule, and JsonpModule too.
            { path: '', redirectTo: 'home', pathMatch: 'full' },
            { path: 'home', component: HomeComponent },
            { path: 'counter', component: CounterComponent },
            { path: 'fetch-data', component: FetchDataComponent },
            { path: 'hello', component: HelloWorldComponent },
            { path: 'weather', component: WeatherComponent },
            { path: '**', redirectTo: 'home' }
export class AppModule {

Now try hitting your page again and everything should work as you’d expect.


So now you know how to take user input and pass it (via an Angular 2 component) to .NET Core Web API.

If you want to take this weather app a step further, here are some ideas you could try for yourself.

  • Create a more interesting (better designed) html template for our current weather component
  • Display units next to the temperature (currently the ui doesn’t tell you what unit the temp is in)
  • Integrate into other OpenWeather API calls (such as forecasts, not just the current weather)
  • Refactor our weather API controller so the calls off to OpenWeather are made in a dedicated class (rather than the controller)

photo credit: jcburns Wacky QWERTY. via photopin (license)

  • Don Starkey

    How do i get this to work with ie9

    • Hi.

      I haven’t tried it on IE9 myself.

      Would need a bit more detail really. What doesn’t work specifically?

      According to https://angular.io/docs/ts/latest/guide/browser-support.html Angular 2 works on IE9…


      • Don Starkey

        Hi Jon,

        Thanks for the reply. I have downloaded IETester. I am able to retrieve weather information through the api on IE 10 and 11 but not IE9. This is holding us back from our move to Angular2 from AngularJs. Any help resolving this issue is greatly appreciated. Once again, thank you.


        • Hi Don.

          Did you get any further with this issue?


          • Don Starkey

            no still stuck, I tried a couple of shims but it did not seem to work. By any chance have you tried to update this to angular 4? I know its another issue but it seems like this is the path to go. I was able to upgrade Angular 2 packages but Webpack kept throwing errors so had to revert my changes. In any event thanks for the great article. Hopefully someone smarter than me will update the VS Angular Template to Angular 4 and have Webpack HMR working. Again, thank you.

          • Regarding Angular 4, probably worth keeping an eye on this thread…


    • Elvin Dauz

      Also not working for IE11 for me. Even the Counter button.
      I found that this is an issue for IE11 and below like this:


      Their solution is to uncomment some lines in polyfills.ts but I can’t find this file in our solution. I guess there are changes when building it with VS. They’re suggesting to compile it to es5 and not es6 as fat arrows (=>) are not supported in these browsers. This can be done by changing to “target”: “es5” in tsconfig.json but I still can’t run the app.

      I think I’m getting to the right direction. I just need to find the right file in VS to edit.

  • Řōbîn Řēgmï

    Hello there, I got one problem here that how can in add custom css, js, png, etc from my own template theme? There is the webpack.config.js to bundle the files but cannot understand. I’ve tried many time like import’../assets/css/layout.css’ in ts component but the webpack throwing an error. Thanks.

    • HI.

      At a simple level you can just add css files to the wwwroot folder. Once there you can link to them as you would normally.

      By way of example, I tried adding a custom.css file to wwwroot/dist and referenced it as follows from _Layout.cshtml.

      Alternatively, if you want to add styles to your individual angular 2 components, there are a few options.

      The official docs cover this quite nicely.



  • Jeff Swenson

    This was excellent. I’ve started and stopped 3 different tutorials for Angualr2 starting with the template is what made the difference for me. Now that I’ve done this series, I’m ready to get into the “weeds” of Angular.

    Nice work!

  • Asim Aslam

    It is very nicely written, but I am bit stuck with something.
    Everything is working fine, but (click)=getWeather(chosenCity) is not firing.
    I did everything you teach here.
    Can you please help me on this?

    • steady


      • Asim Aslam

        Yes, I did that with quotes. but click event is not firing

        • steady

          Post the contents of weather.component.html, weather.component.ts, and WeatherController.cs

          • Asim Aslam

            Weather check


            Weather for {{weather.city}}



            import { Component } from ‘@angular/core’;
            import { Http } from ‘@angular/http’;
            selector: ‘weather’,
            template: require(‘./weather.component.html’)
            export class WeatherComponent {
            public weather: Weather;
            constructor(private http: Http) {

            public getWeather(chosenCity: string) {
            this.http.get(‘/api/weather/city/’ + chosenCity).subscribe(result => {
            this.weather = result.json();
            interface Weather {
            temp: string;
            summary: string;
            city: string;

            namespace Qr.Asimplify.com.Controllers
            public class WeatherController : Controller
            public async Task City(string city)
            using (var client = new HttpClient())
            client.BaseAddress = new Uri(“http://api.openweathermap.org”);
            var response = await client.GetAsync($”/data/2.5/weather?q={city}&appid=96a5bff30fece5ecf2a554c24a76e400&units=metric”);
            var stringResult = await response.Content.ReadAsStringAsync();
            var rawWeather = JsonConvert.DeserializeObject(stringResult);
            return Ok(new
            Temp = rawWeather.Main.Temp,
            Summary = string.Join(“,”, rawWeather.Weather.Select(x => x.Main)),
            City = rawWeather.Name
            catch (Exception ex)
            return BadRequest($”Error getting weather from OpenWeather: {ex.Message}”);

          • steady

            So just some typos.

            Weather.component.ts: looks fine
            public async Task City(string city)
            var response = await client.GetAsync($”/data/2.5/weather?q={city}&appid=96a5bff30fece5ecf2a554c24a76e400&units=metric”); //The api key should not be in your source code. Consider having it has an environment variable instead.
            var rawWeather = JsonConvert.DeserializeObject(stringResult);

  • Saravanan Ramalingam

    Doesn’t ngModel require the backing field chosenCity to be declared in the Component? If true, it doesn’t have to be explicitly passed as input to getWeather()

  • Kevin Clary

    The demo is working for me in development, but when I deploy it to IIS, the fetch data is failing with a 404 not found. In Fiddler, I can see that the request GET http://myserver/api/SampleData/WeatherForecasts HTTP/1.1 (which gets 404) instead of GET http://localhost:57769/api/SampleData/WeatherForecasts HTTP/1.1 (which works in development) – any idea how to deploy this to IIS successfully?

  • Jennifer Fadriquela

    I am having an error when including “import { UniversalModule } from ‘angular2-universal’;”
    How should I properly install this module?

  • Felix Rabinovich

    Great series. One small update – the latest template includes FormsModule out of the box; so the last error (ngModel not being part of input) is taken care of 🙂