logger)
18 | {
19 | _logger = logger;
20 | }
21 |
22 | public string RequestId { get; set; }
23 |
24 | public bool ShowRequestId => !string.IsNullOrEmpty(RequestId);
25 |
26 | public void OnGet()
27 | {
28 | RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier;
29 | }
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/Demo.Web/Pages/Error.cshtml:
--------------------------------------------------------------------------------
1 | @page
2 | @model ErrorModel
3 | @{
4 | ViewData["Title"] = "Error";
5 | }
6 |
7 | Error.
8 | An error occurred while processing your request.
9 |
10 | @if (Model.ShowRequestId)
11 | {
12 |
13 | Request ID: @Model.RequestId
14 |
15 | }
16 |
17 | Development Mode
18 |
19 | Swapping to the Development environment displays detailed information about the error that occurred.
20 |
21 |
22 | The Development environment shouldn't be enabled for deployed applications.
23 | It can result in displaying sensitive information from exceptions to end users.
24 | For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development
25 | and restarting the app.
26 |
27 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-create/terms-create.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, OnDestroy } from '@angular/core';
2 | import { TermsService } from '../terms.service';
3 | import { Subscription } from 'rxjs';
4 | import { Router } from '@angular/router';
5 |
6 | @Component({
7 | selector: 'app-terms-create',
8 | templateUrl: './terms-create.component.html',
9 | styles: []
10 | })
11 | export class TermsCreateComponent implements OnInit, OnDestroy {
12 |
13 | subscription = new Subscription();
14 | constructor(
15 | private termService: TermsService,
16 | private router: Router) {
17 | }
18 |
19 | ngOnInit() {
20 | }
21 |
22 | save(form) {
23 | this.subscription.add(this.termService.create(form)
24 | .subscribe(result => {
25 | if (result.success) {
26 | this.router.navigate(['/terms']);
27 | }
28 | }));
29 | }
30 |
31 | ngOnDestroy() {
32 | this.subscription.unsubscribe();
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/InfrastructureStartup.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using Demo.ApplicationCore.Interfaces.Services;
3 | using Demo.Infrastructure.Data;
4 | using Demo.Infrastructure.Services;
5 | using Microsoft.EntityFrameworkCore;
6 | using Microsoft.Extensions.DependencyInjection;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Text;
10 |
11 | namespace Demo.Infrastructure
12 | {
13 | public static class InfrastructureStartup
14 | {
15 | public static IServiceCollection AddInfrastructure(this IServiceCollection services, Action options)
16 | {
17 | //Register DbContext
18 | services.AddDbContext(options);
19 |
20 | //Register AutoMapper
21 | services.AddAutoMapper(typeof(AutoMapperProfiles) /* You can add more Assembly profiles*/);
22 |
23 | //Register Application Services
24 | services.AddTransient();
25 |
26 | return services;
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms.service.ts:
--------------------------------------------------------------------------------
1 | import { Injectable, Inject } from '@angular/core';
2 | import { HttpClient } from '@angular/common/http';
3 | import { API_URLS, IApiUrls } from '..';
4 | import { Observable } from 'rxjs';
5 |
6 | @Injectable({
7 | providedIn: 'root'
8 | })
9 | export class TermsService {
10 | private baseUrl: string;
11 | constructor(
12 | private http: HttpClient,
13 | @Inject(API_URLS) urls: IApiUrls) {
14 | this.baseUrl = urls.terms;
15 | }
16 |
17 | getAll(page = 0): Observable {
18 | return this.http.get(this.baseUrl, {
19 | params: {
20 | 'currentPage': page + ''
21 | }
22 | });
23 | }
24 |
25 | find(id): Observable {
26 | return this.http.get(this.baseUrl + id);
27 | }
28 |
29 | create(term): Observable {
30 | return this.http.post(this.baseUrl, term);
31 | }
32 |
33 | update(id, term): Observable {
34 | return this.http.put(this.baseUrl + id, term);
35 | }
36 |
37 | delete(id): Observable {
38 | return this.http.delete(this.baseUrl + id);
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, '../coverage'),
20 | reports: ['html', 'lcovonly'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false
30 | });
31 | };
32 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/Migrations/20191129012640_InitialCreate.cs:
--------------------------------------------------------------------------------
1 | using Microsoft.EntityFrameworkCore.Migrations;
2 |
3 | namespace Demo.Infrastructure.Migrations
4 | {
5 | public partial class InitialCreate : Migration
6 | {
7 | protected override void Up(MigrationBuilder migrationBuilder)
8 | {
9 | migrationBuilder.CreateTable(
10 | name: "Terms",
11 | columns: table => new
12 | {
13 | Id = table.Column(nullable: false)
14 | .Annotation("SqlServer:Identity", "1, 1"),
15 | Name = table.Column(nullable: true),
16 | Description = table.Column(nullable: true)
17 | },
18 | constraints: table =>
19 | {
20 | table.PrimaryKey("PK_Terms", x => x.Id);
21 | });
22 | }
23 |
24 | protected override void Down(MigrationBuilder migrationBuilder)
25 | {
26 | migrationBuilder.DropTable(
27 | name: "Terms");
28 | }
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/README.md:
--------------------------------------------------------------------------------
1 | # Demo.Web
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 6.0.0.
4 |
5 | ## Development server
6 |
7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Code scaffolding
10 |
11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12 |
13 | ## Build
14 |
15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
16 |
17 | ## Running unit tests
18 |
19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20 |
21 | ## Running end-to-end tests
22 |
23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
28 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/Demo.Infrastructure.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 | all
13 | runtime; build; native; contentfiles; analyzers; buildtransitive
14 |
15 |
16 | all
17 | runtime; build; native; contentfiles; analyzers; buildtransitive
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-list/terms-list.component.html:
--------------------------------------------------------------------------------
1 | Terms List
2 |
3 |
4 |
5 | #
6 | Name
7 | Description
8 |
9 |
10 |
11 |
12 |
13 | {{i + 1 }}
14 | {{item.name}}
15 | {{item.description}}
16 |
17 |
18 | Edit
19 | |
20 |
21 | Delete
22 |
23 |
24 |
25 |
26 | 1 && pagesCount > currentPage">
27 |
28 |
29 |
30 |
31 | Load More
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/Demo.Web/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Linq;
4 | using System.Threading.Tasks;
5 | using Demo.Infrastructure.Data;
6 | using Microsoft.AspNetCore;
7 | using Microsoft.AspNetCore.Hosting;
8 | using Microsoft.EntityFrameworkCore;
9 | using Microsoft.Extensions.Configuration;
10 | using Microsoft.Extensions.DependencyInjection;
11 | using Microsoft.Extensions.Logging;
12 |
13 | namespace Demo.Web
14 | {
15 | public class Program
16 | {
17 | public async static Task Main(string[] args)
18 | {
19 | var host = CreateWebHostBuilder(args).Build();
20 |
21 | using (var scope = host.Services.CreateScope())
22 | {
23 | var provider = scope.ServiceProvider;
24 | var context = provider.GetRequiredService();
25 | await context.Database.MigrateAsync();
26 | }
27 |
28 | host.Run();
29 | }
30 |
31 | public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
32 | WebHost.CreateDefaultBuilder(args)
33 | .UseStartup();
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 | import { FormsModule } from '@angular/forms';
4 | import { HttpClientModule } from '@angular/common/http';
5 |
6 | import { AppComponent } from './app.component';
7 | import { NavMenuComponent } from './nav-menu/nav-menu.component';
8 | import { HomeComponent } from './home/home.component';
9 | import { AppRoutingModule } from './app-routing.module';
10 | import { httpInterceptors } from './http-interceptors';
11 | import { ToastrModule } from 'ngx-toastr';
12 | import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
13 |
14 | @NgModule({
15 | declarations: [
16 | AppComponent,
17 | NavMenuComponent,
18 | HomeComponent
19 | ],
20 | imports: [
21 | BrowserModule.withServerTransition({ appId: 'ng-cli-universal' }),
22 | HttpClientModule,
23 | FormsModule,
24 | AppRoutingModule,
25 | BrowserAnimationsModule,
26 | ToastrModule.forRoot({ positionClass: 'toast-bottom-right' })
27 | ],
28 | providers: [
29 | httpInterceptors
30 | ],
31 | bootstrap: [AppComponent]
32 | })
33 | export class AppModule { }
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/http-interceptors/toastr.interceptor.ts:
--------------------------------------------------------------------------------
1 | import { HttpInterceptor, HttpHandler, HttpRequest, HttpEvent, HttpResponse } from '@angular/common/http';
2 | import { Observable } from 'rxjs';
3 | import { ToastrService } from 'ngx-toastr';
4 | import { Injectable } from '@angular/core';
5 | import { tap } from 'rxjs/operators';
6 |
7 | @Injectable()
8 | export class ToastrInterceptor implements HttpInterceptor {
9 | constructor(private toastrService: ToastrService) { }
10 |
11 | intercept(req: HttpRequest, next: HttpHandler): Observable> {
12 | const method = req.method;
13 | return next.handle(req).pipe(
14 | tap(event => {
15 | if (method !== 'GET') {
16 | if (event instanceof HttpResponse) {
17 | if (event.body.success) {
18 | this.toastrService.success(event.body.message);
19 | } else {
20 | this.toastrService.error(event.body.message);
21 | }
22 | }
23 | }
24 | }, error => {
25 | this.toastrService.error('Error: please try again');
26 | }));
27 | }
28 | }
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/nav-menu/nav-menu.component.html:
--------------------------------------------------------------------------------
1 |
25 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-form/terms-form.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
2 | import { FormGroup, FormBuilder, Validators } from '@angular/forms';
3 | import { Term } from '..';
4 | import { LoaderService } from 'src/app/shared/services/loader.service';
5 |
6 | @Component({
7 | selector: 'app-terms-form',
8 | templateUrl: './terms-form.component.html',
9 | styles: []
10 | })
11 | export class TermsFormComponent implements OnInit {
12 |
13 | termForm: FormGroup;
14 | descMaxLength = 100;
15 | nameMaxLength = 25;
16 | @Input() model: Term;
17 | @Output() submitEvent = new EventEmitter();
18 | constructor(private fb: FormBuilder, private loaderService : LoaderService) { }
19 |
20 | ngOnInit() {
21 | if (!this.model) {
22 | this.model = new Term();
23 | }
24 | this.createTermForm();
25 | }
26 |
27 | createTermForm() {
28 | this.termForm = this.fb.group({
29 | name: [this.model.name, [Validators.required, Validators.maxLength(this.nameMaxLength)]],
30 | description: [this.model.description, [Validators.required, Validators.maxLength(this.descMaxLength)]],
31 | });
32 | }
33 |
34 | submit(form) {
35 | if (this.termForm.valid) {
36 | this.submitEvent.emit(form);
37 | }
38 | }
39 | get isLoading() {
40 | return this.loaderService.isLoading;
41 | }
42 | }
43 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/home/home.component.html:
--------------------------------------------------------------------------------
1 | Clean Architecture (ASP.NET Core with Angular)
2 |
3 |
4 |
5 |
6 |
7 | Clean Architecture Sample
8 |
9 | Clean Architecture Design
10 | ASP.NET Core 3.0
11 | Entity Framework Core
12 | CRUD Operations
13 | Dependency Injection
14 | AutoMapper
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 | Angular Sample
23 |
24 | Modular
25 | Dependency Injection
26 | Services
27 | Reactive Forms
28 | Validation
29 | @Input & @Output Decorators
30 | Http Client Requests
31 | Pagination
32 | OnInit & OnDestroy (Lifecycle Hooks)
33 | Rxjs Observables
34 | Subscription (Subscribe & Unsubscribe)
35 | Routing
36 | Lazy Loading Modules
37 | Http Interceptors
38 | Toastr
39 | Bootstrap 4
40 |
41 |
42 |
43 |
44 |
45 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-form/terms-form.component.html:
--------------------------------------------------------------------------------
1 |
31 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-edit/terms-edit.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, OnDestroy } from '@angular/core';
2 | import { Subscription } from 'rxjs';
3 | import { TermsService } from '../terms.service';
4 | import { Router, ActivatedRoute } from '@angular/router';
5 | import { Term } from '..';
6 |
7 | @Component({
8 | selector: 'app-terms-edit',
9 | templateUrl: './terms-edit.component.html',
10 | styles: []
11 | })
12 | export class TermsEditComponent implements OnInit, OnDestroy {
13 |
14 | subscription = new Subscription();
15 | selectedTerm: any;
16 | constructor(
17 | private termService: TermsService,
18 | private route: ActivatedRoute,
19 | private router: Router) {
20 | }
21 |
22 | ngOnInit() {
23 | const routeSub = this.route.paramMap.subscribe(p => {
24 | const id = p.get('id');
25 | const detailsSub = this.termService.find(id).subscribe(result => {
26 | if (result.success) {
27 | this.selectedTerm = result.data;
28 | }
29 | });
30 | this.subscription.add(detailsSub);
31 | });
32 | this.subscription.add(routeSub);
33 | }
34 |
35 | save(form) {
36 | this.subscription.add(this.termService.update(this.selectedTerm.id, form)
37 | .subscribe(result => {
38 | if (result.success) {
39 | this.router.navigate(['/terms']);
40 | }
41 | }));
42 | }
43 |
44 | ngOnDestroy() {
45 | this.subscription.unsubscribe();
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/Demo.ApplicationCore/DTOs/OperationResult.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Text;
4 |
5 | namespace Demo.ApplicationCore.DTOs
6 | {
7 | public class OperationResult
8 | {
9 | public OperationResult(bool success, string messag, dynamic payload)
10 | {
11 | this.Success = success;
12 | this.Message = messag;
13 | this.Payload = payload;
14 | }
15 | public bool Success { get; set; }
16 | public string Message { get; set; }
17 |
18 | public dynamic Payload { get; set; }
19 |
20 | public static OperationResult Succeeded(string msg = "Operation Completed Successfully!.", dynamic payload = null)
21 | {
22 | return new OperationResult(true, msg, payload);
23 | }
24 | public static OperationResult NotFound(string msg = "Item Not Found!.", dynamic payload = null)
25 | {
26 | return new OperationResult(false, msg, payload);
27 | }
28 | public static OperationResult Failed(string msg = "Operation Failed!.", dynamic payload = null)
29 | {
30 | return new OperationResult(false, msg, payload);
31 | }
32 |
33 | public static OperationResult Existed(string msg = "Item Already Exisited!.", dynamic payload = null)
34 | {
35 | return new OperationResult(false, msg, payload);
36 | }
37 |
38 | // Add More Results .......
39 |
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/Migrations/TermsContextModelSnapshot.cs:
--------------------------------------------------------------------------------
1 | //
2 | using Demo.Infrastructure.Data;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
7 |
8 | namespace Demo.Infrastructure.Migrations
9 | {
10 | [DbContext(typeof(TermsContext))]
11 | partial class TermsContextModelSnapshot : ModelSnapshot
12 | {
13 | protected override void BuildModel(ModelBuilder modelBuilder)
14 | {
15 | #pragma warning disable 612, 618
16 | modelBuilder
17 | .HasAnnotation("ProductVersion", "3.0.1")
18 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
19 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
20 |
21 | modelBuilder.Entity("Demo.ApplicationCore.Entities.Term", b =>
22 | {
23 | b.Property("Id")
24 | .ValueGeneratedOnAdd()
25 | .HasColumnType("int")
26 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
27 |
28 | b.Property("Description")
29 | .HasColumnType("nvarchar(max)");
30 |
31 | b.Property("Name")
32 | .HasColumnType("nvarchar(max)");
33 |
34 | b.HasKey("Id");
35 |
36 | b.ToTable("Terms");
37 | });
38 | #pragma warning restore 612, 618
39 | }
40 | }
41 | }
42 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/app/terms/terms-list/terms-list.component.ts:
--------------------------------------------------------------------------------
1 | import { Component, OnInit, OnDestroy } from '@angular/core';
2 | import { Subscription } from 'rxjs';
3 | import { TermsService } from '../terms.service';
4 |
5 | @Component({
6 | selector: 'app-terms-list',
7 | templateUrl: './terms-list.component.html',
8 | styles: []
9 | })
10 | export class TermsListComponent implements OnInit, OnDestroy {
11 |
12 | subscription = new Subscription();
13 | terms: any[];
14 | pagesCount: number;
15 | currentPage = 1;
16 | constructor(
17 | private termService: TermsService) {
18 | }
19 |
20 | ngOnInit() {
21 | this.subscription.add(this.termService.getAll()
22 | .subscribe(result => {
23 | if (result.success) {
24 | this.terms = result.data;
25 | this.pagesCount = result.pagesCount;
26 | }
27 | }));
28 | }
29 |
30 | loadMore() {
31 | if (this.currentPage <= this.pagesCount) {
32 | this.subscription.add(this.termService.getAll(this.currentPage)
33 | .subscribe(result => {
34 | if (result.success) {
35 | result.data.forEach(d => {
36 | this.terms.push(d);
37 | });
38 | this.currentPage = this.currentPage + 1;
39 | }
40 | }));
41 | }
42 | }
43 | deleteTerm(id) {
44 | const confirmed = confirm('are you sure?');
45 | if (confirmed) {
46 | this.subscription.add(this.termService.delete(id)
47 | .subscribe(result => {
48 | if (result.success) {
49 | this.terms = this.terms.filter(t => t.id !== id);
50 | }
51 | }));
52 | }
53 | }
54 | ngOnDestroy() {
55 | this.subscription.unsubscribe();
56 | }
57 | }
58 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/Migrations/20191129012640_InitialCreate.Designer.cs:
--------------------------------------------------------------------------------
1 | //
2 | using Demo.Infrastructure.Data;
3 | using Microsoft.EntityFrameworkCore;
4 | using Microsoft.EntityFrameworkCore.Infrastructure;
5 | using Microsoft.EntityFrameworkCore.Metadata;
6 | using Microsoft.EntityFrameworkCore.Migrations;
7 | using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
8 |
9 | namespace Demo.Infrastructure.Migrations
10 | {
11 | [DbContext(typeof(TermsContext))]
12 | [Migration("20191129012640_InitialCreate")]
13 | partial class InitialCreate
14 | {
15 | protected override void BuildTargetModel(ModelBuilder modelBuilder)
16 | {
17 | #pragma warning disable 612, 618
18 | modelBuilder
19 | .HasAnnotation("ProductVersion", "3.0.1")
20 | .HasAnnotation("Relational:MaxIdentifierLength", 128)
21 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
22 |
23 | modelBuilder.Entity("Demo.ApplicationCore.Entities.Term", b =>
24 | {
25 | b.Property("Id")
26 | .ValueGeneratedOnAdd()
27 | .HasColumnType("int")
28 | .HasAnnotation("SqlServer:ValueGenerationStrategy", SqlServerValueGenerationStrategy.IdentityColumn);
29 |
30 | b.Property("Description")
31 | .HasColumnType("nvarchar(max)");
32 |
33 | b.Property("Name")
34 | .HasColumnType("nvarchar(max)");
35 |
36 | b.HasKey("Id");
37 |
38 | b.ToTable("Terms");
39 | });
40 | #pragma warning restore 612, 618
41 | }
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "demo.web",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve",
7 | "build": "ng build",
8 | "build:ssr": "ng run Demo.Web:server:dev",
9 | "test": "ng test",
10 | "lint": "ng lint",
11 | "e2e": "ng e2e"
12 | },
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "8.2.14",
16 | "@angular/common": "8.2.14",
17 | "@angular/compiler": "8.2.14",
18 | "@angular/core": "8.2.14",
19 | "@angular/forms": "8.2.14",
20 | "@angular/platform-browser": "8.2.14",
21 | "@angular/platform-browser-dynamic": "8.2.14",
22 | "@angular/platform-server": "8.2.14",
23 | "@angular/router": "8.2.14",
24 | "@nguniversal/module-map-ngfactory-loader": "8.0.0-rc.1",
25 | "aspnet-prerendering": "^3.0.1",
26 | "bootstrap": "^4.4.1",
27 | "core-js": "^2.6.5",
28 | "jquery": "3.4.1",
29 | "ngx-toastr": "^11.2.1",
30 | "oidc-client": "^1.9.0",
31 | "popper.js": "^1.14.3",
32 | "rxjs": "^6.5.3",
33 | "zone.js": "~0.9.1"
34 | },
35 | "devDependencies": {
36 | "@angular-devkit/build-angular": "^0.803.20",
37 | "@angular/cli": "8.3.20",
38 | "@angular/compiler-cli": "8.2.14",
39 | "@angular/language-service": "8.2.14",
40 | "@types/jasmine": "~3.3.9",
41 | "@types/jasminewd2": "~2.0.6",
42 | "@types/node": "~11.10.5",
43 | "codelyzer": "^5.0.1",
44 | "jasmine-core": "~3.3.0",
45 | "jasmine-spec-reporter": "~4.2.1",
46 | "karma": "^4.0.0",
47 | "karma-chrome-launcher": "~2.2.0",
48 | "karma-coverage-istanbul-reporter": "~2.0.5",
49 | "karma-jasmine": "~2.0.1",
50 | "karma-jasmine-html-reporter": "^1.4.0",
51 | "typescript": "3.5.3"
52 | },
53 | "optionalDependencies": {
54 | "node-sass": "^4.9.3",
55 | "protractor": "~5.4.0",
56 | "ts-node": "~5.0.1",
57 | "tslint": "~5.9.1"
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/CleanArchitecture.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | # Visual Studio Version 16
4 | VisualStudioVersion = 16.0.29409.12
5 | MinimumVisualStudioVersion = 10.0.40219.1
6 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo.ApplicationCore", "Demo.ApplicationCore\Demo.ApplicationCore.csproj", "{58900E20-38C5-4545-BFDA-EA09BE55DC27}"
7 | EndProject
8 | Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Demo.Infrastructure", "Demo.Infrastructure\Demo.Infrastructure.csproj", "{A56D9130-C21A-4494-ADF6-FD4A77ADB8B9}"
9 | EndProject
10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Demo.Web", "Demo.Web\Demo.Web.csproj", "{C5435655-4B32-4DB3-8010-6B768AA87CD4}"
11 | EndProject
12 | Global
13 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
14 | Debug|Any CPU = Debug|Any CPU
15 | Release|Any CPU = Release|Any CPU
16 | EndGlobalSection
17 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
18 | {58900E20-38C5-4545-BFDA-EA09BE55DC27}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
19 | {58900E20-38C5-4545-BFDA-EA09BE55DC27}.Debug|Any CPU.Build.0 = Debug|Any CPU
20 | {58900E20-38C5-4545-BFDA-EA09BE55DC27}.Release|Any CPU.ActiveCfg = Release|Any CPU
21 | {58900E20-38C5-4545-BFDA-EA09BE55DC27}.Release|Any CPU.Build.0 = Release|Any CPU
22 | {A56D9130-C21A-4494-ADF6-FD4A77ADB8B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
23 | {A56D9130-C21A-4494-ADF6-FD4A77ADB8B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
24 | {A56D9130-C21A-4494-ADF6-FD4A77ADB8B9}.Release|Any CPU.ActiveCfg = Release|Any CPU
25 | {A56D9130-C21A-4494-ADF6-FD4A77ADB8B9}.Release|Any CPU.Build.0 = Release|Any CPU
26 | {C5435655-4B32-4DB3-8010-6B768AA87CD4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
27 | {C5435655-4B32-4DB3-8010-6B768AA87CD4}.Debug|Any CPU.Build.0 = Debug|Any CPU
28 | {C5435655-4B32-4DB3-8010-6B768AA87CD4}.Release|Any CPU.ActiveCfg = Release|Any CPU
29 | {C5435655-4B32-4DB3-8010-6B768AA87CD4}.Release|Any CPU.Build.0 = Release|Any CPU
30 | EndGlobalSection
31 | GlobalSection(SolutionProperties) = preSolution
32 | HideSolutionNode = FALSE
33 | EndGlobalSection
34 | GlobalSection(ExtensibilityGlobals) = postSolution
35 | SolutionGuid = {BCE28F32-77DF-4A96-B849-D1D00FD18400}
36 | EndGlobalSection
37 | EndGlobal
38 |
--------------------------------------------------------------------------------
/Demo.Infrastructure/Services/TermsService.cs:
--------------------------------------------------------------------------------
1 | using AutoMapper;
2 | using AutoMapper.QueryableExtensions;
3 | using Demo.ApplicationCore.DTOs;
4 | using Demo.ApplicationCore.Interfaces.Services;
5 | using Demo.Infrastructure.Data;
6 | using Microsoft.EntityFrameworkCore;
7 | using System;
8 | using System.Collections.Generic;
9 | using System.Linq;
10 | using System.Text;
11 | using System.Threading.Tasks;
12 | using Entities = Demo.ApplicationCore.Entities;
13 | namespace Demo.Infrastructure.Services
14 | {
15 | public class TermsService : ITermsService
16 | {
17 | private readonly TermsContext _context;
18 | private IMapper _mapper;
19 | public TermsService(TermsContext context, IMapper mapper)
20 | {
21 | _context = context;
22 | _mapper = mapper;
23 | }
24 | public async Task CreateAsync(InputTerm entityToCreate)
25 | {
26 | var newTerm = _mapper.Map(entityToCreate);
27 | await _context.Terms.AddAsync(newTerm);
28 | await _context.SaveChangesAsync();
29 | return OperationResult.Succeeded();
30 | }
31 |
32 | public async Task DeleteAsync(int key)
33 | {
34 | var selectedTerm = await _context.Terms.FindAsync(key);
35 | if (selectedTerm != null)
36 | {
37 | _context.Terms.Remove(selectedTerm);
38 | await _context.SaveChangesAsync();
39 | return OperationResult.Succeeded();
40 | }
41 | return OperationResult.NotFound();
42 | }
43 |
44 | public async Task FindAsync(int key)
45 | {
46 | var selectedTerm = await _context.Terms.FindAsync(key);
47 | return selectedTerm != null ? _mapper.Map(selectedTerm) : null;
48 | }
49 |
50 | public IQueryable GetAll()
51 | {
52 | var result = _context.Terms
53 | .OrderByDescending(t => t.Id)
54 | .ProjectTo(_mapper.ConfigurationProvider);
55 | return result;
56 | }
57 |
58 | public async Task UpdateAsync(int key, InputTerm entityToUpdate)
59 | {
60 | var selectedTerm = await _context.Terms.FindAsync(key);
61 | if (selectedTerm != null)
62 | {
63 | var updatedTerm = _mapper.Map(entityToUpdate);
64 | updatedTerm.Id = key;
65 | _context.Entry(updatedTerm).State = EntityState.Modified;
66 | await _context.SaveChangesAsync();
67 | return OperationResult.Succeeded();
68 | }
69 | return OperationResult.NotFound();
70 |
71 | }
72 | }
73 | }
74 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags.ts';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/Demo.Web/Startup.cs:
--------------------------------------------------------------------------------
1 | using Demo.Infrastructure;
2 | using Microsoft.AspNetCore.Builder;
3 | using Microsoft.AspNetCore.Hosting;
4 | using Microsoft.AspNetCore.HttpsPolicy;
5 | using Microsoft.AspNetCore.SpaServices.AngularCli;
6 | using Microsoft.EntityFrameworkCore;
7 | using Microsoft.Extensions.Configuration;
8 | using Microsoft.Extensions.DependencyInjection;
9 | using Microsoft.Extensions.Hosting;
10 |
11 | namespace Demo.Web
12 | {
13 | public class Startup
14 | {
15 | public Startup(IConfiguration configuration)
16 | {
17 | Configuration = configuration;
18 | }
19 |
20 | public IConfiguration Configuration { get; }
21 |
22 | // This method gets called by the runtime. Use this method to add services to the container.
23 | public void ConfigureServices(IServiceCollection services)
24 | {
25 |
26 | //Add Infrastructure Configuration
27 | services.AddInfrastructure(options =>
28 | {
29 | options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
30 | });
31 |
32 | services.AddControllersWithViews();
33 | // In production, the Angular files will be served from this directory
34 | services.AddSpaStaticFiles(configuration =>
35 | {
36 | configuration.RootPath = "ClientApp/dist";
37 | });
38 | }
39 |
40 | // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
41 | public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
42 | {
43 | if (env.IsDevelopment())
44 | {
45 | app.UseDeveloperExceptionPage();
46 | }
47 | else
48 | {
49 | app.UseExceptionHandler("/Error");
50 | // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
51 | app.UseHsts();
52 | }
53 |
54 | app.UseHttpsRedirection();
55 | app.UseStaticFiles();
56 | if (!env.IsDevelopment())
57 | {
58 | app.UseSpaStaticFiles();
59 | }
60 |
61 | app.UseRouting();
62 |
63 | app.UseEndpoints(endpoints =>
64 | {
65 | endpoints.MapControllerRoute(
66 | name: "default",
67 | pattern: "{controller}/{action=Index}/{id?}");
68 | });
69 |
70 | app.UseSpa(spa =>
71 | {
72 | // To learn more about options for serving an Angular SPA from ASP.NET Core,
73 | // see https://go.microsoft.com/fwlink/?linkid=864501
74 |
75 | spa.Options.SourcePath = "ClientApp";
76 | spa.Options.StartupTimeout = new System.TimeSpan(0, 0, 300000);
77 | if (env.IsDevelopment())
78 | {
79 | spa.UseAngularCliServer(npmScript: "start");
80 | }
81 | });
82 | }
83 | }
84 | }
85 |
--------------------------------------------------------------------------------
/Demo.Web/Controllers/TermsController.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 | using System.Dynamic;
4 | using System.Linq;
5 | using System.Threading.Tasks;
6 | using Demo.ApplicationCore.DTOs;
7 | using Demo.ApplicationCore.Interfaces.Services;
8 | using Microsoft.AspNetCore.Http;
9 | using Microsoft.AspNetCore.Mvc;
10 | using Microsoft.EntityFrameworkCore;
11 |
12 | namespace Demo.Web.Controllers
13 | {
14 | [Route("api/[controller]")]
15 | [ApiController]
16 | public class TermsController : ControllerBase
17 | {
18 | private readonly ITermsService _termsService;
19 | public TermsController(ITermsService termsService)
20 | {
21 | _termsService = termsService;
22 | }
23 | // GET: api/Terms
24 | [HttpGet]
25 | public async Task Get(int currentPage = 0)
26 | {
27 | var result = _termsService.GetAll();
28 | return await GetPagedData(result, currentPage);
29 | }
30 |
31 | private async Task GetPagedData(IQueryable data, int currentPage = 0)
32 | {
33 | var pageSize = 5;
34 | currentPage = currentPage >= 0 ? currentPage : 0;
35 | var startIndex = pageSize * currentPage;
36 | var pagedData = await data
37 | .Skip(startIndex)
38 | .Take(pageSize)
39 | .ToListAsync();
40 |
41 | if (currentPage <= 1)
42 | {
43 | var pagesCount = Math.Ceiling(Convert.ToDecimal(data.Count()) / Convert.ToDecimal(pageSize));
44 | return Ok(new { Success = true, Data = pagedData, pagesCount });
45 | }
46 | return Ok(new { Success = true, Data = pagedData });
47 | }
48 |
49 | // GET: api/Terms/5
50 | [HttpGet("{id}")]
51 | public async Task GetBy(int id)
52 | {
53 | var selectedTerm = await _termsService.FindAsync(id);
54 | return Ok(new { success = true, data = selectedTerm });
55 | }
56 |
57 | // POST: api/Terms
58 | [HttpPost]
59 | public async Task Post(InputTerm value)
60 | {
61 | if (ModelState.IsValid)
62 | {
63 | var result = await _termsService.CreateAsync(value);
64 | return Ok(result);
65 | }
66 | return Ok(new { Success = false, Message = getErrorMessages() });
67 | }
68 |
69 | private string getErrorMessages()
70 | {
71 | var msg = string.Join(',', ModelState.Values.SelectMany(v => v.Errors.Select(e => e.ErrorMessage)));
72 | return msg;
73 | }
74 |
75 | // PUT: api/Terms/5
76 | [HttpPut("{id}")]
77 | public async Task Put(int id, InputTerm value)
78 | {
79 | if (ModelState.IsValid)
80 | {
81 | var result = await _termsService.UpdateAsync(id, value);
82 | return Ok(result);
83 | }
84 | return Ok(new { Success = false, Message = getErrorMessages() });
85 | }
86 |
87 | // DELETE: api/Terms/5
88 | [HttpDelete("{id}")]
89 | public async Task Delete(int id)
90 | {
91 | var result = await _termsService.DeleteAsync(id);
92 | return Ok(result);
93 | }
94 | }
95 | }
96 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "rulesDirectory": [
3 | "node_modules/codelyzer"
4 | ],
5 | "rules": {
6 | "arrow-return-shorthand": true,
7 | "callable-types": true,
8 | "class-name": true,
9 | "comment-format": [
10 | true,
11 | "check-space"
12 | ],
13 | "curly": true,
14 | "deprecation": {
15 | "severity": "warn"
16 | },
17 | "eofline": true,
18 | "forin": true,
19 | "import-blacklist": [
20 | true,
21 | "rxjs/Rx"
22 | ],
23 | "import-spacing": true,
24 | "indent": [
25 | true,
26 | "spaces"
27 | ],
28 | "interface-over-type-literal": true,
29 | "label-position": true,
30 | "max-line-length": [
31 | true,
32 | 140
33 | ],
34 | "member-access": false,
35 | "member-ordering": [
36 | true,
37 | {
38 | "order": [
39 | "static-field",
40 | "instance-field",
41 | "static-method",
42 | "instance-method"
43 | ]
44 | }
45 | ],
46 | "no-arg": true,
47 | "no-bitwise": true,
48 | "no-console": [
49 | true,
50 | "debug",
51 | "info",
52 | "time",
53 | "timeEnd",
54 | "trace"
55 | ],
56 | "no-construct": true,
57 | "no-debugger": true,
58 | "no-duplicate-super": true,
59 | "no-empty": false,
60 | "no-empty-interface": true,
61 | "no-eval": true,
62 | "no-inferrable-types": [
63 | true,
64 | "ignore-params"
65 | ],
66 | "no-misused-new": true,
67 | "no-non-null-assertion": true,
68 | "no-shadowed-variable": true,
69 | "no-string-literal": false,
70 | "no-string-throw": true,
71 | "no-switch-case-fall-through": true,
72 | "no-trailing-whitespace": true,
73 | "no-unnecessary-initializer": true,
74 | "no-unused-expression": true,
75 | "no-use-before-declare": true,
76 | "no-var-keyword": true,
77 | "object-literal-sort-keys": false,
78 | "one-line": [
79 | true,
80 | "check-open-brace",
81 | "check-catch",
82 | "check-else",
83 | "check-whitespace"
84 | ],
85 | "prefer-const": true,
86 | "quotemark": [
87 | true,
88 | "single"
89 | ],
90 | "radix": true,
91 | "semicolon": [
92 | true,
93 | "always"
94 | ],
95 | "triple-equals": [
96 | true,
97 | "allow-null-check"
98 | ],
99 | "typedef-whitespace": [
100 | true,
101 | {
102 | "call-signature": "nospace",
103 | "index-signature": "nospace",
104 | "parameter": "nospace",
105 | "property-declaration": "nospace",
106 | "variable-declaration": "nospace"
107 | }
108 | ],
109 | "unified-signatures": true,
110 | "variable-name": false,
111 | "whitespace": [
112 | true,
113 | "check-branch",
114 | "check-decl",
115 | "check-operator",
116 | "check-separator",
117 | "check-type"
118 | ],
119 | "no-output-on-prefix": true,
120 | "no-inputs-metadata-property": true,
121 | "no-outputs-metadata-property": true,
122 | "no-host-metadata-property": true,
123 | "no-input-rename": true,
124 | "no-output-rename": true,
125 | "use-lifecycle-interface": true,
126 | "use-pipe-transform-interface": true,
127 | "component-class-suffix": true,
128 | "directive-class-suffix": true
129 | }
130 | }
131 |
--------------------------------------------------------------------------------
/Demo.Web/Demo.Web.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netcoreapp3.0
5 | true
6 | Latest
7 | false
8 | ClientApp\
9 | $(DefaultItemExcludes);$(SpaRoot)node_modules\**
10 |
11 |
12 | false
13 |
14 |
15 |
16 |
17 |
18 | all
19 | runtime; build; native; contentfiles; analyzers; buildtransitive
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 | %(DistFiles.Identity)
59 | PreserveNewest
60 | true
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/Demo.Web/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 |
4 | # User-specific files
5 | *.suo
6 | *.user
7 | *.userosscache
8 | *.sln.docstates
9 |
10 | # User-specific files (MonoDevelop/Xamarin Studio)
11 | *.userprefs
12 |
13 | # Build results
14 | [Dd]ebug/
15 | [Dd]ebugPublic/
16 | [Rr]elease/
17 | [Rr]eleases/
18 | x64/
19 | x86/
20 | build/
21 | bld/
22 | bin/
23 | Bin/
24 | obj/
25 | Obj/
26 |
27 | # Visual Studio 2015 cache/options directory
28 | .vs/
29 |
30 | # MSTest test Results
31 | [Tt]est[Rr]esult*/
32 | [Bb]uild[Ll]og.*
33 |
34 | # NUNIT
35 | *.VisualState.xml
36 | TestResult.xml
37 |
38 | # Build Results of an ATL Project
39 | [Dd]ebugPS/
40 | [Rr]eleasePS/
41 | dlldata.c
42 |
43 | *_i.c
44 | *_p.c
45 | *_i.h
46 | *.ilk
47 | *.meta
48 | *.obj
49 | *.pch
50 | *.pdb
51 | *.pgc
52 | *.pgd
53 | *.rsp
54 | *.sbr
55 | *.tlb
56 | *.tli
57 | *.tlh
58 | *.tmp
59 | *.tmp_proj
60 | *.log
61 | *.vspscc
62 | *.vssscc
63 | .builds
64 | *.pidb
65 | *.svclog
66 | *.scc
67 |
68 | # Chutzpah Test files
69 | _Chutzpah*
70 |
71 | # Visual C++ cache files
72 | ipch/
73 | *.aps
74 | *.ncb
75 | *.opendb
76 | *.opensdf
77 | *.sdf
78 | *.cachefile
79 |
80 | # Visual Studio profiler
81 | *.psess
82 | *.vsp
83 | *.vspx
84 | *.sap
85 |
86 | # TFS 2012 Local Workspace
87 | $tf/
88 |
89 | # Guidance Automation Toolkit
90 | *.gpState
91 |
92 | # ReSharper is a .NET coding add-in
93 | _ReSharper*/
94 | *.[Rr]e[Ss]harper
95 | *.DotSettings.user
96 |
97 | # JustCode is a .NET coding add-in
98 | .JustCode
99 |
100 | # TeamCity is a build add-in
101 | _TeamCity*
102 |
103 | # DotCover is a Code Coverage Tool
104 | *.dotCover
105 |
106 | # NCrunch
107 | _NCrunch_*
108 | .*crunch*.local.xml
109 | nCrunchTemp_*
110 |
111 | # MightyMoose
112 | *.mm.*
113 | AutoTest.Net/
114 |
115 | # Web workbench (sass)
116 | .sass-cache/
117 |
118 | # Installshield output folder
119 | [Ee]xpress/
120 |
121 | # DocProject is a documentation generator add-in
122 | DocProject/buildhelp/
123 | DocProject/Help/*.HxT
124 | DocProject/Help/*.HxC
125 | DocProject/Help/*.hhc
126 | DocProject/Help/*.hhk
127 | DocProject/Help/*.hhp
128 | DocProject/Help/Html2
129 | DocProject/Help/html
130 |
131 | # Click-Once directory
132 | publish/
133 |
134 | # Publish Web Output
135 | *.[Pp]ublish.xml
136 | *.azurePubxml
137 | # TODO: Comment the next line if you want to checkin your web deploy settings
138 | # but database connection strings (with potential passwords) will be unencrypted
139 | *.pubxml
140 | *.publishproj
141 |
142 | # NuGet Packages
143 | *.nupkg
144 | # The packages folder can be ignored because of Package Restore
145 | **/packages/*
146 | # except build/, which is used as an MSBuild target.
147 | !**/packages/build/
148 | # Uncomment if necessary however generally it will be regenerated when needed
149 | #!**/packages/repositories.config
150 |
151 | # Microsoft Azure Build Output
152 | csx/
153 | *.build.csdef
154 |
155 | # Microsoft Azure Emulator
156 | ecf/
157 | rcf/
158 |
159 | # Microsoft Azure ApplicationInsights config file
160 | ApplicationInsights.config
161 |
162 | # Windows Store app package directory
163 | AppPackages/
164 | BundleArtifacts/
165 |
166 | # Visual Studio cache files
167 | # files ending in .cache can be ignored
168 | *.[Cc]ache
169 | # but keep track of directories ending in .cache
170 | !*.[Cc]ache/
171 |
172 | # Others
173 | ClientBin/
174 | ~$*
175 | *~
176 | *.dbmdl
177 | *.dbproj.schemaview
178 | *.pfx
179 | *.publishsettings
180 | orleans.codegen.cs
181 |
182 | /node_modules
183 |
184 | # RIA/Silverlight projects
185 | Generated_Code/
186 |
187 | # Backup & report files from converting an old project file
188 | # to a newer Visual Studio version. Backup files are not needed,
189 | # because we have git ;-)
190 | _UpgradeReport_Files/
191 | Backup*/
192 | UpgradeLog*.XML
193 | UpgradeLog*.htm
194 |
195 | # SQL Server files
196 | *.mdf
197 | *.ldf
198 |
199 | # Business Intelligence projects
200 | *.rdl.data
201 | *.bim.layout
202 | *.bim_*.settings
203 |
204 | # Microsoft Fakes
205 | FakesAssemblies/
206 |
207 | # GhostDoc plugin setting file
208 | *.GhostDoc.xml
209 |
210 | # Node.js Tools for Visual Studio
211 | .ntvs_analysis.dat
212 |
213 | # Visual Studio 6 build log
214 | *.plg
215 |
216 | # Visual Studio 6 workspace options file
217 | *.opt
218 |
219 | # Visual Studio LightSwitch build output
220 | **/*.HTMLClient/GeneratedArtifacts
221 | **/*.DesktopClient/GeneratedArtifacts
222 | **/*.DesktopClient/ModelManifest.xml
223 | **/*.Server/GeneratedArtifacts
224 | **/*.Server/ModelManifest.xml
225 | _Pvt_Extensions
226 |
227 | # Paket dependency manager
228 | .paket/paket.exe
229 |
230 | # FAKE - F# Make
231 | .fake/
232 |
--------------------------------------------------------------------------------
/Demo.Web/ClientApp/angular.json:
--------------------------------------------------------------------------------
1 | {
2 | "$schema": "./node_modules/@angular/cli/lib/config/schema.json",
3 | "version": 1,
4 | "newProjectRoot": "projects",
5 | "projects": {
6 | "Demo.Web": {
7 | "root": "",
8 | "sourceRoot": "src",
9 | "projectType": "application",
10 | "prefix": "app",
11 | "schematics": {},
12 | "architect": {
13 | "build": {
14 | "builder": "@angular-devkit/build-angular:browser",
15 | "options": {
16 | "progress": true,
17 | "extractCss": true,
18 | "outputPath": "dist",
19 | "index": "src/index.html",
20 | "main": "src/main.ts",
21 | "polyfills": "src/polyfills.ts",
22 | "tsConfig": "src/tsconfig.app.json",
23 | "assets": ["src/assets"],
24 | "styles": [
25 | "node_modules/bootstrap/dist/css/bootstrap.min.css",
26 | "node_modules/ngx-toastr/toastr.css",
27 | "src/styles.css"
28 | ],
29 | "scripts": [
30 | ]
31 | },
32 | "configurations": {
33 | "production": {
34 | "fileReplacements": [
35 | {
36 | "replace": "src/environments/environment.ts",
37 | "with": "src/environments/environment.prod.ts"
38 | }
39 | ],
40 | "optimization": true,
41 | "outputHashing": "all",
42 | "sourceMap": false,
43 | "extractCss": true,
44 | "namedChunks": false,
45 | "aot": true,
46 | "extractLicenses": true,
47 | "vendorChunk": false,
48 | "buildOptimizer": true
49 | }
50 | }
51 | },
52 | "serve": {
53 | "builder": "@angular-devkit/build-angular:dev-server",
54 | "options": {
55 | "browserTarget": "Demo.Web:build"
56 | },
57 | "configurations": {
58 | "production": {
59 | "browserTarget": "Demo.Web:build:production"
60 | }
61 | }
62 | },
63 | "extract-i18n": {
64 | "builder": "@angular-devkit/build-angular:extract-i18n",
65 | "options": {
66 | "browserTarget": "Demo.Web:build"
67 | }
68 | },
69 | "test": {
70 | "builder": "@angular-devkit/build-angular:karma",
71 | "options": {
72 | "main": "src/test.ts",
73 | "polyfills": "src/polyfills.ts",
74 | "tsConfig": "src/tsconfig.spec.json",
75 | "karmaConfig": "src/karma.conf.js",
76 | "styles": ["styles.css"],
77 | "scripts": [],
78 | "assets": ["src/assets"]
79 | }
80 | },
81 | "lint": {
82 | "builder": "@angular-devkit/build-angular:tslint",
83 | "options": {
84 | "tsConfig": ["src/tsconfig.app.json", "src/tsconfig.spec.json"],
85 | "exclude": ["**/node_modules/**"]
86 | }
87 | },
88 | "server": {
89 | "builder": "@angular-devkit/build-angular:server",
90 | "options": {
91 | "outputPath": "dist-server",
92 | "main": "src/main.ts",
93 | "tsConfig": "src/tsconfig.server.json"
94 | },
95 | "configurations": {
96 | "dev": {
97 | "optimization": true,
98 | "outputHashing": "all",
99 | "sourceMap": false,
100 | "namedChunks": false,
101 | "extractLicenses": true,
102 | "vendorChunk": true
103 | },
104 | "production": {
105 | "optimization": true,
106 | "outputHashing": "all",
107 | "sourceMap": false,
108 | "namedChunks": false,
109 | "extractLicenses": true,
110 | "vendorChunk": false
111 | }
112 | }
113 | }
114 | }
115 | },
116 | "Demo.Web-e2e": {
117 | "root": "e2e/",
118 | "projectType": "application",
119 | "architect": {
120 | "e2e": {
121 | "builder": "@angular-devkit/build-angular:protractor",
122 | "options": {
123 | "protractorConfig": "e2e/protractor.conf.js",
124 | "devServerTarget": "Demo.Web:serve"
125 | }
126 | },
127 | "lint": {
128 | "builder": "@angular-devkit/build-angular:tslint",
129 | "options": {
130 | "tsConfig": "e2e/tsconfig.e2e.json",
131 | "exclude": ["**/node_modules/**"]
132 | }
133 | }
134 | }
135 | }
136 | },
137 | "defaultProject": "Demo.Web"
138 | }
139 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | ## Ignore Visual Studio temporary files, build results, and
2 | ## files generated by popular Visual Studio add-ons.
3 | ##
4 | ## Get latest from https://github.com/github/gitignore/blob/master/VisualStudio.gitignore
5 |
6 | # User-specific files
7 | *.rsuser
8 | *.suo
9 | *.user
10 | *.userosscache
11 | *.sln.docstates
12 |
13 | # User-specific files (MonoDevelop/Xamarin Studio)
14 | *.userprefs
15 |
16 | # Mono auto generated files
17 | mono_crash.*
18 |
19 | # Build results
20 | [Dd]ebug/
21 | [Dd]ebugPublic/
22 | [Rr]elease/
23 | [Rr]eleases/
24 | x64/
25 | x86/
26 | [Aa][Rr][Mm]/
27 | [Aa][Rr][Mm]64/
28 | bld/
29 | [Bb]in/
30 | [Oo]bj/
31 | [Ll]og/
32 | [Ll]ogs/
33 |
34 | # Visual Studio 2015/2017 cache/options directory
35 | .vs/
36 | # Uncomment if you have tasks that create the project's static files in wwwroot
37 | #wwwroot/
38 |
39 | # Visual Studio 2017 auto generated files
40 | Generated\ Files/
41 |
42 | # MSTest test Results
43 | [Tt]est[Rr]esult*/
44 | [Bb]uild[Ll]og.*
45 |
46 | # NUnit
47 | *.VisualState.xml
48 | TestResult.xml
49 | nunit-*.xml
50 |
51 | # Build Results of an ATL Project
52 | [Dd]ebugPS/
53 | [Rr]eleasePS/
54 | dlldata.c
55 |
56 | # Benchmark Results
57 | BenchmarkDotNet.Artifacts/
58 |
59 | # .NET Core
60 | project.lock.json
61 | project.fragment.lock.json
62 | artifacts/
63 |
64 | # StyleCop
65 | StyleCopReport.xml
66 |
67 | # Files built by Visual Studio
68 | *_i.c
69 | *_p.c
70 | *_h.h
71 | *.ilk
72 | *.meta
73 | *.obj
74 | *.iobj
75 | *.pch
76 | *.pdb
77 | *.ipdb
78 | *.pgc
79 | *.pgd
80 | *.rsp
81 | *.sbr
82 | *.tlb
83 | *.tli
84 | *.tlh
85 | *.tmp
86 | *.tmp_proj
87 | *_wpftmp.csproj
88 | *.log
89 | *.vspscc
90 | *.vssscc
91 | .builds
92 | *.pidb
93 | *.svclog
94 | *.scc
95 |
96 | # Chutzpah Test files
97 | _Chutzpah*
98 |
99 | # Visual C++ cache files
100 | ipch/
101 | *.aps
102 | *.ncb
103 | *.opendb
104 | *.opensdf
105 | *.sdf
106 | *.cachefile
107 | *.VC.db
108 | *.VC.VC.opendb
109 |
110 | # Visual Studio profiler
111 | *.psess
112 | *.vsp
113 | *.vspx
114 | *.sap
115 |
116 | # Visual Studio Trace Files
117 | *.e2e
118 |
119 | # TFS 2012 Local Workspace
120 | $tf/
121 |
122 | # Guidance Automation Toolkit
123 | *.gpState
124 |
125 | # ReSharper is a .NET coding add-in
126 | _ReSharper*/
127 | *.[Rr]e[Ss]harper
128 | *.DotSettings.user
129 |
130 | # TeamCity is a build add-in
131 | _TeamCity*
132 |
133 | # DotCover is a Code Coverage Tool
134 | *.dotCover
135 |
136 | # AxoCover is a Code Coverage Tool
137 | .axoCover/*
138 | !.axoCover/settings.json
139 |
140 | # Visual Studio code coverage results
141 | *.coverage
142 | *.coveragexml
143 |
144 | # NCrunch
145 | _NCrunch_*
146 | .*crunch*.local.xml
147 | nCrunchTemp_*
148 |
149 | # MightyMoose
150 | *.mm.*
151 | AutoTest.Net/
152 |
153 | # Web workbench (sass)
154 | .sass-cache/
155 |
156 | # Installshield output folder
157 | [Ee]xpress/
158 |
159 | # DocProject is a documentation generator add-in
160 | DocProject/buildhelp/
161 | DocProject/Help/*.HxT
162 | DocProject/Help/*.HxC
163 | DocProject/Help/*.hhc
164 | DocProject/Help/*.hhk
165 | DocProject/Help/*.hhp
166 | DocProject/Help/Html2
167 | DocProject/Help/html
168 |
169 | # Click-Once directory
170 | publish/
171 |
172 | # Publish Web Output
173 | *.[Pp]ublish.xml
174 | *.azurePubxml
175 | # Note: Comment the next line if you want to checkin your web deploy settings,
176 | # but database connection strings (with potential passwords) will be unencrypted
177 | *.pubxml
178 | *.publishproj
179 |
180 | # Microsoft Azure Web App publish settings. Comment the next line if you want to
181 | # checkin your Azure Web App publish settings, but sensitive information contained
182 | # in these scripts will be unencrypted
183 | PublishScripts/
184 |
185 | # NuGet Packages
186 | *.nupkg
187 | # NuGet Symbol Packages
188 | *.snupkg
189 | # The packages folder can be ignored because of Package Restore
190 | **/[Pp]ackages/*
191 | # except build/, which is used as an MSBuild target.
192 | !**/[Pp]ackages/build/
193 | # Uncomment if necessary however generally it will be regenerated when needed
194 | #!**/[Pp]ackages/repositories.config
195 | # NuGet v3's project.json files produces more ignorable files
196 | *.nuget.props
197 | *.nuget.targets
198 |
199 | # Microsoft Azure Build Output
200 | csx/
201 | *.build.csdef
202 |
203 | # Microsoft Azure Emulator
204 | ecf/
205 | rcf/
206 |
207 | # Windows Store app package directories and files
208 | AppPackages/
209 | BundleArtifacts/
210 | Package.StoreAssociation.xml
211 | _pkginfo.txt
212 | *.appx
213 | *.appxbundle
214 | *.appxupload
215 |
216 | # Visual Studio cache files
217 | # files ending in .cache can be ignored
218 | *.[Cc]ache
219 | # but keep track of directories ending in .cache
220 | !?*.[Cc]ache/
221 |
222 | # Others
223 | ClientBin/
224 | ~$*
225 | *~
226 | *.dbmdl
227 | *.dbproj.schemaview
228 | *.jfm
229 | *.pfx
230 | *.publishsettings
231 | orleans.codegen.cs
232 |
233 | # Including strong name files can present a security risk
234 | # (https://github.com/github/gitignore/pull/2483#issue-259490424)
235 | #*.snk
236 |
237 | # Since there are multiple workflows, uncomment next line to ignore bower_components
238 | # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
239 | #bower_components/
240 |
241 | # RIA/Silverlight projects
242 | Generated_Code/
243 |
244 | # Backup & report files from converting an old project file
245 | # to a newer Visual Studio version. Backup files are not needed,
246 | # because we have git ;-)
247 | _UpgradeReport_Files/
248 | Backup*/
249 | UpgradeLog*.XML
250 | UpgradeLog*.htm
251 | ServiceFabricBackup/
252 | *.rptproj.bak
253 |
254 | # SQL Server files
255 | *.mdf
256 | *.ldf
257 | *.ndf
258 |
259 | # Business Intelligence projects
260 | *.rdl.data
261 | *.bim.layout
262 | *.bim_*.settings
263 | *.rptproj.rsuser
264 | *- [Bb]ackup.rdl
265 | *- [Bb]ackup ([0-9]).rdl
266 | *- [Bb]ackup ([0-9][0-9]).rdl
267 |
268 | # Microsoft Fakes
269 | FakesAssemblies/
270 |
271 | # GhostDoc plugin setting file
272 | *.GhostDoc.xml
273 |
274 | # Node.js Tools for Visual Studio
275 | .ntvs_analysis.dat
276 | node_modules/
277 |
278 | # Visual Studio 6 build log
279 | *.plg
280 |
281 | # Visual Studio 6 workspace options file
282 | *.opt
283 |
284 | # Visual Studio 6 auto-generated workspace file (contains which files were open etc.)
285 | *.vbw
286 |
287 | # Visual Studio LightSwitch build output
288 | **/*.HTMLClient/GeneratedArtifacts
289 | **/*.DesktopClient/GeneratedArtifacts
290 | **/*.DesktopClient/ModelManifest.xml
291 | **/*.Server/GeneratedArtifacts
292 | **/*.Server/ModelManifest.xml
293 | _Pvt_Extensions
294 |
295 | # Paket dependency manager
296 | .paket/paket.exe
297 | paket-files/
298 |
299 | # FAKE - F# Make
300 | .fake/
301 |
302 | # CodeRush personal settings
303 | .cr/personal
304 |
305 | # Python Tools for Visual Studio (PTVS)
306 | __pycache__/
307 | *.pyc
308 |
309 | # Cake - Uncomment if you are using it
310 | # tools/**
311 | # !tools/packages.config
312 |
313 | # Tabs Studio
314 | *.tss
315 |
316 | # Telerik's JustMock configuration file
317 | *.jmconfig
318 |
319 | # BizTalk build output
320 | *.btp.cs
321 | *.btm.cs
322 | *.odx.cs
323 | *.xsd.cs
324 |
325 | # OpenCover UI analysis results
326 | OpenCover/
327 |
328 | # Azure Stream Analytics local run output
329 | ASALocalRun/
330 |
331 | # MSBuild Binary and Structured Log
332 | *.binlog
333 |
334 | # NVidia Nsight GPU debugger configuration file
335 | *.nvuser
336 |
337 | # MFractors (Xamarin productivity tool) working folder
338 | .mfractor/
339 |
340 | # Local History for Visual Studio
341 | .localhistory/
342 |
343 | # BeatPulse healthcheck temp database
344 | healthchecksdb
345 |
346 | # Backup folder for Package Reference Convert tool in Visual Studio 2017
347 | MigrationBackup/
348 |
349 | # Ionide (cross platform F# VS Code tools) working folder
350 | .ionide/
351 |
--------------------------------------------------------------------------------