Example: quiz answers

ASP.NET Core Web API Best Practices

Core Web API Best PracticesS T E V E S M I T HA R D A L I S .C O M | @ A R D A L I S | S T E V E @ A R D A L I S .C O MW E E K LY D E V T I P S .C O M ( P O D C A S T )Web API Best Practices -@ardalisLearn More After Today1) DevIQ Core Quick ) Microsoft FREE eBook/Sample App ) Weekly Dev Tips Podcast / Newsletter ) Contact me for mentoring/training for your company/team API Best Practices -@ardalisWeb API DesignWeb API Best Practices -@ardalisRepresentational State Transfer (REST)"An architectural style for building distributed systems based on hypermedia"Open standards-basedTechnology-agnosticClient issues a request to a URIthat represents a resource; Request verbthat indicates the operationto perform on the resource. Request bodyincludes the datarequired for the APIs are stateless; each request may be handled by a different server-side API Best Practices -@ardalisURI Design ConsiderationsURI values should correspond to nouns /customers, /authors, /ordersURI values should typically be plural (when referring to collections) Again, /customers, /authors, /ordersRequests for individual resources should append an identifier: Example: /customers/1, /orders/00234 Web API Best Practices -@ardalisPrinciple of Least Asto

Not generally an issue with Web APIs REST services should (typically) return the resource in the body of POST commands, not redirect Web API Best Practices - @ardalis. What to Return? ... // Enable middleware to serve generated Swagger as a JSON endpoint. // Enable middleware to serve swagger-ui specifying the Swagger JSON endpoint. app ...

Tags:

  Services, Verse, Json

Information

Domain:

Source:

Link to this page:

Please notify us if you found a problem with this document:

Other abuse

Transcription of ASP.NET Core Web API Best Practices

1 Core Web API Best PracticesS T E V E S M I T HA R D A L I S .C O M | @ A R D A L I S | S T E V E @ A R D A L I S .C O MW E E K LY D E V T I P S .C O M ( P O D C A S T )Web API Best Practices -@ardalisLearn More After Today1) DevIQ Core Quick ) Microsoft FREE eBook/Sample App ) Weekly Dev Tips Podcast / Newsletter ) Contact me for mentoring/training for your company/team API Best Practices -@ardalisWeb API DesignWeb API Best Practices -@ardalisRepresentational State Transfer (REST)"An architectural style for building distributed systems based on hypermedia"Open standards-basedTechnology-agnosticClient issues a request to a URIthat represents a resource; Request verbthat indicates the operationto perform on the resource. Request bodyincludes the datarequired for the APIs are stateless; each request may be handled by a different server-side API Best Practices -@ardalisURI Design ConsiderationsURI values should correspond to nouns /customers, /authors, /ordersURI values should typically be plural (when referring to collections) Again, /customers, /authors, /ordersRequests for individual resources should append an identifier: Example: /customers/1, /orders/00234 Web API Best Practices -@ardalisPrinciple of Least AstonishmentTry not to surprise your client with how your API works!

2 Keep it SIMPLEKeep it CONSISTENTWeb API Best Practices -@ardalisDon tExpose Business/Data ModelAvoid coupling your Web API directly to your data/domain modelAPI design, including URIs, may not map 1:1 to domain objects or database :POST /ordersMay map to a NewOrderRequeston the server that triggers processing payment, checking inventory, sending notifications, it could just insert a record in the Orders should be able to do either without the API API Best Practices -@ardalisUse a standard URI structure for subcollectionsFor performance or other reasons, API might not return full object tree with root-level request:GET /customers/1{"id":"1","name": "Steve Smith"}To get the customer s orders:GET /customers/1/orders[{"id":"123","custome rId":"1", ..}, {"id":"234","customerId":"1", ..}]Web API Best Practices -@ardalisAvoidDeeply Nested URI StructuresOK/customers/customers/1/custo mers/1/ordersTOO MUCH/customers/1/orders/123(instead: /orders/123)/customers/1/orders/123/item s/1/products/2(instead: /products/2)Web API Best Practices -@ardalisHypermedia as the Engine of Application State (HATEOAS)Less commonly implemented aspect of REST approachCurrently no widely used standardBasic idea: Each response includes links defining available requests on a given resourceExample:GET /customers/1 Response includes customer data, as well as links to:Update the customerDelete the customerList customer ordersList customer addressesAdd an addressAdd an orderWeb API Best Practices -@ardalisHATEOAS Example -RFC 5988 (web linking)GET /customers/1 RESPONSE:{"id":"1","name": "Steve Smith","links" : ["href" : "1/orders","rel".]}

3 "orders","type" : "GET"]} API Best Practices -@ardalisStandard Verbs and BehaviorsGETF etch a resource (or collection of resources)PUTU pdate a a new a API Best Practices -@ardalisSafe and Idempotent API RequestsSaferequests are requests that do not change resources, and which can be made repeatedly without impact. Think of safe requests as read-only idempotentHTTP method can be called multiple times without changing the expected these the same?Web API Best Practices -@ardalisHTTP Verb Idempotency/SafetyVERBI dempotent?Safe?GETYesYesPUTYesNoPOSTNoNo DELETEYes*No*Decide if a DELETE for a missing id should return a 404 or not. If it returns 404, it won t be API Best Practices -@ardalisWeb API ImplementationWeb API Best Practices -@ardalisUse Model Validation (up to )Always check if performing unsafe operationsWeb API Best Practices -@ardalisUse Filters To Represent PoliciesValidate Model State using a filter (globally, per-controller, or per-action)Web API Best Practices -@ardalisUse [ApiController] in +Performs model validation automaticallyRequiresattribute routingRecommendation: Add to a base API controller classAlternately in can be applied to Startup for whole projectWeb API Best Practices -@ardalisBase ClassInherit from ControllerBase, not ControllerCreate your own BaseApiControllerlike this one (consider also adding Authorizefilter).

4 Web API Best Practices -@ardalisUse Proper HTTP Status Codes as Results200 OKRequest was successful; body has OK POST or PUT was successful; body has latest OKDELETE was successful; resource was BAD REQUESTThe request was invalid or cannot otherwise be UNAUTHORIZEDA uthorization failed or authentication details not NOT FOUNDThe URI requested or the resource requested doesn t Internal Server ErrorSomething very bad happened. Unhandled exceptions lead to API Best Practices -@ardalisWeb API ConventionsScenarioExpectedResponseGet Object with ID Object Found200 OKGet Object with ID No such object404 NotFoundCreate Object Object is valid200 OKCreate Object Object is invalid400 Bad RequestUpdate Object Object exists and new object is valid200 OKUpdateObject No such object404 Not FoundUpdate Object New object is invalid400 Bad RequestDelete Object with ID Deletion successful200 OKDelete Object with ID No such object404 Not Found or 200 OKWeb API Best Practices -@ardalisPrefer NotFoundto NullReferenceExceptionWeb API Best Practices -@ardalisPrefer NotFoundto NullReferenceExceptionWeb API Best Practices -@ardalisUse a filterto confirm existenceWeb API Best Practices -@ardalisAvoid Duplicating Data within RequestsDon t ask for an ID in the

5 Route and also in the BindingModel Unless you re going to allow updates to a resource s ID!Which value should you use? How do you decide? Best to use a model type that doesn t include the ID if it s redundantWeb API Best Practices -@ardalisUse DTOs AppropriatelyAvoidusing domain objects or data entities as your API inputs or outputs. Doing so exposes your app s internal state and can be a security riskAvoid creating DTO types that inadvertently reference non-DTO types. Tip: Look for using statements in your DTO files that shouldn t be thereIf specifying ID on DTOs, may not make sense to use for new object requests (POSTs) Consider having separate NewResourceDTOand ResourceDTOtypes ResourceDTOcan inherit from NewResourceDTOand simply add the Id propertyWeb API Best Practices -@ardalisEntity Class Used in POST Actionpublic class GuestbookEntry: BaseEntity{public string EmailAddress{ get; set; }public string Message { get; set; }public DateTimeOffsetDateTimeCreated{ get; set; } = ;}Intended behavior is only EmailAddressand Messageare sent by API Best Practices -@ardalisSecurity Issue: Data Object for APIWeb API Best Practices -@ardalisExample: Create/Update DTOspublic class NewCustomerDTO{public string Name { get; set; }public string EmailAddress{ get; set.}}

6 }}public class CustomerDTO: NewCustomerDTO{public int Id { get; set; }}Web API Best Practices -@ardalisNon-DTOs May Expose Sensitive DataWeb API Best Practices -@ardalisPost-Redirect-Get (PRG) PatternOverview Client POSTs to Server Server performs requested operation and returns a Redirect (302) to new URI Client GETs new URIThis pattern is most appropriate to MVC non-API apps. One of its primary benefits is that it eliminates browser refreshes from reissuing POST commands. Not generally an issue with Web APIsREST services should (typically) return the resource in the body of POST commands, not redirectWeb API Best Practices -@ardalisWhat to Return?Object Author, Customer, or void Automatically wrapped in a result (or Encoding-Specific return json (model); // JsonResultIActionResult( and earlier) or ActionResult<T> ( +) return Ok(model); return NotFound(); return BadRequest();Web API Best Practices -@ardalisPrefer IActionResultor ActionResult<T>Support Content NegotiationRequests can include Acceptheader specifying content they want/supportWeb API will attempt to comply with specified content formatSupport json (default) and XML:Add XML Serializerswhen adding MVC in ().)

7 AddXmlSerializerFormatters();Web API Best Practices -@ardalisContent Negotiation In ActionWeb API Best Practices -@ardalisContent Negotiation In ActionWeb API Best Practices -@ardalisDocumentation / DiscoverabilitySwagger the OpenAPIS pecificationProvide live, runtime documentation of your APIsAbility to generate client libraries to assist in consuming your API NSwag- API Best Practices -@ardalisAdding Swagger to your Web APIAdd Nuget package services in (c =>{ ("v1", new Info { Title = "My API", Version = "v1" });});Add Middleware to Configure() (next slide)Web API Best Practices -@ardalisAdding Swagger to your Web API (cont.)public void Configure(IApplicationBuilderapp){ (); // Enable middleware to serve generated Swagger as a json Enable middleware to serve swagger-uispecifying the Swagger json (c =>{ ("/swagger/v1 ", "My API V1");}); ().}

8 }Web API Best Practices -@ardalisResponse Types ProducedWeb API Best Practices -@ardalisAnalyzersWeb API Best Practices -@ardalisNSwagStudioWeb API Best Practices -@ardalisDemoW O R K I N G W I T H S WA G G E RWeb API Best Practices -@ardalisTesting Web APIsWeb API Best Practices -@ardalisKinds of TestsUnit Tests Test a single unit typically a method Only test your code, not infrastructure Limited usefulness for testing APIsIntegration Tests Test several methods and/or classes working together Useful for verifying infrastructure code works correctlyFunctional Tests Test full application stack Slowest, often most brittle, but provide greatest confidence a particular user scenario works fullyWeb API Best Practices -@ardalisWeb API Best Practices -@ardalisWeb API Best Practices -@ardalisTest APIs with TestServerInstall PackageConfigure with WebHostBuilder.

9 Use HttpClientto make requests to TestServerinstanceLearn more: API Best Practices -@ardalisExample Web API TestWeb API Best Practices -@ardalisDemoVA L I D AT I N G F I LT E RS P R O D U C E S A M E R E S U LT S A S I N L I N E C O D EWeb API Best Practices -@ardalisVersioning Web APIsWeb API Best Practices -@ardalisNo VersioningLimit updates to non-destructive wherever possibleCoordinate with clients on breaking changesWorks best with internal APIsWeb API Best Practices -@ardalisURI VersioningExample: versions work as beforeResults in multiple URIs corresponding to same resourceCan complicate HATEOAS linksCan be unwieldy if API evolves quickly/frequentlyWeb API Best Practices -@ardalisQuerystringVersioningExample: versions work as before (default to 1 if omitted)Can complicate HATEOAS linksCan be unwieldy if API evolves quickly/frequentlyWeb API Best Practices -@ardalisHeader VersioningExample: GET : 2 Previous versions work as before (default to 1 if omitted)HATEOAS links must use same headerCan be unwieldy if API evolves quickly/frequentlyWeb API Best Practices -@ardalisMedia Type VersioningExample: GET : +jsonResponse includes header indicating version providedPrevious versions work as before (default to 1 if omitted)Works well with HATEOAS links (can include MIME types)Web API Best Practices -@ardalisVersioning ConsiderationsConsider performance impact, especially for web server and proxy server caching.

10 Header and Media Type versioning is less cache friendly than other techniquesConsider whether you will version your entire API (simplest) or resource by resource (generally not recommended).Avoidmaking breaking changes to your API as much as possible. No versioning option is without its API Best Practices -@ardalisSecuring Web APIsWeb API Best Practices -@ardalisUse HTTPS(seriously, just use it)Web API Best Practices -@ardalisWindows AuthSimplestWell-knownOnly works on Windows and within an intranetWeb API Best Practices -@ardalisIdentityServer4An OpenID Connect and OAuth framework for Core Authentication ServiceSingle Sign-On SupportAccess Control for APIs, including tokens for: Server-to-Server clients Web clients and SPAs Native/Mobile appsFree, Open Source, Part of .NET FoundationLearn more: API Best Practices -@ardalisWeb Tokens (JWT)Roll your own using available packages:<PackageReferenceInclude=" " Version=" " /> <PackageReferenceInclude=" " Version=" " />Great article on this topic Authenticate user and issue token.


Related search queries