Ce diaporama a bien été signalé.
Le téléchargement de votre SlideShare est en cours. ×

Building Beautiful REST APIs in ASP.NET Core

Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Publicité
Chargement dans…3
×

Consultez-les par la suite

1 sur 27 Publicité

Building Beautiful REST APIs in ASP.NET Core

Télécharger pour lire hors ligne

Core 1.0 is the latest iteration of ASP.NET. What’s changed? Everything! Nate Barbettini, .NET Developer Evangelist at Stormpath, does a deep dive on how to build RESTful APIs the right way on top of ASP.NET Web API.

Core 1.0 is the latest iteration of ASP.NET. What’s changed? Everything! Nate Barbettini, .NET Developer Evangelist at Stormpath, does a deep dive on how to build RESTful APIs the right way on top of ASP.NET Web API.

Publicité
Publicité

Plus De Contenu Connexe

Diaporamas pour vous (20)

Les utilisateurs ont également aimé (20)

Publicité

Similaire à Building Beautiful REST APIs in ASP.NET Core (20)

Publicité

Plus récents (20)

Building Beautiful REST APIs in ASP.NET Core

  1. 1. BEAUTIFUL REST APIs in ASP.NET Core Nate Barbettini @nbarbettini recaffeinate.co .ws
  2. 2. Overview ● Why is API design important? ● HATEOAS (Hypertext As The Engine Of Application State) ● REST APIs in ASP.NET Core
  3. 3. /getAccount?id=17 Bad REST API design /getAccount?all=1&includePosts=1 /getAllAccounts /updateAccount?id=17 /createAccount /findPostsByAccountId?account=17 /accountSearch?lname=Skywalker /getAccount?id=17&includePosts=1 /getAccount?id=17&format=json /getAllAccountsJson /updateAccount?id=17&return=json /createAccountJson /accountSearch?lname=Skywalker&xml=1 /findPostsByAccountIdJSON?account=17 /getAllPosts?filter=account&id=17 /countAccounts /partialUpdateAccount?id=17 /getPostCount?id=17 /deleteUser
  4. 4. HATEOAS, yo! "A REST API should be entered with no prior knowledge beyond the initial URI (bookmark) and set of standardized media types that are appropriate for the intended audience (i.e., expected to be understood by any client that might use the API). From that point on, all application state transitions must be driven by client selection of server-provided choices that are present in the received representations or implied by the user’s manipulation of those representations." ~ Dr. Fielding Tl;dr The API responses themselves should document what you are allowed to do and where you can go. If you can get to the root (/), you should be able to “travel” anywhere else in the API.
  5. 5. Good REST API design should... ● Be discoverable and self-documenting ● Represent resources and collections ● Represent actions using HTTP verbs ● KISS!
  6. 6. Revisiting the API example /users GET: List all users POST or PUT: Create a user /users/17 GET: Retrieve a single user POST or PUT: Update user details DELETE: Delete this user /users/17/posts GET: Get the user’s posts POST: Create a post /users?lname=Skywalker Search /users/17?include=posts Include linked data
  7. 7. A specification for REST+JSON APIs The ION spec: https://github.com/ionwg/ion-doc
  8. 8. Getting a single user GET /users/17 { "meta": { "href": "https://example.io/users/17" }, "firstName": "Luke", "lastName": "Skywalker" }
  9. 9. Getting a list of users GET /users { "meta": { "href": "https://example.io/users", "rel": ["collection"] }, "items": [{ "meta": { "href": "https://example.io/users/17" }, "firstName": "Luke", "lastName": "Skywalker" }, { "meta": { "href": "https://example.io/users/18" }, "firstName": "Han", "lastName": "Solo" }] }
  10. 10. Discoverable forms GET /users { ... "create": { "meta": { "href": "https://example.io/users", "rel": ["create-form"], "method": "post" }, "items": [ { "name": "firstName" }, { "name": "lastName" } ] } }
  11. 11. Discoverable search GET /users { ... "search": { "meta": { "href": "https://example.io/users", "rel": ["search-form"], "method": "get" }, "items": [ { "name": "fname" }, { "name": "lname" } ] } }
  12. 12. The starting point (API root) GET / { "meta": { "href": "https://example.io/" }, "users": { "meta": { "href": "https://example.io/users", "rel": ["collection"], } } }
  13. 13. ● Install the .NET Core SDK - http://dot.net/core ● If you’re using Visual Studio: ○ Install the latest updates (Update 3) ○ Install the .NET Core tooling - https://go.microsoft.com/fwlink/?LinkID=824849 ● Or, install Visual Studio Code ● Create a new project from the ASP.NET Core (.NET Core) template ● Pick the API subtemplate ● Ready to run! Getting started with ASP.NET Core
  14. 14. Getting a single user GET /users/17 { "meta": { "href": "https://example.io/users/17" }, "firstName": "Luke", "lastName": "Skywalker" }
  15. 15. public class Link { public string Href { get; set; } } public abstract class Resource { [JsonProperty(Order = -2)] public Link Meta { get; set; } } Getting a single user
  16. 16. public class User : Resource { public string FirstName { get; set; } public string LastName { get; set; } } Getting a single user
  17. 17. [Route("/users")] public class UsersController : Controller { private readonly BulletinBoardDbContext _context; private readonly IUrlHelperFactory _urlHelperFactory; public UsersController( BulletinBoardDbContext context, IUrlHelperFactory urlHelperFactory) { _context = context; _urlHelperFactory = urlHelperFactory; } Getting a single user
  18. 18. [Route("{id}")] public async Task<IActionResult> GetUser(string id) { var user = await _context.Users.SingleOrDefaultAsync(x => x.Id == id); if (user == null) return NotFound(); var urlHelper = _urlHelperFactory.GetUrlHelper(ControllerContext); var url = urlHelper.Link("default", new { controller = "users", id = user.Id }); var response = new User() { Meta = new Link() { Href = url }, FirstName = user.FirstName, LastName = user.LastName }; return Ok(response); } Getting a single user
  19. 19. Getting a list of users GET /users { "meta": { "href": "https://example.io/users", "rel": ["collection"] }, "items": [{ "meta": { "href": "https://example.io/users/17" }, "firstName": "Luke", "lastName": "Skywalker" }, { "meta": { "href": "https://example.io/users/18" }, "firstName": "Han", "lastName": "Solo" }] }
  20. 20. Getting a list of users public class Link { public string Href { get; set; } [JsonProperty(PropertyName = "rel", NullValueHandling = NullValueHandling.Ignore)] public string[] Relations { get; set; } }
  21. 21. Getting a list of users public class Collection<T> : Resource { public T[] Items { get; set; } }
  22. 22. Getting a list of users public async Task<IActionResult> GetAll() { var urlHelper = _urlHelperFactory.GetUrlHelper(ControllerContext); var allUsers = await _context.Users.ToArrayAsync(); var projected = allUsers.Select(x => new User() { Meta = new Link() { Href = urlHelper.Link("default", new { controller = "users", id = x.Id }) }, FirstName = x.FirstName, LastName = x.LastName }); var response = new Collection<User>() { Meta = new Link() { Href = urlHelper.Link("default", new { controller = "users" }), Relations = new string[] {"collection"}, }, Items = projected.ToArray() }; return Ok(response); }
  23. 23. The starting point (API root) GET / { "meta": { "href": "https://example.io/" }, "users": { "meta": { "href": "https://example.io/users", "rel": ["collection"], } } }
  24. 24. Adding a root route [Route("/")] public class RootController : Controller { private readonly IUrlHelperFactory _urlHelperFactory; public RootController(IUrlHelperFactory urlHelperFactory) { _urlHelperFactory = urlHelperFactory; } public IActionResult Get() { var urlHelper = _urlHelperFactory.GetUrlHelper(ControllerContext); var response = new { meta = new Link() { Href = urlHelper.Link("default", new { controller = "root" }) }, users = new Link() { Href = urlHelper.Link("default", new { controller = "users" }), Relations = new string[] {"collection"} } }; return Ok(response); } }
  25. 25. Building and running (anywhere!) > dotnet build (...) Done. > dotnet run (...) Listening on https://localhost:5000
  26. 26. Next Steps ● Full example https://github.com/nbarbettini/beautiful-rest-api-aspnetcore ● ION draft spec https://github.com/ionwg/ion-doc
  27. 27. Thank you! Nate Barbettini @nbarbettini recaffeinate.co .ws

×