From 0fd87958afd7b3c8eb89e948b8304c4658c668d5 Mon Sep 17 00:00:00 2001 From: Marcello Lamonaca Date: Wed, 27 Oct 2021 14:05:47 +0200 Subject: [PATCH 1/5] Add variance summary image --- .images/dotnet_covariant_contravariant.png | Bin 0 -> 17479 bytes DotNet/C#/C#.md | 2 ++ 2 files changed, 2 insertions(+) create mode 100644 .images/dotnet_covariant_contravariant.png diff --git a/.images/dotnet_covariant_contravariant.png b/.images/dotnet_covariant_contravariant.png new file mode 100644 index 0000000000000000000000000000000000000000..a08ac6eee17069c90e8aabdfd69aab59e99606c6 GIT binary patch literal 17479 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 Date: Mon, 8 Nov 2021 09:17:32 +0100 Subject: [PATCH 2/5] Mark postponed C# features --- DotNet/C#/C#.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/DotNet/C#/C#.md b/DotNet/C#/C#.md index ad2aff8..d7c3a9e 100644 --- a/DotNet/C#/C#.md +++ b/DotNet/C#/C#.md @@ -1439,10 +1439,10 @@ class Class set => _backingField = value; } - // access backing field with the field keyword [C# 10] + // access backing field with the field keyword [C# 11?] public Type Property { get => field; set => field = value; } - // required property [C# 10], prop myst be set at obj init (in constructor or initializer) + // required property [C# 11?], prop must be set at obj init (in constructor or initializer) public required Type Property { get; set; } // EXPRESSION-BODIED READ-ONLY PROPERTY From 1fad5ca3bdefa8a618fd7066ead423caadce1174 Mon Sep 17 00:00:00 2001 From: Marcello Lamonaca Date: Mon, 8 Nov 2021 11:47:02 +0100 Subject: [PATCH 3/5] Add notes on testing file & directory existance --- Bash/Bash Commands.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Bash/Bash Commands.md b/Bash/Bash Commands.md index 274cff8..bd4cda8 100644 --- a/Bash/Bash Commands.md +++ b/Bash/Bash Commands.md @@ -127,8 +127,9 @@ find [start-position] -type f -name FILENAME # search for a file named "filenam find [start-position] -type d -name DIRNAME # search for a directory named "dirname" find [path] -exec {} \; # execute command on found items (identified by {}) -[ -f "path" ] # test if a file exists -[ -d "path" ] # test if a folder exists +[[ -f "path" ]] # test if a file exists +[[ -d "path" ]] # test if a folder exists +[[ -L "path" ]] # test if is symlink ``` ### Other From c939822755988b93fbd415988b3df3acf9eafa6f Mon Sep 17 00:00:00 2001 From: Marcello Lamonaca Date: Tue, 9 Nov 2021 14:51:42 +0100 Subject: [PATCH 4/5] Simplify REST API Notes --- DotNet/ASP.NET/REST API.md | 297 +++++-------------------------------- 1 file changed, 41 insertions(+), 256 deletions(-) diff --git a/DotNet/ASP.NET/REST API.md b/DotNet/ASP.NET/REST API.md index c5ed0fe..491f27c 100644 --- a/DotNet/ASP.NET/REST API.md +++ b/DotNet/ASP.NET/REST API.md @@ -1,181 +1,5 @@ # ASP .NET REST API -## Startup class - -- Called by `Program.cs` - -```cs -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.Configuration; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; - -namespace -{ - public class Startup - { - public Startup(IConfiguration configuration) - { - Configuration = configuration; - } - - public IConfiguration Configuration { get; } - - // This method gets called by the runtime. Use this method to add services to the container. - public void ConfigureServices(IServiceCollection services) - { - services.AddControllers(); // controllers w/o views - //or - services.AddControllersWithViews(); // MVC Controllers - } - - // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - - app.UseHttpsRedirection(); - - app.UseRouting(); - - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapControllers(); - }); - } - } -} -``` - -## DB Context (EF to access DB) - -NuGet Packages to install: - -- `Microsoft.EntityFrameworkCore` -- `Microsoft.EntityFrameworkCore.Tools` -- `Microsoft.EntityFrameworkCore.Design` *or* `Microsoft.EntityFrameworkCore..Design` -- `Microsoft.EntityFrameworkCore.` - -In `AppDbContext.cs`: - -```cs -using .Model; -using Microsoft.EntityFrameworkCore; - -namespace .Repo -{ - public class AppDbContext : DbContext - { - public AppDbContext(DbContextOptions options) : base(options) - { - - } - //DBSet represents the collection of all entities in the context, or that can be queried from the database, of a given type - public DbSet entities { get; set; } - } -} -``` - -In `appsettings.json`: - -```json -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - "AllowedHosts": "*", - "ConnectionStrings": { - "CommanderConnection" : "Server=;Database=;UID=;Pwd=" - } -} -``` - -In `Startup.cs`: - -```cs -// This method gets called by the runtime. Use this method to add services to the container. -public void ConfigureServices(IServiceCollection services) -{ - // SqlServer is the db used in this example - services.AddDbContext(option => option.UseSqlServer(Configuration.GetConnectionString("CommanderConnection"))); - services.AddControllers(); -} -``` - -### Migrations - -- Mirroring of model in the DB. -- Will create & update DB Schema if necessary - -In Package Manager Shell: - -```ps1 -add-migrations -update-database # use the migrations to modify the db -``` - -## Repository - -In `IEntityRepo`: - -```cs -using .Model; -using System.Collections.Generic; - -namespace .Repository -{ - public interface IEntityRepo - { - IEnumerable SelectAll(); - Entity SelectOneById(int id); - - ... - } -} -``` - -In `EntityRepo`: - -```cs -using .Model; -using System.Collections.Generic; - -namespace .Repo -{ - public class EntityRepo : IEntityRepo - { - private readonly AppDbContext _context; - - public EntityRepo(AppDbContext context) - { - _context = context; - } - - public IEnumerable SelectAll() - { - return _context.Entities.ToList(); // linq query (ToList()) becomes sql query - } - - public Entity SelectOneById(int id) - { - return _context.Entities.FirstOrDefault(p => p.Id == id); - } - - ... - } -} -``` - ## Data Transfer Objects (DTOs) A **DTO** is an object that defines how the data will be sent and received over the network (usually as JSON). @@ -202,13 +26,13 @@ public void ConfigureServices(IServiceCollection services) } ``` -In `EntityDTO.cs`: +In `EntityDTO.cs`: ```cs namespace .DTOs { // define the data to be serialized in JSON (can differ from model) - public class EntityCrudOpDTO // e.g: EntityReadDTO, ... + public class EntityDTO { // only properties to be serialized } @@ -228,7 +52,7 @@ namespace .Profiles { public EntitiesProfile() { - CreateMap(); // map entity to it's DTO + CreateMap(); // map entity to it's DTO } } } @@ -236,69 +60,40 @@ namespace .Profiles ## Controller (No View) -Uses [Dependency Injection](https://en.wikipedia.org/wiki/Dependency_injection) to receive a suitable implementation of `IEntityRepo`, - -### Service Lifetimes - -- `AddSingleton`: same for every request -- `AddScoped`: created once per client -- `Transient`: new instance created every time - -In `Startup.cs`: - ```cs -// This method gets called by the runtime. Use this method to add services to the container. -public void ConfigureServices(IServiceCollection services) +[Route("api/endpoint")] +[ApiController] +public class EntitiesController : ControllerBase // MVC controller w/o view { - services.AddControllers(); - services.AddScoped(); // map the interface to its implementation, needed for dependency injection -} -``` + private readonly ICommandRepo _repo; + private readonly IMapper _mapper; // AutoMapper class -### Request Mappings - -```cs -using .Model; -using .Repo; -using Microsoft.AspNetCore.Mvc; -using System.Collections.Generic; - -namespace .Controllers -{ - [Route("api/endpoint")] - [ApiController] - public class EntitiesController : ControllerBase // MVC controller w/o view + public EntitiesController(IEntityRepo repository, IMapper mapper) { - private readonly ICommandRepo _repo; - private readonly IMapper _mapper; // AutoMapper class + _repo = repository; + _mapper = mapper + } - public EntitiesController(IEntityRepo repository, IMapper mapper) // injection og the dependency + [HttpGet] // GET api/endpoint + public ActionResult> SelectAllEntities() + { + var results = _repo.SelectAll(); + + return Ok(_mapper.Map(results)); + } + + [HttpGet("{id}")] // GET api/endpoint/{id} + public ActionResult SelectOneEntityById(int id) + { + var result = _repo.SelectOneById(id); + + if(result != null) { - _repo = repository; - _mapper = mapper + // transform entity to it's DTO + return Ok(_mapper.Map(result)); } - [HttpGet] // GET api/endpoint - public ActionResult> SelectAllEntities() - { - var results = _repo.SelectAll(); - - return Ok(_mapper.Map(results)); // return an action result OK (200) with the results - } - - // default binding source: [FromRoute] - [HttpGet("{id}")] // GET api/endpoint/{id} - public ActionResult SelectOneEntityById(int id) - { - var result = _repo.SelectOneById(id); - - if(result != null) - { - return Ok(_mapper.Map(result)); // transform entity to it's DTO - } - - return NotFound(); // ActionResult NOT FOUND (404) - } + return NotFound(); } } ``` @@ -306,31 +101,21 @@ namespace .Controllers ## Controller (With View) ```cs -using .Model; -using Microsoft.AspNetCore.Mvc; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Threading.Tasks; - -namespace .Controllers +[Route("api/endpoint")] +[ApiController] +public class EntitiesController : Controller { - [Route("api/endpoint")] - [ApiController] - public class EntitiesController : Controller + private readonly AppDbContext _db; + + public EntitiesController(AppDbContext db) { - private readonly AppDbContext _db; + _db = db; + } - public EntitiesController(AppDbContext db) - { - _db = db; - } - - [HttpGet] - public IActionResult SelectAll() - { - return Json(new { data = _db.Entities.ToList() }); // json view - } + [HttpGet] + public IActionResult SelectAll() + { + return Json(new { data = _db.Entities.ToList() }); // json view } } ``` From b3d3606c482c87e5eaeed3a1cd05d4706f1fc749 Mon Sep 17 00:00:00 2001 From: Marcello Lamonaca Date: Tue, 9 Nov 2021 14:55:42 +0100 Subject: [PATCH 5/5] Add Swagger notes --- DotNet/ASP.NET/App Configuration.md | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/DotNet/ASP.NET/App Configuration.md b/DotNet/ASP.NET/App Configuration.md index d2949a9..6102d3f 100644 --- a/DotNet/ASP.NET/App Configuration.md +++ b/DotNet/ASP.NET/App Configuration.md @@ -1,5 +1,17 @@ # ASP.NET Configuration +## `.csproj` + +```xml + + + true + + + $(NoWarn);1591 + +``` + ## `Program.cs` ```cs @@ -78,12 +90,20 @@ namespace App services.AddServerSideBlazor(); // needs Razor Pages services.AddSignalR(); - + // set dependency injection lifetimes services.AddSingleton(); services.AddScoped(); services.AddTransient(); - + + // add swagger + services.AddSwaggerGen(options => { + + // OPTIONAL: use xml comments for swagger documentation + var xmlFilename = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + options.IncludeXmlComments(Path.Combine(AppContext.BaseDirectory, xmlFilename)); + }); + } // This method gets called by the runtime. Use this method to configure the HTTP request pipeline. @@ -99,6 +119,7 @@ namespace App // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } + app.UseHttpsRedirection(); app.UseStaticFiles(); @@ -106,6 +127,9 @@ namespace App app.UseAuthorization(); + app.UseSwagger(); + app.UseSwaggerUI(); + app.UseEndpoints(endpoints => { // MVC routing