Вооружившись информацией, полученной из прошлых тем, определим простейший проект, который будет реализовать CRUD интерфейс, применяя маршрутизацию. Для этого возьмем базовый проект:
Для обработки запросов будет использоваться контроллер ProductController из папки Controllers:
using System.Collections.Generic; using System.Linq; using Microsoft.AspNetCore.Mvc; using HelloAngularApp.Models; namespace HelloAngularApp.Controllers { [ApiController] [Route("api/products")] public class ProductController : Controller { ApplicationContext db; public ProductController(ApplicationContext context) { db = context; if (!db.Products.Any()) { db.Products.Add(new Product { Name = "iPhone X", Company = "Apple", Price = 79900 }); db.Products.Add(new Product { Name = "Galaxy S8", Company = "Samsung", Price = 49900 }); db.Products.Add(new Product { Name = "Pixel 2", Company = "Google", Price = 52900 }); db.SaveChanges(); } } [HttpGet] public IEnumerable<Product> Get() { return db.Products.ToList(); } [HttpGet("{id}")] public Product Get(int id) { Product product = db.Products.FirstOrDefault(x => x.Id == id); return product; } [HttpPost] public IActionResult Post(Product product) { if (ModelState.IsValid) { db.Products.Add(product); db.SaveChanges(); return Ok(product); } return BadRequest(ModelState); } [HttpPut] public IActionResult Put(Product product) { if (ModelState.IsValid) { db.Update(product); db.SaveChanges(); return Ok(product); } return BadRequest(ModelState); } [HttpDelete("{id}")] public IActionResult Delete(int id) { Product product = db.Products.FirstOrDefault(x => x.Id == id); if (product != null) { db.Products.Remove(product); db.SaveChanges(); } return Ok(product); } } }
В качестве модели данных этот контроллер использует класс Product:
public class Product { public int Id { get; set; } public string Name { get; set; } public string Company { get; set; } public decimal Price { get; set; } }
А для взаимодействия контроллер использует контекст данных ApplicationContext:
using Microsoft.EntityFrameworkCore; namespace HelloAngularApp.Models { public class ApplicationContext : DbContext { public ApplicationContext(DbContextOptions<ApplicationContext> options) : base(options) { Database.EnsureCreated(); } public DbSet<Product> Products { get; set; } } }
В классе Startup для работы с приложением Angular применяются SpaServices:
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.AspNetCore.SpaServices.AngularCli; using Microsoft.EntityFrameworkCore; using HelloAngularApp.Models; namespace HelloAngularApp { public class Startup { public void ConfigureServices(IServiceCollection services) { string connectionString = "Server=(localdb)\\mssqllocaldb;Database=productsdb;Trusted_Connection=True;"; services.AddDbContext<ApplicationContext>(options => options.UseSqlServer(connectionString)); services.AddControllers(); services.AddSpaStaticFiles(configuration => { configuration.RootPath = "ClientApp/dist"; }); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } app.UseStaticFiles(); if (!env.IsDevelopment()) { app.UseSpaStaticFiles(); } app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); app.UseSpa(spa => { spa.Options.SourcePath = "ClientApp"; if (env.IsDevelopment()) { spa.UseAngularCliServer(npmScript: "start"); } }); } } }
Для загрузки приложения Angular будет использоваться статический файл index.html из папки ClientApp/src:
<!DOCTYPE html> <html> <head> <meta charset="utf-8" /> <base href="/" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Angular in ASP.NET Core</title> <link rel="stylesheet" href="https://ajax.aspnetcdn.com/ajax/bootstrap/3.3.7/css/bootstrap.min.css" /> </head> <body> <app>Загрузка...</app> </body> </html>
В папке ClientApp/app в файле product.ts определен класс, представляющий модель данных:
export class Product { constructor( public id?: number, public name?: string, public company?: string, public price?: number) { } }
В файле data.service.ts определен сервис для взаимодействия с сервером:
import { Injectable } from '@angular/core'; import { HttpClient} from '@angular/common/http'; import { Product } from './product'; @Injectable() export class DataService { private url = "/api/products"; constructor(private http: HttpClient) { } getProducts() { return this.http.get(this.url); } getProduct(id: number) { return this.http.get(this.url + '/' + id); } createProduct(product: Product) { return this.http.post(this.url, product); } updateProduct(product: Product) { return this.http.put(this.url, product); } deleteProduct(id: number) { return this.http.delete(this.url + '/' + id); } }
В файле app.component.ts определен главный компонент приложения:
import { Component} from '@angular/core'; @Component({ selector: 'app', templateUrl: './app.component.html' }) export class AppComponent { }
А в файле app.component.html определено представление этого компонента:
<div class="container body-content"> <router-outlet></router-outlet> </div>
Содержимое файла app.module.ts пока не имеет значения, поскольку в дальнейшем мы его все равно изменим. Теперь перейдем к добавлению компонентов, которые будут выполнять отдельные функции интерфейса CRUD.