Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Einmal API mit allem bitte - ASP.NET Core MVC und SignalR in Action

Einmal API mit allem bitte - ASP.NET Core MVC und SignalR in Action

Moderne APIs können so viel mehr als nur gängige HTTPS-Endpunkte bereitzustellen: Zum einen die Möglichkeit zur (optionalen) Echtzeitkommunikation auf Basis von WebSockets. Mit Hilfe von Microsofts Open-Source-Plattform ASP.NET Core MVC und SignalR lassen sich im Handumdrehen Web-APIs und Push Services entwickeln. Doch damit nicht genug: Weitere Themen wie Security, Rate Limiting, eine sinnvolle Dokumentation und ein vernünftiges, zentralisiertes Logging sind mit von der Partie. Und jeder dieser einzelnen Bereiche bietet uns eine neue Herausforderung.

Sebastian Gingter und Manuel Rauber zeigen Ihnen in diesem Workshop, wie man mit .NET Core moderne APIs auf und für verschiedene Plattformen entwickeln kann. Zusätzlich wird durch den Einsatz von Entity Framework Core die Anbindung an unterschiedliche Datenbanken ermöglicht. Durch den Einsatz weiterer Open-Source-Bibliotheken für das Logging oder zur automatischen Generierung einer Swagger/OpenAPI-Dokumentation ergänzen wir das API um weitere Funktionalitäten. Eine Clientanwendung, das Deployment auf unterschiedliche Plattformen und das Deployment in die Cloud runden den Workshop ab – vollständig End-to-End und einmal mit allem eben!

GitHub: https://github.com/thinktecture/api-ms-summit-spring-2019-services-dotnetcore

Manuel Rauber

June 19, 2019
Tweet

More Decks by Manuel Rauber

Other Decks in Programming

Transcript

  1. ASP.NET Core MVC und SignalR in Action!
    Einmal API mit allem, bitte.
    Sebastian Gingter Manuel Rauber
    @PhoenixHawk @ManuelRauber
    Consultant Consultant

    View Slide

  2. Speakers
    [email protected]
    @manuelrauber
    https://manuel-rauber.com
    Microsoft MVP
    [email protected]
    @PhoenixHawk
    https://gingter.org/

    View Slide

  3. Time Doing
    09:00 – 10:30 Part I
    10:30 – 11:00 ☕
    11:00 – 12:30 Part II
    12:30 – 13:30
    13:30 – 15:00 Part III
    15:00 – 15:30 ☕ &
    15:30 – 17:00 Part IV
    Timetable

    View Slide

  4. • Lightweight service-based architecture
    • Functional services with dedicated interfaces
    • Use other services, like database or file system
    • (JSON-based) HTTPS Web APIs
    • Application push services via WebSocket
    • SignalR
    • Socket.io
    Target Architecture
    HTTP HTTPS WebSocket
    Service A Service B Service C
    Web APIs
    (ASP.NET, Node.js, …)
    HTML5-Application
    (Single-Page Application)
    Web Cordova Electron

    View Slide

  5. • Functional services with dedicated interfaces
    • Strict REST services do not model real world
    • Better: Design interfaces according to use case
    • Single Web API can use multiple backend services
    • (JSON-based) HTTPS Web APIs
    • Embraces usage of common denominator
    • Content Negotation
    • HTTP Status Codes
    • Resources are mapped to URLs
    • Lightweight & scalable
    Target Architecture
    HTTP HTTPS WebSocket
    Service A Service B Service C
    Web APIs
    (ASP.NET, Node.js, …)
    AuthN & AuthZ
    Client

    View Slide

  6. From specification to implementation
    .NET Standard & .NET Core

    View Slide

  7. What exactly is it?
    • .NET Standard is an open source specification: https://github.com/dotnet/standard
    • Represents a common set of API to be implemented by all .NET platforms
    • .NET Standard replaces PCLs
    .NET Standard

    View Slide

  8. One library to rule them all
    .NET tomorrow today!
    https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/

    View Slide

  9. .NET Core 3.0 Future

    View Slide

  10. Overview
    • .NET Core is an open source implementation of the .NET Standard specification:
    • https://github.com/dotnet/core
    • Runs on Linux, macOS and Windows
    • CLI tools available
    • Supports C# and F#
    • Compatible to .NET Framework, Xamarin and Mono (due to .NET Standard)
    • Fully supported by Microsoft (LTS support three years after GA)
    .NET Core

    View Slide

  11. Platform-specific APIs
    Some APIs are not available everywhere (e.g. Registry, Windows Identity, Reflection Emit) and
    will throw a PlatformNotSupportedException.
    .NET Core

    View Slide

  12. IDEs
    .NET Core
    VS 2017/2019
    VS Code JetBrains Rider
    VS for Mac

    View Slide

  13. Use case depending alternatives
    • Node.js
    • JavaScript, TypeScript, CoffeeScript, …
    • Restify, Express, Koa.js
    • TypeORM, SequelizeJS, ORM
    • Node Package Manager, YARN
    • Java
    • Jersey, RESTful WebServices
    • Hibernate, ORM
    • Maven, Package Management
    • Ruby, Python, …
    .NET Core

    View Slide

  14. Summary
    • Powerful language/tools and base for creating cross-platform .NET libs & apps
    • Good and growing API support
    • Targeting platform specific APIs could result in an error or conditional compilation
    • Cloud-ready
    • „No breaking changes between versions“
    .NET Standard & .NET Core

    View Slide

  15. No …
    No … breaking …
    No … breaking … changes …
    No … breaking … changes … between …
    No … breaking … changes … between … versions …

    View Slide

  16. Ready for your next Todo App? ;-)
    The Sample

    View Slide

  17. Security Token Service
    Identity Server
    Database Todo-
    API
    Push-
    API
    Realtime-Data
    Users
    Web-Server
    SPA (static files)
    Demo Architecture

    View Slide

  18. Security Token Service
    Identity Server
    Database Todo-
    API
    Push-
    API
    Realtime-Data
    Users
    Web-Server
    SPA (static files)
    Demo Architecture

    View Slide

  19. Demo Client Application

    View Slide

  20. Cross-Platform Web Application & Web APIs
    ASP.NET Core

    View Slide

  21. Overview
    • Unifies MVC and Web APIs
    • Built-in dependency injection
    • Cloud-ready configuration system
    • HTTP Request Pipeline
    • Hostable in IIS or as Self Host
    • Everything’s a NuGet Package
    • Leads to having a lot packages installed (“Hello node_modules J”)
    • Built on .NET Core
    • Open Source, https://github.com/aspnet/Home
    • “Can I port my application to .NET Core?”
    • https://icanhasdot.net/
    ASP.NET Core

    View Slide

  22. Compared to ASP.NET
    ASP.NET Core
    • Runs on Linux, macOS, Windows
    • C#, F#
    • MVC & Web API, Razor Pages
    • New platform, new toolings
    • Multiple versions per machine
    • MSDN: “Ultra Performance”
    ASP.NET
    • Runs on Windows
    • C#, F#, VB.NET
    • MVC, Web API, WebForms, WebPages,
    SignalR
    • Mature platform
    • One version per machine
    • MSDN: “High Performance”
    ASP.NET Core

    View Slide

  23. Hosting
    • Kestrel: ASP.NET Core’s Web Server
    • IISIntegration to host in IIS
    • Mandatory for App Services
    • Specifies a class used
    for Startup configuration
    ASP.NET Core
    public class Program
    {
    public static void Main(string[] args)
    {
    var host = new WebHostBuilder()
    .UseKestrel()
    .UseContentRoot(Directory.GetCurrentDirectory())
    .UseIISIntegration()
    .UseStartup()
    .Build();
    host.Run();
    }
    }

    View Slide

  24. Startup
    • ConfigureServices: Used for configuring the built-in dependency injection
    • Configure: Used for configuring the HTTP pipeline via IApplicationBuilder
    ASP.NET Core
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services) { }
    public void Configure(IApplicationBuilder app,
    IHostingEnvironment env, ILoggerFactory loggerFactory) { }
    }

    View Slide

  25. Dependency Injection
    • Built-in dependency injection
    • Constructor injection should be preferred over direct DI container access
    • Overriding the container is possible, e.g. to use AutoFac instead
    • Throws an error when a dependency could not be resolved (e.g. wrong container configuration)
    ASP.NET Core

    View Slide

  26. Dependency Injection
    • Supports three lifetimes
    • Transient: Creates an instance each it is requested
    • Scoped: Creates an instance once per request
    • Singleton: Creates an instance once per application
    ASP.NET Core
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddTransient();
    services.AddScoped();
    services.AddSingleton();
    }

    View Slide

  27. Pipeline
    • Customizable HTTP pipeline
    • Every request will run through
    • Order in code defines the order of the pipeline
    • Nesting of pipelines is possible
    • IApplicationBuilder is used to define the pipeline
    ASP.NET Core
    https://docs.microsoft.com/en-us/aspnet/core/fundamentals/middleware
    public void Configure(IApplicationBuilder app)
    {
    app.UseExceptionHandler("/Home/Error");
    app.UseStaticFiles();
    app.UseMvcWithDefaultRoute();
    }
    Middleware 1
    // Server logic
    next()
    // more logic
    Middleware 2
    // Server logic
    next()
    // more logic
    Middleware 3
    // Server logic
    // more logic
    Request
    Response
    Client
    Logging Authentication …

    View Slide

  28. Multiple Environments
    • Support multiple environments like Development, Staging or Production out-of-box
    • Can be set via environment variable ASPNETCORE_ENVIRONMENT
    • Convention based application startup
    • Startup, StartupDevelopment, Startup{Environment}
    • Careful, using webhostBuilder.UseStartup() overrides this behavior
    • Configure, ConfigureDevelopment, Configure{Environment}
    • ConfigureServices, ConfigureDevelopmentServices, Configure{Environment}Services
    ASP.NET Core

    View Slide

  29. Multiple Environments
    IHostingEnvironment for checking environment at runtime
    ASP.NET Core
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    if (env.IsDevelopment() || env.IsProduction() || env.IsStaging() || env.IsEnvironment(”MyEnv"))
    { }
    }

    View Slide

  30. Configuration System
    • ConfigurationBuilder is used to define configuration sources
    • Order is used for configuration overriding, later defined sources override previous defined
    • Optional sources and sources depending on the environment are possible
    ASP.NET Core
    public Startup(IHostingEnvironment env)
    {
    var builder = new ConfigurationBuilder()
    .SetBasePath(env.ContentRootPath)
    .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true)
    .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
    .AddEnvironmentVariables();
    Configuration = builder.Build();
    }

    View Slide

  31. Options Pattern
    • Typed (nested) Configurations
    • Injectable
    • Runtime-reloadable
    ASP.NET Core
    public void ConfigureServices(IServiceCollection services)
    {
    services.Configure(Configuration.GetSection("PushServer"));
    }
    public class PushService {
    private readonly PushServerSettings _config;
    public PushService(IOptions settingsAccessor) {
    _config = settingsAccessor.Value;
    }
    }

    View Slide

  32. Authentication
    • Middleware within the pipeline
    • “Plug & Play” solutions for authentication
    • ASP.NET Identity
    • IdentityServer 4, open source project
    • Different authentication schemes
    • Cookies
    • Bearer
    • Basic
    • External providers
    • Custom
    ASP.NET Core

    View Slide

  33. Controllers
    • Two base classes for controllers
    • ControllerBase: Preferred for Web APIs, offers everything except Views
    • Controller: Preferred for MVC, inherits from ControllerBase and adds View capabilities
    • Offer various methods for returning a result
    • Ok() / NotFound() / StatusCodeResult()
    • FileResult() / FileContentResult() / FileStreamResult()
    • Offers access to authenticated user via User property
    • Can be asynchronous using async/await pattern
    • If enabled, automatic Content Negotiation
    ASP.NET Core

    View Slide

  34. Routing
    • Routing: Mapping URLs to actions (methods within a controller)
    • Routing via definition in pipeline
    • Routing via attributes
    • Routing via custom routing handler
    • Support for all important HTTP verbs like GET, POST, PUT, DELETE
    ASP.NET Core
    public void Configure(IApplicationBuilder app) =>
    app.UseMvc(routes => routes.MapRoute("api", "{controller}/{action}"));
    [Route("customers")]
    public class CustomerApiController : ControllerBase
    {
    [HttpGet("{id:int}")]
    public IActionResult Get(int id) { }
    }

    View Slide

  35. Error Handling
    • Provides a developer exception page with detailed information about errors
    • Supports error page per status code or custom error pages
    • Supports custom error filter per action, controller or globally
    ASP.NET Core
    public void Configure(IApplicationBuilder app)
    {
    // Use in development only
    app.UseDeveloperExceptionPage();
    // Simple status code error pages
    app.UseStatusCodePages();
    // Custom error handler
    app.UseExceptionHandler("/error");
    }

    View Slide

  36. Swagger Help Pages
    • NuGet: Swashbuckle.AspNetCore
    • Swagger: Generates a swagger.json containing all information about your Web APIs
    • Swagger UI: Provides a basic UI to view the swagger.json
    ASP.NET Core
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddSwaggerGen(options =>
    {
    options.SwaggerDoc("v1", new Info() { Title = "Awesome Customer API", Version = "1.0" });
    });
    }
    public void Configure(IApplicationBuilder app)
    {
    app.UseSwagger();
    app.UseSwaggerUI(options => { options.SwaggerEndpoint("v1/swagger.json", "API v1"); });
    }

    View Slide

  37. Swagger Help Pages
    ASP.NET Core

    View Slide

  38. • Built-in logging
    • Third party logging solutions (e.g. Serilog, Nlog) can be easily integrated without changing the
    logging API
    Logging
    public class SampleController : ControllerBase {
    private readonly ILogger _logger;
    public SampleController(ILogger logger)
    {
    _logger = logger;
    }
    [HttpGet]
    public IActionResult Get(int listId, string listName)
    {
    _logger?.LogDebug($"{nameof(SendListCreated)}: {{ListId}}, {{ListName}}", listId, listName);
    // Useful code
    }
    }

    View Slide

  39. • https://github.com/stefanprodan/AspNetCoreRateLimit
    • Public APIs
    • DDoS protection
    • Pay per request APIs
    • Rates for “expensive” resources
    • Rates per timeframe: Hour, Minute, Second
    • How?
    • IP-based
    • Account-based
    Rate Limiting
    public void ConfigureServices(IServiceCollection services)
    {
    services
    .Configure(Configuration.GetSection("IpRateLimiting"))
    .Configure(Configuration.GetSection("IpRateLimitPolicies"))
    .AddSingleton()
    .AddSingleton();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    app.UseIpRateLimiting();
    }

    View Slide

  40. • Tell client that the data did not change
    • HTTP Status Code 304
    • Two standardized options
    • Last Modified Header: Did data change since …?
    • Etag-Header: Checksum of data
    • e.g.: https://github.com/KevinDockx/HttpCacheHeaders
    Reduce traffic
    Initial request
    GET /item/1
    OK 200
    Etag: 123123123123
    Following request
    GET /item/1
    If-None-Match: 123123123123
    304 Not Modified

    View Slide

  41. • Supported by all modern browsers
    • Supported by most servers
    • Reduces traffic by up to 70 %
    • But
    • more computation on server and client
    • is not always smaller
    • https://docs.microsoft.com/en-us/aspnet/core/performance/response-compression
    GZIP
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddResponseCompression();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    app.UseResponseCompression();
    }

    View Slide

  42. • Via URL (api.com/v1/item/1)
    • Via Accept-Header
    • Via Custom-Header
    • https://github.com/Microsoft/aspnet-api-versioning
    Versioning
    public class Startup
    {
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddMvc();
    services.AddApiVersioning();
    }
    }
    [ApiVersion("1.0")]
    [Route("[controller]")]
    public class PeopleController : Controller
    {
    [HttpGet]
    public IActionRoute Get() => Ok(new[] { new Person() });
    }

    View Slide

  43. • Hypermedia as the engine of application state
    • Navigate from anywhere to everywhere
    • Usage of API without prior knowledge
    HATEOAS

    View Slide

  44. • Example: POST
    • Example: Pagination
    HATEOAS
    POST /items
    201 Created
    Location: https://api.io/item/3
    GET /items?page=1&size=10
    200 OK
    Link:
    ; rel=“next”,
    ; rel=“last”

    View Slide

  45. • Bi-directional real time communication server <-> client
    • Integrates into the whole ASP.NET Core universe (Routing, Dependency Injection)
    • No jQuery dependency on client-side anymore!!!!111
    • Usable not only on client-side JavaScript, but in Node.js or Web Workers
    • Browser support: IE 11, all evergreens
    SignalR

    View Slide

  46. Integrate into ASP.NET Core pipeline
    Add NuGet “Microsoft.AspNetCore.SignalR” (included by default)
    SignalR
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddSignalR();
    }
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
    app.UseSignalR(routes =>
    {
    routes.MapHub("/chathub");
    });
    }

    View Slide

  47. Hub
    • Represents a high-level pipeline allowing clients and
    servers to call methods on each other.
    • Bridges dispatching messages between client and
    server to easily call methods.
    • Strongly-typed parameters, model binding
    • Text protocol on JSON, binary protocol on MessagePack
    SignalR
    Hubs
    Endpoints
    Clients
    Transport
    WebSocket
    Server-Sent Events
    Long Polling
    Built on top of
    Text/Binary protocol
    via
    JSON/MessagePack
    public class ChatHub : Hub
    {
    public async Task SendMessage(string user, string message)
    {
    await Clients.All.SendAsync("ReceiveMessage", user, message);
    }
    }

    View Slide

  48. JavaScript Client
    • Install via NPM: @aspnet/signalr
    • Don’t forget CORS!
    • Possibility to receive and invoke methods
    • Third party modules for RxJS integration
    SignalR
    const connection = new signalR.HubConnection(
    "/chathub", { logger: signalR.LogLevel.Information });
    connection.on("ReceiveMessage", (user, message) => {
    // Do something with the payload
    });
    // Send something (e.g. via button)
    connection.invoke("SendMessage", user, message).catch(err => console.error);
    // Start the connection
    connection.start().catch(err => console.error);

    View Slide

  49. Summary
    • Unifies MVC and Web APIs
    • Built-in dependency injection
    • Cloud-ready
    • HTTP Pipeline & Configuration System
    • Several hosting options
    • Help Pages via Swagger
    • Don’t forget gzip, versioning, rate limiting, …
    • SignalR enables real time connections for server à client communication scenarios
    ASP.NET Core

    View Slide

  50. Lightweight & cross-platform data access
    EntityFramework Core

    View Slide

  51. Overview
    • Open source implementation: https://github.com/aspnet/EntityFramework
    • Lightweight & cross-platform version of .NET’s full-fledged EntityFramework
    • Support different database providers
    • MS SQL
    • SQLite
    • Postgres
    • InMemory
    • Offers Commandline Tools
    • Code First, Database First
    • Migrations
    EntityFramework Core

    View Slide

  52. Compared to EntityFramework 6
    • EntityFramework Core does offer the following features, but some of them are still in
    development
    • Complex value types (without an ID)
    • Spatial data (geography, geometry) (in development)
    • Graphical visualization of the model (Model First) (in development)
    • Complex LINQ-Queries
    • Many-to-Many without a joining entity (in development)
    • Lazy Loading
    • Stored Procedures
    • Data Seeding (via model definition)
    • Full list available at https://docs.microsoft.com/en-us/ef/efcore-and-ef6/features
    EntityFramework Core

    View Slide

  53. NuGet Package & CLI
    • Core Package: Microsoft.EntityFrameworkCore
    • Database Provider Packages
    • MS SQL: Microsoft.EntityFrameworkCore.SqlServer
    • Postgres: Npgsql.EntityFrameworkCore.PostgreSQL
    • SQLite: Microsoft.EntityFrameworkCore.SQLite
    • CLI Tools
    • Powershell: Microsoft.EntityFrameworkCore.Tools
    • cmd/bash: Microsoft.EntityFrameworkCore.Tools.DotNet
    • Careful: cmd/bash is not installable via NuGet, only by editing .csproj directly
    EntityFramework Core

    View Slide

  54. Model
    • Working with EntityFramework Core is based on a model
    • A model is a simple class with specific attributes
    EntityFramework Core
    public class CustomerEntity
    {
    [Key]
    [DatabaseGenerated(DatabaseGeneratedOption.Identity)]
    public int Id { get; set; }
    [Required]
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }
    }

    View Slide

  55. Database Context
    • A database context (DbContext) represents a session to the database
    • Has one or multiple DbSet to query the database
    • Allows executing raw SQL queries
    EntityFramework Core
    public class SampleApplicationDbContext : DbContext
    {
    public SampleApplicationDbContext(DbContextOptions options)
    : base(options)
    {
    // Overriding constructor is necessary to make use of DbContextOptions
    }
    public DbSet Customers { get; set; }
    }

    View Slide

  56. Database Context
    • DbContext can be added to the dependency injection
    • Services can request a DbContext via constructor injection
    EntityFramework Core
    public void ConfigureServices(IServiceCollection services)
    {
    services.AddDbContext(options =>
    {
    options.UseSqlServer(Configuration.GetConnectionString("SampleApplication"));
    }
    );
    }
    public class CustomerService
    {
    public CustomerService(SampleApplicationDbContext dbContext)
    { }
    }

    View Slide

  57. Fluent API
    • Instead of using attributes to define a model, the Fluent API can be used
    • Fluent API has a richer API than the attributes for more complex scenarios
    EntityFramework Core
    public class SampleApplicationDbContext : DbContext
    {
    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
    modelBuilder.Entity()
    .HasKey(e => e.Id);
    modelBuilder.Entity()
    .Property(e => e.FirstName)
    .IsRequired();
    }
    }

    View Slide

  58. Querying
    • LINQ for database querying
    • Simple selects
    • Ordering
    • Grouping
    • Limiting
    • Can load related data
    • Eager Loading
    • Explicitly
    • Lazy Loading (soon)
    EntityFramework Core
    public class CustomerService
    {
    private readonly SampleApplicationDbContext _dbContext;
    public CustomerService(SampleApplicationDbContext dbContext)
    {
    _dbContext = dbContext;
    }
    public ICollection List()
    {
    return _dbContext.Customers
    .OrderBy(c => c.Id)
    .ToList();
    }
    }

    View Slide

  59. Saving
    • Tracks changes on entities per default
    • Writes back changes to the database when the DbContext is saved
    EntityFramework Core
    public void Update()
    {
    var entity = _dbContext.Customers.First();
    entity.FirstName = "Max";
    _dbContext.SaveChanges();
    }

    View Slide

  60. Saving
    • Related data is also saved on change tracked entities
    • Use AsNoTracking() when querying to not track changes, e.g. for read-only scenarios
    EntityFramework Core
    public ICollection List()
    {
    return _dbContext.Customers
    .AsNoTracking() .ToList();
    }

    View Slide

  61. Transactions
    • SaveChanges() calls done as a transaction by default
    • Custom transaction can be create by using DbContext.Database.BeginTransaction()
    EntityFramework Core
    using (var transaction = _dbContext.Database.BeginTransaction())
    {
    try
    {
    _dbContext.Customers.Add(new CustomerEntity { FirstName = "Max" });
    _dbContext.SaveChanges();
    _dbContext.Customers.Add(new CustomerEntity { FirstName = "Erika" });
    _dbContext.SaveChanges();
    transaction.Commit();
    }
    catch (Exception e)
    {
    // TODO: Handle exception
    }
    }

    View Slide

  62. Migrations
    • Needs the PowerShell or cmd/bash tools installed
    • Add Migrations via
    • PowerShell: Add-Migration MigrationName
    • cmd/bash: dotnet ef migrations add MigrationName
    • Custom database initializer is needed to actually apply the migrations on startup
    EntityFramework Core
    public class DatabaseInitializer
    {
    public void Migrate()
    {
    _dbContext.Database.Migrate();
    }
    }

    View Slide

  63. Summary
    • Cross-platform version of .NET’s EntityFramework
    • Not all features are supported yet
    • Offers PowerShell and cmd/bash toolings
    • Supports transactions & migrations
    • Support multiple database providers and an InMemory database for testing
    EntityFramework Core

    View Slide

  64. Better safe than sorry
    Unit & Integration Testing

    View Slide

  65. Overview
    • Well-known „.NET toolbelt“ can be used
    • Xunit, Nunit
    • Moq
    • Fluent Assertions
    • EntityFramework Core can be mocked for unit testing
    • Additionally it has an in-memory provider for integration testing
    Unit & Integration Testing

    View Slide

  66. Unit Testing Sample
    Unit & Integration Testing
    public class TodoServiceUnitTests
    {
    [Fact]
    public void GetAllLists_should_return_lists()
    {
    // in-memory sample-data data
    IQueryable lists = new List() { { Name = "First list" } }.AsQueryable();
    var mockSet = new Mock>();
    mockSet.As>().Setup(m => m.Provider).Returns(lists.Provider);
    // ... more mock setup
    var mockContext = new Mock();
    mockContext.Setup(c => c.Lists).Returns(mockSet.Object);
    var sub = new TodoService(null, mockContext.Object);
    var actual = sub.GetAllLists();
    actual.Should().NotBeEmpty().And.HaveCount(2);
    actual.First().Value.Should().Be("First list");
    }
    }

    View Slide

  67. The cloud is just someone else‘s computer
    Deployment

    View Slide

  68. Docker
    • Docker is just one of multiple possibilities for deploying the application
    • Runs on
    • Microsoft Azure: Container Registry, Container Services, Container Instances
    • Amazon EC2 Container Services
    • Google Cloud Platform
    • IBM Bluemix Container Services
    • Runnable via
    • Simple Azure (Linux-based) Web Apps
    • Docker Swarm
    • Kubernetes
    Deployment

    View Slide

  69. Docker in Azure
    • Multi-step Docker Image
    • Build Image
    • Runtime Image
    • Runtime Image will be published to container host
    • Fully Continuous Delivery compatible
    Deployment
    # Build Image
    FROM microsoft/dotnet:2.1-sdk-alpine AS build-env
    WORKDIR /app
    COPY *.csproj ./
    RUN dotnet restore
    COPY . ./
    RUN dotnet publish -c Release -o out
    # Build runtime image
    FROM microsoft/dotnet:2.1-aspnetcore-runtime-alpine
    WORKDIR /app
    COPY --from=build-env /app/out .
    ENTRYPOINT ["dotnet", “MyApplication.dll"]

    View Slide

  70. Summary
    • .NET Standard makes it easier to create multi-targeting code (replacing PCLs)
    • .NET Standard 2.0 can target existing .NET code to reuse your existing business logic
    • ASP.NET Core provides a cross-platform possibility for MVC & Web APIs
    • ASP.NET Core is cloud-ready and offers a customizable HTTP pipeline
    • EntityFramework Core provides cross-platform and cross-database capabilities
    .NET Core & ASP.NET Core & EntityFramework Core

    View Slide

  71. .NET Standard MSDN
    https://docs.microsoft.com/en-us/dotnet/articles/standard/library
    Introducing .NET Standard
    https://blogs.msdn.microsoft.com/dotnet/2016/09/26/introducing-net-standard/
    .NET Core MSDN
    https://docs.microsoft.com/en-us/dotnet/articles/core/
    ASP.NET Core MVC MSDN
    https://docs.microsoft.com/en-us/aspnet/core/mvc/overview
    ASP.NET Core Web API MSDN
    https://docs.microsoft.com/en-us/aspnet/core/mvc/web-api/
    EntityFramework Core MSDN
    https://docs.microsoft.com/en-us/ef/
    Resources

    View Slide

  72. Thank you! Questions?
    Repository
    Sebastian Gingter Manuel Rauber
    @PhoenixHawk @manuelrauber
    Consultant Consultant
    https://github.com/thinktecture/api-ms-summit-spring-2019-services-dotnetcore

    View Slide