Create an Angular 6 Site in .Net Core Part 2
Tags: tutorial, dotnetcore, angular, webdev
Published: 2019-01-31 22:47:56

---
title: Create an Angular 6 Site in .Net Core Part 2
published: true
description: 
tags: tutorial, dotnetcore, angular, webdev
canonical_url: http://charles.stuartedwards.me.uk/blog/create-an-angular-6-site-in-net-core-2-1-from-scratch-pt2
series: Angular 6 Site in .Net Core
---


Continued from [Part 1](https://dev.to/cstuartedwards/create-an-angular-6-site-in-net-core-part-1-198c)

In the Tour of Heroes tutorial you simulate the data server using the in-memory Web API module. We will remove this and write a .Net Core API service to handle the requests from the angular application. We will create an in-memory database using entity framework and do some data seeding to put an initial list of heroes into the database.

1. In the **Startup** class add **services.AddMvc()** to the **ConfigureServices** method:
    ~~~ csharp
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddSpaStaticFiles(configuration =>
		{
			configuration.RootPath = "ClientApp/dist";
		});
		services.AddMvc();
	}
    ~~~

2. In the **Configuration** method add the following code above app.UseSpa:
    ~~~ csharp
	app.UseMvc(routes =>
	{
		routes.MapRoute(
		name: "default",
		template: "{controller}/{action=Index}/{id?}");
	});
    ~~~

	The method should look like this:
    ~~~ csharp
	public void Configure(IApplicationBuilder app, IHostingEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}

		app.UseStaticFiles();
		app.UseSpaStaticFiles();

		app.UseMvc(routes =>
		{
			routes.MapRoute(
				name: "default",
				template: "{controller}/{action=Index}/{id?}");
		});

		app.UseSpa(spa =>
		{
			// To learn more about options for serving an Angular SPA from ASP.NET Core, 
			// see https://go.microsoft.com/fwlink/?linkid=864501
			spa.Options.SourcePath = "ClientApp";

			if (env.IsDevelopment())
			{
				spa.UseAngularCliServer(npmScript: "start");
			}
		});
	}
    ~~~

3. Add a **Models** folder to the project: </br>
<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-14.png">

4. Add a **Hero** class to the Models folder: Select the **Models** folder. Press **Shift + Alt + C** to open the **Add New Item** dialog. Select the Class item and name it **Hero.cs**.</br>
 <img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-15.png">
 
5. Add a public property for **Id** and **Name**:
    ~~~ csharp
	public class Hero
	{
		public int Id { get; set; }
		public string Name { get; set; }
	}
    ~~~
	
6. Add the database context class called **HeroesContext**: Select the **Models** folder. Press **Shift + Alt + C**. Select the Class item and name it **HeroesContext.cs**:

7. The class needs to inherit from the **DbContext** an you need to add the appropriate using reference:
 <img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-17.png">

8. Add a constructor and property as follows:
    ~~~ csharp
	public class HeroesContext : DbContext
	{
		public HeroesContext(DbContextOptions<HeroesContext> options)
			: base (options)
		{

		}

		public DbSet<Hero> Heroes { get; set; } 
	}
    ~~~

9. We are going to use data seeding to initialise that database with some dummy data for testing. In the **HeroesContext** class override the **OnModelingCreating** method to add the seed data into the database:
    ~~~ csharp
	public class HeroesContext : DbContext
	{
		public HeroesContext(DbContextOptions<HeroesContext> options)
			: base(options)
		{

		}

		public DbSet<Hero> Heroes { get; set; }

		protected override void OnModelCreating(ModelBuilder builder)
		{
			base.OnModelCreating(builder);

			// Seed data for testing
			builder.Entity<Hero>().HasData(
				new Hero { Id = 1, Name = "Super Kid" },
				new Hero { Id = 2, Name = "Mega Baby" },
				new Hero { Id = 3, Name = "Hyper Girl" },
				new Hero { Id = 4, Name = "Plastic boy" },
				new Hero { Id = 5, Name = "The Dark Kite" },
				new Hero { Id = 6, Name = "Blue Ray" },
				new Hero { Id = 7, Name = "Bob" }
			);
		}
	}
    ~~~

10. For testing we will use an in memory database, you would need to hook this up to a real database for production. 
</br></br>
Register the database context with the dependency injection container by adding to the **ConfigureServices** method in the **Startup** class as follows:
    ~~~ csharp
	public void ConfigureServices(IServiceCollection services)
	{
		services.AddDbContext&lt;HeroesContext>(opt =>
			opt.UseInMemoryDatabase("HeroesDatabase"));

		services.AddSpaStaticFiles(configuration =>
		{
			configuration.RootPath = "ClientApp/dist";
		});

		services.AddMvc();
	}
    ~~~
	
	Add the following  using statements to reference the data model and entity framework:
    ~~~ csharp
	using Microsoft.EntityFrameworkCore;
	using AngularSix.Web.Models;
    ~~~

11. To force the data seeding add the following to the **Configure** method in the **Startup** class:
    ~~~ csharp
	using (var serviceScope = app.ApplicationServices.CreateScope())
	{
		var context = serviceScope.ServiceProvider.GetService<HeroesContext>();
		// This will force the data seeding
		context.Database.EnsureCreated();
	}
    ~~~
	
	The **Configure** method should look as follows:
    ~~~ csharp
	public void Configure(IApplicationBuilder app, IHostingEnvironment env)
	{
		if (env.IsDevelopment())
		{
			app.UseDeveloperExceptionPage();
		}

		using (var serviceScope = app.ApplicationServices.CreateScope())
		{
			var context = serviceScope.ServiceProvider.GetService<HeroesContext>();
			// This will force the data seeding
			context.Database.EnsureCreated();
		}

		app.UseStaticFiles();
		app.UseSpaStaticFiles();

		app.UseMvc(routes =>
		{
			routes.MapRoute(
				name: "default",
				template: "{controller}/{action=Index}/{id?}");
		});

		app.UseSpa(spa =>
		{
			// To learn more about options for serving an Angular SPA from ASP.NET Core, see https://go.microsoft.com/fwlink/?linkid=864501
			spa.Options.SourcePath = "ClientApp";

			if (env.IsDevelopment())
			{
				spa.UseAngularCliServer(npmScript: "start");
			}
		});
	}
    ~~~

12. Add a **Controllers** folder: </br>
 <img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-18.png">
 
13. Add an API controller: Select the **Controllers** folder. Press **Shift + Alt + C**. Select the **Web** category and choose **API Controller Class**. Name the Class **HeroesController** and click **Add**
 <img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-19.png" style="width: 100%;">
 
14. Add a **constructor** and a **HeroContext** property to the controller class. Inject the HeroContext object as a parameter into the constructor and assign it to the HeroesContext property:
    ~~~ csharp
	private readonly HeroesContext _context;

	public HeroesController(HeroesContext context)
	{
		_context = context;
	}
    ~~~


15. Replace the **Get** method with the following:
    ~~~ csharp
	// GET: api/<controller>
	[HttpGet]
	public ActionResult<IEnumerable<Hero>> GetAll()
	{
		return _context.Heroes;
	}
    ~~~
	**Please Note:** It is a really really really BAD idea to pull an object directly from a database and hand it off to a presentation layer. Over time additional information may be added to the object and there are no measures in place to limit the information in the api response.  
	
	Check the api call works by running the application and navigating to **/api/heroes**
	<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-20.png" style="width: 100%;">
	
	If you want to test that the Angular app is working with the new api then in the app.module.ts file comment out the **HttpClientInMemoryWebApiModule** declaration in the imports array:
	<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-21.png">
	
	Navigate to **/heroes** and you should see the heroes declared in the GetAll method. </br>
	<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-22.png">
	
	Nice
	
	Now let's finish the remaining api calls

16. Replace the **Put** method with the following **Update** method:
    ~~~ csharp
	// PUT api/<controller>/5
	[HttpPut("{id}")]
	public IActionResult Update(int Id, [FromBody]Hero item)
	{
		var hero = _context.Heroes.Find(item.Id);
		if (hero == null)
		{
			return NotFound();
		}

		hero.Name = item.Name;

		_context.Heroes.Update(hero);
		_context.SaveChanges();
		return NoContent();
	}
    ~~~

17. You need to update the **updateHero** method in **hero.service.ts** to include the hero id in the route:
    ~~~ javascript
	/** PUT: update the hero on the server */
	updateHero(hero: Hero): Observable<any> {
		return this.http.put(`${this.heroesUrl}/${hero.id}`, hero, httpOptions).pipe(
			tap(_ => this.log(`updated hero id=${hero.id}`)),
			catchError(this.handleError<any>('updateHero'))
		);
	}
    ~~~

18. Replace the **Post** method with the following **Create** method:
    ~~~ csharp
	// POST api/<controller>
	[HttpPost]
	public ActionResult<Hero> Create([FromBody]Hero item)
	{
		_context.Heroes.Add(item);
		_context.SaveChanges();

		return item;
	}
    ~~~
	
	If you test this by adding a new hero then you may receive an error
	<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-23.png"/>
	 	
	This is because the Add(item) call assigns the hero object an Id of 1. Maybe I missed something but I think there is a bug when adding seed data via the HasData approach. Here is how I got around it.
	</br></br>
	Create a method in the Startup class called **AddSeedData** and use the **HeroesContext** to add the data to the db:
    ~~~ csharp
	private void AddSeedData(HeroesContext context)
	{
		if (context.Heroes.Count() == 0)
		{
			// Create a new TodoItem if collection is empty,
			// which means you can't delete all TodoItems.
			context.Heroes.Add(new Hero { Name = "Super Kid" });
			context.Heroes.Add(new Hero { Name = "Mega Baby" });
			context.Heroes.Add(new Hero { Name = "Hyper Girl" });
			context.Heroes.Add(new Hero { Name = "Plastic boy" });
			context.Heroes.Add(new Hero { Name = "The Dark Kite" });
			context.Heroes.Add(new Hero { Name = "Blue Ray" });
			context.Heroes.Add(new Hero { Name = "Bob" });
			context.SaveChanges();
		}
	}
    ~~~
	In the **Configure** method remove or comment out the **context.Database.EnsureCreated();** and add a call to **AddSeedData** passing the context as a parameter:
    ~~~ csharp
	using (var serviceScope = app.ApplicationServices.CreateScope())
	{
		var context = serviceScope.ServiceProvider.GetService&lt;HeroesContext>();
		// This will force the data seeding
		//context.Database.EnsureCreated();
		AddSeedData(context);
	}
    ~~~
	Remove or comment out the **OnModelCreating** method in the **HeroesContext** Class.
	</br></br>
	Now if you add a new hero now then the object should be assigned an id that isn't already used. </br>
	<img src="http://charles.stuartedwards.me.uk/media/Blog Images/Post 3/3-24.png"/>

19. Replace the **Delete** method with:
    ~~~ csharp
	// DELETE api/<controller>/5
	[HttpDelete("{id}")]
	public IActionResult Delete(int id)
	{
		var hero = _context.Heroes.Find(id);
		if (hero == null)
		{
			return NotFound();
		}

		_context.Heroes.Remove(hero);
		_context.SaveChanges();
		return NoContent();
	}
    ~~~

20. Finally modify the **GetAll** method to include a basic search by name:
       
    ~~~ csharp
	// GET: api/&lt;controller>
	[HttpGet]
	public ActionResult<IEnumerable<Hero>> GetAll(string name)
	{
		if (name == null)
		{
			return _context.Heroes;
		}
		else
		{
		return _context.Heroes
			.Where(r => r.Name.ToLowerInvariant().Contains(name))
			.ToList();
		}
	}
    ~~~


**The end**

> Originally published on my personal blog: [Create an Angular 6 Site in .Net Core 2.1 from Scratch Part 2](http://charles.stuartedwards.me.uk/blog/create-an-angular-6-site-in-net-core-2-1-from-scratch-pt2)

#### Additional Resources:
- [Build web APIs with ASP.NET Core](https://docs.microsoft.com/en-us/aspnet/core/web-api/?view=aspnetcore-2.1)
- [Tutorial: Create a web API with ASP.NET Core MVC](https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api?view=aspnetcore-2.1)
- [Entity Framework Core 2.1: Data Seeding](https://elanderson.net/2018/09/entity-framework-core-2-1-data-seeding/)
- [https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding](https://docs.microsoft.com/en-us/ef/core/modeling/data-seeding)
- [Cannot resolve DbContext in ASP.NET Core 2.0](https://stackoverflow.com/questions/46063945/cannot-resolve-dbcontext-in-asp-net-core-2-0/46064116)
- [Tutorial: Using Entity Framework Core as an In-Memory Database for ASP.NET Core](https://stormpath.com/blog/tutorial-entity-framework-core-in-memory-database-asp-net-core)
- [Testing with InMemory](https://docs.microsoft.com/en-us/ef/core/miscellaneous/testing/in-memory)