Quantcast
Channel: Andy Blog
Viewing all articles
Browse latest Browse all 119

ASP.NET Core Tutorial (1) WebApi

$
0
0

download source code here

Create project via Cli

  1. Install .net core sdk, .net core runtime at https://www.microsoft.com/net/learn/get-started/windows or https://www.microsoft.com/net/download/windows

    in Feb, 2018, .net core sdk is v2.1.4, .net core runtime is v 2.0.5

  2. open console, dotnet new --help to check templates

  3. create webapi project, dotnet new webapi -o myApi

  4. run the app, dotnet run

  5. install entity framework core package. dotnet add Microsoft.EntityFrameworkCore.SqlServer

    other commands:

    dotnet add package: Adds a package reference to the project file, then runs dotnet restore to install the package. dotnet remove package: Removes a package reference from the project file dotnet restore: Restores the dependencies and tools of a project. dotnet nuget locals: Clears or lists local NuGet resources such as the http-request cache, the temporary cache, and the machine-wide global packages folder.

Create project via Visual Studio

we got

If this webapi project references other libaries, make sure to choose the compatible .net framework version

ctrl + f5 to run,

nuget > install Microsoft.EntityFrameworkCore.SqlServer package

Create a simple demo

  1. add models

    Models > TodoItem.cs:

     namespace Models
     {
         public class TodoItem
         {
             public long Id { get; set; }
             public string Name { get; set; }
             public bool IsComplete { get; set; }
         }
     }
    
  2. add data

    Data > TodoContext.cs:

     using Microsoft.EntityFrameworkCore;
     using Models;
    
     namespace TodoApi.Models
     {
         public class TodoContext : DbContext
         {
             public TodoContext(DbContextOptions<TodoContext> options)
                 : base(options)
             {
             }
    	
             public DbSet<TodoItem> TodoItems { get; set; }
    	
         }
     }
    

  3. register db context in dependency injection container. Here we specify an in-memory database is injected into the service container.

    update Startup.cs

     public class Startup
     {       
         public void ConfigureServices(IServiceCollection services)
         {
             services.AddDbContext<TodoContext>(opt => opt.UseInMemoryDatabase("TodoList"));
             services.AddMvc();
         }
         ...
     }
    
  4. Create a controller: TodoController.cs

     using Microsoft.AspNetCore.Mvc;
     using Models;
     using Data;
     using System.Linq;
    	
     namespace TodoApi.Controllers
     {
         [Route("api/[controller]")]
         public class TodoController : Controller
         {
             private readonly TodoContext _context;
    	
             public TodoController(TodoContext context)
             {
                 _context = context;
    	
                 if (_context.TodoItems.Count() == 0)
                 {
                     _context.TodoItems.Add(new TodoItem { Name = "Item1" });
                     _context.SaveChanges();
                 }
             }
         }
     }
    
  5. Add get endpoints

     [HttpGet]
     public IEnumerable<TodoItem> GetAll()
     {
         return _context.TodoItems.ToList();
     }
    	
     [HttpGet("{id}", Name = "GetTodo")]
     public IActionResult GetById(long id)
     {
         var item = _context.TodoItems.FirstOrDefault(t => t.Id == id);
         if (item == null)
         {
             return NotFound();
         }
         return new ObjectResult(item);
     }
    
  6. Add create endpoint

     [HttpPost]
     public IActionResult Create([FromBody] TodoItem item)
     {
         if (item == null)
         {
             return BadRequest();
         }
    	
         _context.TodoItems.Add(item);
         _context.SaveChanges();
    	
         return CreatedAtRoute("GetTodo", new { id = item.Id }, item);
     }
    
  7. Add update endpoint

     [HttpPut("{id}")]
     public IActionResult Update(long id, [FromBody] TodoItem item)
     {
         if (item == null || item.Id != id)
         {
             return BadRequest();
         }
    	
         var todo = _context.TodoItems.FirstOrDefault(t => t.Id == id);
         if (todo == null)
         {
             return NotFound();
         }
    	
         todo.IsComplete = item.IsComplete;
         todo.Name = item.Name;
    	
         _context.TodoItems.Update(todo);
         _context.SaveChanges();
         return new NoContentResult();
     }
    
  8. add delete endpoint

     [HttpDelete("{id}")]
     public IActionResult Delete(long id)
     {
         var todo = _context.TodoItems.FirstOrDefault(t => t.Id == id);
         if (todo == null)
         {
             return NotFound();
         }
    	
         _context.TodoItems.Remove(todo);
         _context.SaveChanges();
         return new NoContentResult();
     }
    

Enable cors

  1. Install package Microsoft.AspNetCore.Cors either via nuget in visual studio or command line

  2. Enable cors

    1. way1, enable in middleware. modify Startup.cs

       public void ConfigureServices(IServiceCollection services)
       {
           services.AddCors();
       }
      
    2. way2, enable in controller

Add lazy loading

  1. Install package Microsoft.EntityFrameworkCore.Proxies

  2. Suppose we have a database EmployeeManagement, we use database first to generate model classes:

    Scaffold-DbContext "Server=(local);Database=EmployeeManagement;Integrated Security=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities

    A folder Entities will be created with entities and dbcontext in it

  3. Open entity classes, manually set all navigation properties as virtual:

  4. Enable lazy loading, Startup.cs

     ```
     ...
      public void ConfigureServices(IServiceCollection services)
             {
                 // add db optoins
                 var connection = @"Server=(local);Database=EmployeeManagement;Integrated Security=true;";
                 services.AddDbContext<EmployeeManagementContext>(opt =>
                     {
                         opt.UseLazyLoadingProxies().UseSqlServer(connection);
                     }
                 );
                 //services.AddEntityFrameworkProxies();
                 services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
             }
     ```
    

Test

  1. run via dotnet run

  2. navigate to http://localhost:5000/api/todo

  3. post a json data

    { “id”: 2, “name”: “Item2”, “isComplete”: true }

Add database first entities

  1. Add nuget libraries:
     Microsoft.EntityFrameworkCore.SqlServer
     EntityFrameworkCore.Tools
     EntityFrameworkCore.SqlServer.Design
    
  2. nuget command console Scaffold-DbContext "Server=(local)\SQLEXPRESS;Database=EFCoreDBFirstDemo;Integrated Security=True;" Microsoft.EntityFrameworkCore.SqlServer -OutputDir Entities

    it will create a Entities folder with all models from database inside it.

Enable cors

  1. Install Microsoft.AspNetCore.Cors package

  2. Add the CORS services

     public void ConfigureServices(IServiceCollection services)
     {
         ...
         services.AddCors();
     } 
    
  3. Enable cors with middleware. Note that the CORS middleware must precede any defined endpoints in your app that you want to support cross-origin requests (ex. before any call to UseMvc).

     public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
     {
         loggerFactory.AddConsole();
    	
         if (env.IsDevelopment())
         {
             app.UseDeveloperExceptionPage();
         }
    	
         // Shows UseCors with CorsPolicyBuilder.
         app.UseCors(builder =>
            builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());
    	
         ...
     }
    

Model validation

Attribute validation

  1. modify properties of model

  2. We can define our own validation attribute

     public class TorontoPhoneAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
     { 
    
         protected override ValidationResult IsValid(object value, ValidationContext validationContext)
         {
             if(!value.ToString().StartsWith("647"))
             {
                 return new ValidationResult("this is not 647-xxx-xxxx");
             }
             return null;
         }
     }
    
  3. In controller, verify ModelStatus.IsValid and return badrequest accordingly

     [HttpPost("")]
     public IActionResult AddCompany([FromBody] TblCompany company)
     {
         if (ModelState.IsValid)
         {
             this.employeeManagementV2Context.TblCompany.Add(company);
             this.employeeManagementV2Context.SaveChanges();
             return Ok();
         }
         return BadRequest(ModelState);
     }
    
  4. POST a request, we will get errors as below

Fluent validation

  1. Install 3rd package
    • asp.net core FluentValidation.AspNetCore
    • asp.net mvc FluentValidation.Mvc5
    • asp.net webapi v2 FluentValidation.WebApi

References

https://docs.microsoft.com/en-us/aspnet/core/tutorials/first-web-api

https://blogs.msdn.microsoft.com/webdev/2017/04/06/jwt-validation-and-authorization-in-asp-net-core/

https://docs.microsoft.com/en-us/aspnet/core/tutorials/web-api-help-pages-using-swagger?tabs=visual-studio

https://docs.microsoft.com/en-us/aspnet/core/security/cors

https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters?view=aspnetcore-2.1

https://fluentvalidation.net

https://www.c-sharpcorner.com/article/learn-about-web-api-validation/

https://www.jerriepelser.com/blog/validation-response-aspnet-core-webapi/


Viewing all articles
Browse latest Browse all 119

Latest Images

Trending Articles



Latest Images