Gill Cleeren Mobile Architect Snowball Building a RESTful API with ASP.NET Core Web API
COVERED TOPICS  ASP.NET Core & ASP.NET Core API  Creating an API from scratch  Dependency injection  Entity Framework Core  Logging  Content Negotiation  Tooling  And much more!
WHY DO WE NEED API’S IN THE FIRST PLACE?
Typical web apps are synchronous
SLOW… WHY?
SORRY, WE’RE
HELLO ASP.NET CORE
ASP.NET CORE “ASP.NET Core is a new open-source and cross-platform framework for building modern cloud based internet connected applications, such as web apps, IoT apps and mobile backends.” source: https://docs.microsoft.com/en-us/aspnet/core
ASP.NET CORE  Built on top of .NET Core  Cross-platform  Windows, Mac & Linux  Not tied to original .NET framework
WHAT DOES ASP.NET CORE BRING US?  Unification between MVC and Web API  Dependency Injection  Modular HTTP request pipeline  Based on NuGet  Cloud-ready  IIS or self-host  Open source  Cross-platform  New tooling  Better integration of client-side frameworks  Command-line support
MAIN NEW FEATURES IN ASP.NET CORE  Startup class  Dependency Injection  Middleware  New type of configuration  Hosting  Identity
FILE  NEW PROJECT
FILE  NEW PROJECT
PROJECT STRUCTURE  Important things to note  Dependencies  wwwroot  json files  bower.json (MVC only)  appsettings.json  Program.cs  Startup.cs  Regular folders  Controllers  Views (MVC only)
WWWROOT (MVC)
DEPENDENCIES
MANAGING DEPENDENCIES: CSPROJ FILE
MANAGING DEPENDENCIES: CSPROJ FILE
DEMO File  New Project
BASE CONCEPTS IN ASP.NET CORE  An ASP.NET Core app is a console app that creates a web server in its Main method  MVC will get added soon!
STARTUP CLASS  The UseStartup method on WebHostBuilder specifies the Startup class for your app  Use to define request handing pipeline and services for the app are configured  Contains 2 important methods  Configure: used to configure the middleware in the request pipeline  ConfigureServices: defines services that we’ll be using in the app  MVC, EF, Logging…
STARTUP CONSTRUCTOR IN STARTUP CLASS
STARTUP CLASS  Note: this is dependency injection at work public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { } }
SERVICES IN ASP.NET CORE MVC  Service is a component for usage in an application  Are injected and made available through DI  ASP.NET Core comes with built-in DI container  Can be replaced if needed  Supports more loosely-coupled architecture  Components are available throughout the application using this container  Typically, things like logging are injected this way
CONFIGURESERVICES
CONFIGURESERVICES public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); // Add application services. services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>(); }
MIDDLEWARE  Request pipeline gets composed using middleware  ASP.NET Core middleware performs asynchronous logic on an HttpContext and then either invokes the next middleware in the sequence or terminates the request directly  Typically used by adding a reference to a NuGet package  Followed by calling UseXXX() on IApplicationBuilding in the Configure method
MIDDLEWARE  ASP.NET Core comes with lots of built-in middleware  Static file support  Routing  Authentication  MVC…  You can also write your own middleware
REQUEST PIPELINE  Requests are passed from delegate to delegate  Can be short-circuited  Static files (MVC)  Keeps load on server lower
CONFIGURE  Ex: UseMvc  Adds routing  Configures MVC as default handler  Parameters are injected using DI
ORDERING MIDDLEWARE COMPONENTS  Order in which they are added will decide how they are called!  Critical for security, performance and even functionality  Default order  Exception/error handling  Static file server  Authentication  MVC public void Configure(IApplicationBuilder app) { app.UseExceptionHandler("/Home/Error"); // Call first to catch exceptions // thrown in the following middleware. app.UseStaticFiles(); // Return static files and end pipeline. app.UseIdentity(); // Authenticate before you access // secure resources. app.UseMvcWithDefaultRoute(); // Add MVC to the request pipeline. }
THE STARTUP OF THE APPLICATION Application starting Startup class ConfigureServices method Configure method Ready for requests
DEMO Application configuration
CREATING AN API WITH ASP.NET CORE WEB API
THE MVC PATTERN Controller View Model Request Update Update Get data from
WHEN USING AN API… Controller JSON Model Request
CREATING AN API CONTROLLER  API controller == MVC controller that gives access to data without HTML  Data delivery is most often done using REST  Representational State Transfer  REST is based on HTTP verbs and URLs/resources  HTTP verb specifies what we want to do  Resource represent what we want to use, which objects  Format is JSON (preferred) or XML
A VERY SIMPLE CONTROLLER  Similar to controllers in plain ASP.NET Core MVC  Base ApiController is no more  All is now in one class: Controller  You can (and should) now have mixed classes public class PieController : Controller { ... }
A VERY SIMPLE ACTION METHOD public class PieController : Controller { public JsonResult Get() { var pies = new List<Pie>() { ... }; return new JsonResult(pies); } }
AND THE RESULT IS…
WE’LL NEED SOME ROUTING…
ROUTING  Routing will allow us to match the request to the action method on the Controller  2 options exist  Convention-based routing  Useful for MVC applications  Similar to “old” model  Attribute-based routing  More natural fit for APIs
WORKING WITH THE ROUTE  Convention is starting the route with api, followed by name of the controller  Can be reached using /api/pie
HTTP METHODS  Routes are combined with HTTP methods  Used to indicate which action we want to do  Each will have a result, a payload  Response code is used to report on the outcome of the operation
HTTP METHODS Verb Method Result GET /api/pie Gets collection of all pies GET /api/pie/1 Gets specific pie POST /api/pie Contains data to create a new pie instance, will return saved data PUT /api/pie Contains changed data to update an existing pie instance DELETE /api/pie/1 Deletes certain pie
THE RESULT: JSON
DEMO Creating a simple API
TESTING AND USING YOUR CONTROLLERS
TESTING YOUR CONTROLLERS  Different options  Fiddler  PostMan  Swashbuckle  NuGet package that will add API description page and allow for testing
DEMO Testing the API using Postman
USING DEPENDENCY INJECTION AND REPOSITORIES
DEPENDENCY INJECTION  Type of inversion of control (IoC)  Another class is responsible for obtaining the required dependency  Results in more loose coupling  Container handles instantiation as well as lifetime of objects  Built-in into ASP.NET Core  Can be replaced with other container if needed
DEPENDENCY INJECTION DI Container Controller OrderService IOrderService
REGISTERING DEPENDENCIES public void ConfigureServices(IServiceCollection services) { services.AddSingleton<ISomethingService, SomethingService>(); // Add framework services. services.AddMvc(); }
REGISTERING DEPENDENCIES  AddSingleton  AddTransient  AddScoped
DEPENDENCY INJECTION IN CONTROLLER  Constructor injection: adds dependencies into constructor parameters public class PieController : Controller { private readonly ISomethingService _something; public PieController(ISomethingService something) { _something = something; } }
“ ” USE A REPOSITORY TO SEPARATE THE LOGIC THAT RETRIEVES THE DATA AND MAPS IT TO THE ENTITY MODEL FROM THE BUSINESS LOGIC THAT ACTS ON THE MODEL. THE BUSINESS LOGIC SHOULD BE AGNOSTIC TO THE TYPE OF DATA THAT COMPRISES THE DATA SOURCE LAYER
THE REPOSITORY public class PieRepository : IPieRepository { private List<Pie> _pies; public PieRepository() { _pies = new List<Pie>() { ... }; } public IEnumerable<Pie> Pies => _pies; }
REGISTERING THE REPOSITORY public void ConfigureServices(IServiceCollection services) { services.AddSingleton<IPieRepository, PieRepository>(); }
DEMO Adding a Repository and Dependency Injection
ADDING MORE FUNCTIONALITY ON THE CONTROLLER
ACTION METHODS  Action methods need to be declared with attribute that specifies the HTTP method  Available attributes  HttpGet  HttpPost  HttpPut  HttpDelete  HttpPatch  HttpHead  AcceptVerbs: for multiple verbs on one method
ACTION METHODS  We can pass values (routing fragment)  Can be reached by combining the route with the parameter  /api/pie/{id}  Routes in general don’t contain an action segment  Action name isn’t part of the URL to reach an action method  HTTP method is used to differentiate between them
ACTION RESULTS  API action methods don’t rely on ViewResult  Instead, return data  MVC will make sure they get returned in a correct format  By default JSON  It’s possible to change this, even from the client  Media Type formatting is applied here
STATUS CODES  Status code are part of the response from the API  Used for information:  Whether or not the request succeeded  Why did it fail
STATUS CODES  MVC is good at knowing what to return  If we return null, it’ll return 204 – No Content  We can override this by returning a different IActionResult  NotFound leads to 404  Ok just sends the object to the client and returns 200
MOST IMPORTANT STATUS CODES  20X: Success  200: OK  201: Created  204: No content  40X: Client error  400: Bad request  403: Forbidden  404: Not found  50X: Server error  500: Internal server error
DEMO Completing the Controller and repository
ADDING ENTITY FRAMEWORK CORE
“ ” ENTITY FRAMEWORK (EF) CORE IS A LIGHTWEIGHT AND EXTENSIBLE VERSION OF THE POPULAR ENTITY FRAMEWORK DATA ACCESS TECHNOLOGY
ENTITY FRAMEWORK CORE  ORM  Lightweight  Cross-platform  Open source  Works with several databases  Code-first
DEMO Adding Entity Framework Core
LOGGING
LOGGING IN ASP.NET CORE  Built-in into ASP.NET Core  Available as middleware  ILogger  Provider-based model  External providers can be added if needed
BUILT-IN PROVIDERS  Console  Debug  EventSource  EventLog  Azure  …
DEMO Logging
CONTENT FORMATTING
CONTENT FORMATTING  MVC has to work out which data format it should return  Basically, which encoding to use  Can be influenced by the client request  Content format depends on  Format(s) accepted by client  Format(s) that can be produced  Content policy specified by the action  Type returned by the action  Can be hard to figure out  In most cases, the default will do
DEFAULT CONTENT POLICY  Easiest situation: client and action method define no restrictions on the format that can be used  If method returns string, string is returned to client, content-type header is set to text/plain  All other data types are returned as JSON, content-type is set to application/json  Strings aren’t returned as JSON because of possible issues  Double quoted strings: “”Hello world””  An int is simply returned as “2”
DEMO Default content policy
CONTENT NEGOTIATION  Clients will typically include an Accept header  Specifies possible accepted formats (MIME types)  Browser will send  Accept: text/html,application/xhtml +xml,application/xml;q=0.9,image/webp,*/*;q=0.8  Prefers HTML and XHTML, can accept XML and Webp  Q indicated preference (xml is less preferred)  */* indicated that all will work  But only for 0.8
CHANGING THE ACCEPT HEADER  If we ask the API for XML…  Headers Accept="application/xml"  We’ll get back json… (Thank you MVC)  MVC doesn’t know about XML at this point
XML PLEASE  Requires extra package to be included  And as always, some configuration change in the Startup class
DEMO Adding support for XML
OVERRIDING THE ACTION DATA FORMAT  We can specify the data format on the action method itself  Produces is filter  Changes the content type  Argument is the returned data format
PASSING THE DATA FORMAT USING THE ROUTE OR THE QUERY STRING  ACCEPT header can’t always be controlled from client  Data format can therefore also be specified through route or query string to reach an action  We can define a shorthand in the Startup class  xml can now be used to refer to application/xml
PASSING THE DATA FORMAT USING THE ROUTE OR THE QUERY STRING  On the action, we now need to add the FormatFilter  Upon receiving the shorthand (xml), the mapped type from the Startup is retrieved  Route can now also include the format (optional)  If combined with Produces and other type is requested, 404 is returned
REAL CONTENT NEGOTIATION  RespectBrowserAcceptHeader: if true, accept header will be fully respected  ReturnHttpNotAcceptable: if no format can be found, 406 – Not Acceptable is returned
DEMO Content Negotiation
VERSIONING THE API
VERSIONING AN API  Something that’s often forgotten by developers…  Versioning is required  Clients evolve, API needs to follow as well  Old versions often still required  Many ways exist  URI versioning  Header versioning  Accept-headers versioning  …
VERSIONING AN API  Open-source package  microsoft.aspnetcore.mvc.versioning  Supports  ASP.NET Web API  ASP.NET Web API with oData  ASP.NET Core  Added using  services.AddApiVersioning();
VERSIONING USING QUERYSTRING PARAMETER VERSIONING namespace My.Services.V1 { [ApiVersion("1.0")] public class HelloWorldController : Controller { public string Get() => "Hello world v1.0!"; } } namespace My.Services.V2 { [ApiVersion("2.0")] public class HelloWorldController : Controller { public string Get() => "Hello world v2.0!"; } }
VERSIONING USING URL PATH SEGMENT [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] public class HelloWorldController : Controller { public string Get() => "Hello world!"; } [ApiVersion("2.0")] [ApiVersion("3.0")] [Route("api/v{version:apiVersion}/helloworld")] public class HelloWorld2Controller : Controller { [HttpGet] public string Get() => "Hello world v2!"; [HttpGet, MapToApiVersion( "3.0" )] public string GetV3() => "Hello world v3!"; }
VERSIONING USING HEADER public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => o.ApiVersionReader = new HeaderApiVersionReader("api-version")); }
DEMO Versioning the API
DEPLOYING THE API
DEPLOYMENT OPTIONS  Azure  IIS  Docker  Linux
DEPLOYING TO AZURE  Account via portal.azure.com  Create an Azure App Service  SQL Server database if using a DB  Visual Studio Publish from Solution Explorer
DEMO Deploying the API to an Azure App Service
SUMMARY
QUESTIONS?
THANKS!
Gill Cleeren Mobile Architect Snowball Building a RESTful API with ASP.NET Core Web API

ASP.NET Core Web API documentation web application

  • 1.
    Gill Cleeren Mobile Architect Snowball Buildinga RESTful API with ASP.NET Core Web API
  • 4.
    COVERED TOPICS  ASP.NETCore & ASP.NET Core API  Creating an API from scratch  Dependency injection  Entity Framework Core  Logging  Content Negotiation  Tooling  And much more!
  • 5.
    WHY DO WENEED API’S IN THE FIRST PLACE?
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
    ASP.NET CORE “ASP.NET Coreis a new open-source and cross-platform framework for building modern cloud based internet connected applications, such as web apps, IoT apps and mobile backends.” source: https://docs.microsoft.com/en-us/aspnet/core
  • 11.
    ASP.NET CORE  Builton top of .NET Core  Cross-platform  Windows, Mac & Linux  Not tied to original .NET framework
  • 12.
    WHAT DOES ASP.NETCORE BRING US?  Unification between MVC and Web API  Dependency Injection  Modular HTTP request pipeline  Based on NuGet  Cloud-ready  IIS or self-host  Open source  Cross-platform  New tooling  Better integration of client-side frameworks  Command-line support
  • 13.
    MAIN NEW FEATURESIN ASP.NET CORE  Startup class  Dependency Injection  Middleware  New type of configuration  Hosting  Identity
  • 14.
    FILE  NEWPROJECT
  • 15.
    FILE  NEWPROJECT
  • 17.
    PROJECT STRUCTURE  Importantthings to note  Dependencies  wwwroot  json files  bower.json (MVC only)  appsettings.json  Program.cs  Startup.cs  Regular folders  Controllers  Views (MVC only)
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
    BASE CONCEPTS INASP.NET CORE  An ASP.NET Core app is a console app that creates a web server in its Main method  MVC will get added soon!
  • 24.
    STARTUP CLASS  TheUseStartup method on WebHostBuilder specifies the Startup class for your app  Use to define request handing pipeline and services for the app are configured  Contains 2 important methods  Configure: used to configure the middleware in the request pipeline  ConfigureServices: defines services that we’ll be using in the app  MVC, EF, Logging…
  • 25.
  • 26.
    STARTUP CLASS  Note:this is dependency injection at work public class Startup { public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { } }
  • 27.
    SERVICES IN ASP.NETCORE MVC  Service is a component for usage in an application  Are injected and made available through DI  ASP.NET Core comes with built-in DI container  Can be replaced if needed  Supports more loosely-coupled architecture  Components are available throughout the application using this container  Typically, things like logging are injected this way
  • 28.
  • 29.
    CONFIGURESERVICES public void ConfigureServices(IServiceCollectionservices) { // Add framework services. services.AddDbContext<ApplicationDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser, IdentityRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); // Add application services. services.AddTransient<IEmailSender, AuthMessageSender>(); services.AddTransient<ISmsSender, AuthMessageSender>(); }
  • 30.
    MIDDLEWARE  Request pipelinegets composed using middleware  ASP.NET Core middleware performs asynchronous logic on an HttpContext and then either invokes the next middleware in the sequence or terminates the request directly  Typically used by adding a reference to a NuGet package  Followed by calling UseXXX() on IApplicationBuilding in the Configure method
  • 31.
    MIDDLEWARE  ASP.NET Corecomes with lots of built-in middleware  Static file support  Routing  Authentication  MVC…  You can also write your own middleware
  • 32.
    REQUEST PIPELINE  Requestsare passed from delegate to delegate  Can be short-circuited  Static files (MVC)  Keeps load on server lower
  • 33.
    CONFIGURE  Ex: UseMvc Adds routing  Configures MVC as default handler  Parameters are injected using DI
  • 34.
    ORDERING MIDDLEWARE COMPONENTS Order in which they are added will decide how they are called!  Critical for security, performance and even functionality  Default order  Exception/error handling  Static file server  Authentication  MVC public void Configure(IApplicationBuilder app) { app.UseExceptionHandler("/Home/Error"); // Call first to catch exceptions // thrown in the following middleware. app.UseStaticFiles(); // Return static files and end pipeline. app.UseIdentity(); // Authenticate before you access // secure resources. app.UseMvcWithDefaultRoute(); // Add MVC to the request pipeline. }
  • 35.
    THE STARTUP OFTHE APPLICATION Application starting Startup class ConfigureServices method Configure method Ready for requests
  • 36.
  • 37.
    CREATING AN APIWITH ASP.NET CORE WEB API
  • 38.
    THE MVC PATTERN Controller ViewModel Request Update Update Get data from
  • 39.
    WHEN USING ANAPI… Controller JSON Model Request
  • 40.
    CREATING AN APICONTROLLER  API controller == MVC controller that gives access to data without HTML  Data delivery is most often done using REST  Representational State Transfer  REST is based on HTTP verbs and URLs/resources  HTTP verb specifies what we want to do  Resource represent what we want to use, which objects  Format is JSON (preferred) or XML
  • 41.
    A VERY SIMPLECONTROLLER  Similar to controllers in plain ASP.NET Core MVC  Base ApiController is no more  All is now in one class: Controller  You can (and should) now have mixed classes public class PieController : Controller { ... }
  • 42.
    A VERY SIMPLEACTION METHOD public class PieController : Controller { public JsonResult Get() { var pies = new List<Pie>() { ... }; return new JsonResult(pies); } }
  • 43.
  • 44.
  • 45.
    ROUTING  Routing willallow us to match the request to the action method on the Controller  2 options exist  Convention-based routing  Useful for MVC applications  Similar to “old” model  Attribute-based routing  More natural fit for APIs
  • 46.
    WORKING WITH THEROUTE  Convention is starting the route with api, followed by name of the controller  Can be reached using /api/pie
  • 47.
    HTTP METHODS  Routesare combined with HTTP methods  Used to indicate which action we want to do  Each will have a result, a payload  Response code is used to report on the outcome of the operation
  • 48.
    HTTP METHODS Verb MethodResult GET /api/pie Gets collection of all pies GET /api/pie/1 Gets specific pie POST /api/pie Contains data to create a new pie instance, will return saved data PUT /api/pie Contains changed data to update an existing pie instance DELETE /api/pie/1 Deletes certain pie
  • 49.
  • 50.
  • 51.
    TESTING AND USINGYOUR CONTROLLERS
  • 52.
    TESTING YOUR CONTROLLERS Different options  Fiddler  PostMan  Swashbuckle  NuGet package that will add API description page and allow for testing
  • 53.
    DEMO Testing the APIusing Postman
  • 54.
  • 55.
    DEPENDENCY INJECTION  Typeof inversion of control (IoC)  Another class is responsible for obtaining the required dependency  Results in more loose coupling  Container handles instantiation as well as lifetime of objects  Built-in into ASP.NET Core  Can be replaced with other container if needed
  • 56.
  • 57.
    REGISTERING DEPENDENCIES public voidConfigureServices(IServiceCollection services) { services.AddSingleton<ISomethingService, SomethingService>(); // Add framework services. services.AddMvc(); }
  • 58.
  • 59.
    DEPENDENCY INJECTION INCONTROLLER  Constructor injection: adds dependencies into constructor parameters public class PieController : Controller { private readonly ISomethingService _something; public PieController(ISomethingService something) { _something = something; } }
  • 60.
    “ ” USE A REPOSITORYTO SEPARATE THE LOGIC THAT RETRIEVES THE DATA AND MAPS IT TO THE ENTITY MODEL FROM THE BUSINESS LOGIC THAT ACTS ON THE MODEL. THE BUSINESS LOGIC SHOULD BE AGNOSTIC TO THE TYPE OF DATA THAT COMPRISES THE DATA SOURCE LAYER
  • 61.
    THE REPOSITORY public classPieRepository : IPieRepository { private List<Pie> _pies; public PieRepository() { _pies = new List<Pie>() { ... }; } public IEnumerable<Pie> Pies => _pies; }
  • 62.
    REGISTERING THE REPOSITORY publicvoid ConfigureServices(IServiceCollection services) { services.AddSingleton<IPieRepository, PieRepository>(); }
  • 63.
    DEMO Adding a Repositoryand Dependency Injection
  • 64.
    ADDING MORE FUNCTIONALITYON THE CONTROLLER
  • 65.
    ACTION METHODS  Actionmethods need to be declared with attribute that specifies the HTTP method  Available attributes  HttpGet  HttpPost  HttpPut  HttpDelete  HttpPatch  HttpHead  AcceptVerbs: for multiple verbs on one method
  • 66.
    ACTION METHODS  Wecan pass values (routing fragment)  Can be reached by combining the route with the parameter  /api/pie/{id}  Routes in general don’t contain an action segment  Action name isn’t part of the URL to reach an action method  HTTP method is used to differentiate between them
  • 67.
    ACTION RESULTS  APIaction methods don’t rely on ViewResult  Instead, return data  MVC will make sure they get returned in a correct format  By default JSON  It’s possible to change this, even from the client  Media Type formatting is applied here
  • 68.
    STATUS CODES  Statuscode are part of the response from the API  Used for information:  Whether or not the request succeeded  Why did it fail
  • 69.
    STATUS CODES  MVCis good at knowing what to return  If we return null, it’ll return 204 – No Content  We can override this by returning a different IActionResult  NotFound leads to 404  Ok just sends the object to the client and returns 200
  • 70.
    MOST IMPORTANT STATUSCODES  20X: Success  200: OK  201: Created  204: No content  40X: Client error  400: Bad request  403: Forbidden  404: Not found  50X: Server error  500: Internal server error
  • 71.
  • 72.
  • 73.
    “ ” ENTITY FRAMEWORK (EF)CORE IS A LIGHTWEIGHT AND EXTENSIBLE VERSION OF THE POPULAR ENTITY FRAMEWORK DATA ACCESS TECHNOLOGY
  • 74.
    ENTITY FRAMEWORK CORE ORM  Lightweight  Cross-platform  Open source  Works with several databases  Code-first
  • 75.
  • 76.
  • 77.
    LOGGING IN ASP.NETCORE  Built-in into ASP.NET Core  Available as middleware  ILogger  Provider-based model  External providers can be added if needed
  • 78.
    BUILT-IN PROVIDERS  Console Debug  EventSource  EventLog  Azure  …
  • 79.
  • 80.
  • 81.
    CONTENT FORMATTING  MVChas to work out which data format it should return  Basically, which encoding to use  Can be influenced by the client request  Content format depends on  Format(s) accepted by client  Format(s) that can be produced  Content policy specified by the action  Type returned by the action  Can be hard to figure out  In most cases, the default will do
  • 82.
    DEFAULT CONTENT POLICY Easiest situation: client and action method define no restrictions on the format that can be used  If method returns string, string is returned to client, content-type header is set to text/plain  All other data types are returned as JSON, content-type is set to application/json  Strings aren’t returned as JSON because of possible issues  Double quoted strings: “”Hello world””  An int is simply returned as “2”
  • 83.
  • 84.
    CONTENT NEGOTIATION  Clientswill typically include an Accept header  Specifies possible accepted formats (MIME types)  Browser will send  Accept: text/html,application/xhtml +xml,application/xml;q=0.9,image/webp,*/*;q=0.8  Prefers HTML and XHTML, can accept XML and Webp  Q indicated preference (xml is less preferred)  */* indicated that all will work  But only for 0.8
  • 85.
    CHANGING THE ACCEPTHEADER  If we ask the API for XML…  Headers Accept="application/xml"  We’ll get back json… (Thank you MVC)  MVC doesn’t know about XML at this point
  • 86.
    XML PLEASE  Requiresextra package to be included  And as always, some configuration change in the Startup class
  • 87.
  • 88.
    OVERRIDING THE ACTIONDATA FORMAT  We can specify the data format on the action method itself  Produces is filter  Changes the content type  Argument is the returned data format
  • 89.
    PASSING THE DATAFORMAT USING THE ROUTE OR THE QUERY STRING  ACCEPT header can’t always be controlled from client  Data format can therefore also be specified through route or query string to reach an action  We can define a shorthand in the Startup class  xml can now be used to refer to application/xml
  • 90.
    PASSING THE DATAFORMAT USING THE ROUTE OR THE QUERY STRING  On the action, we now need to add the FormatFilter  Upon receiving the shorthand (xml), the mapped type from the Startup is retrieved  Route can now also include the format (optional)  If combined with Produces and other type is requested, 404 is returned
  • 91.
    REAL CONTENT NEGOTIATION RespectBrowserAcceptHeader: if true, accept header will be fully respected  ReturnHttpNotAcceptable: if no format can be found, 406 – Not Acceptable is returned
  • 92.
  • 93.
  • 94.
    VERSIONING AN API Something that’s often forgotten by developers…  Versioning is required  Clients evolve, API needs to follow as well  Old versions often still required  Many ways exist  URI versioning  Header versioning  Accept-headers versioning  …
  • 95.
    VERSIONING AN API Open-source package  microsoft.aspnetcore.mvc.versioning  Supports  ASP.NET Web API  ASP.NET Web API with oData  ASP.NET Core  Added using  services.AddApiVersioning();
  • 96.
    VERSIONING USING QUERYSTRINGPARAMETER VERSIONING namespace My.Services.V1 { [ApiVersion("1.0")] public class HelloWorldController : Controller { public string Get() => "Hello world v1.0!"; } } namespace My.Services.V2 { [ApiVersion("2.0")] public class HelloWorldController : Controller { public string Get() => "Hello world v2.0!"; } }
  • 97.
    VERSIONING USING URLPATH SEGMENT [ApiVersion("1.0")] [Route("api/v{version:apiVersion}/[controller]")] public class HelloWorldController : Controller { public string Get() => "Hello world!"; } [ApiVersion("2.0")] [ApiVersion("3.0")] [Route("api/v{version:apiVersion}/helloworld")] public class HelloWorld2Controller : Controller { [HttpGet] public string Get() => "Hello world v2!"; [HttpGet, MapToApiVersion( "3.0" )] public string GetV3() => "Hello world v3!"; }
  • 98.
    VERSIONING USING HEADER publicvoid ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddApiVersioning(o => o.ApiVersionReader = new HeaderApiVersionReader("api-version")); }
  • 99.
  • 100.
  • 101.
    DEPLOYMENT OPTIONS  Azure IIS  Docker  Linux
  • 102.
    DEPLOYING TO AZURE Account via portal.azure.com  Create an Azure App Service  SQL Server database if using a DB  Visual Studio Publish from Solution Explorer
  • 103.
    DEMO Deploying the APIto an Azure App Service
  • 104.
  • 105.
  • 106.
  • 107.
    Gill Cleeren Mobile Architect Snowball Buildinga RESTful API with ASP.NET Core Web API