Never RESTing – RESTful API Best Practices using ASP.NET Web API - Spencer Schneidenbach

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
my name is Spencer Shannon back and I'm here to about restful api best practices using asp.net web api now if you're not a web developer if you don't use web api that's totally ok a lot of what I have what up what I talked about you can apply to using restful api s and knowing when they're good and bad or apply them later I talked a lot about a lot of theoretical stuff so before I get started I wanted to make sure that you all know that everything that I'm telling you today the slides writ links to all the things that I talk about all available at rest is net you'll also see my twitter handle at night and box at the bottom right I tweeted out a link and it'll be on every slide so if you want to take a picture now that's cool but you can see it see it down here later and then you can go to my Twitter and check it out for yourself all right so I wanted to start off by talking a little bit about why I give this talk ok so I give this talk for a couple of reasons first I think the information is good I think it's I think it's compelling and I think it's interesting but more than anything it's therapeutic this is therapy for me this is therapy because I'm an integrator it's what I do I make software talk to other software and I've used good api's but far in a way I've used way more bad api's and we're going to spend some time today making fun of those bad api's I'm gonna give you plenty of good examples and plenty of bad examples right and it's important this is an important topic to talk about because at the end of the day developers have the power of choice right if you have an application and your manager comes to you and says we'd like to integrate text messaging into your into our application you can either be a hacker and you know network together 40 Android phones and put Linux on them and then you know create your own text text messaging network could do that but you're probably going to go out and find an API to use write an API to consume and there's lots of them for text messaging you're going to go out and you're going to compare and you're going to compare all of these and you're going to look for a few different things right off the bat right you're going to look for how quickly is it to go from 0 to make magic happen and you're going to hear me say that a lot make magic happen because when you make an HTTP call and then you look at your phone and you see a text message it's kind of a cool feeling it kind of feels like magic right that's awesome you're going to find out how quickly it is you go from 0 to make magic happen how quickly can I get things done next thing you're going to look for is how quickly is it for me to how easy is it for me to go and learn stuff more about your API and manage problems or manage exceptions right because inevitably you'll probably make a bad call here there we all do I certainly do and so you're going to want to know how can I solve those problems right we're essentially looking for good documentation and then you're going to look at the long term benefit because you're a discerning developer you want your company to do well right so you're going to probably look for things like uptime or talk about things like cost you're probably going to look at the cost to compare the two and this is really important because at the end of the day you're going to go to your manager and you're going to say hey I found these text messaging platforms I found these three text messaging platforms that we could use and this one that I found immediately I could get be productive right away so you're not I'm not spending a lot of time on this they're great documentation they have a great support line and the costs are similar and your managers probably gonna look at you and say ok and you've become a customer for them and that was in your power because at the end of the day you have the power of choice right you can choose to consume that API now you may do five cents worth of text messaging you could do 55 thousand dollars worth of text messaging or pound from where I am right I know that I integrated text messaging at at a client of mine a while ago and they spend thousands a month and a large part of the decision was mine to figure out what API is going to provide the best short and long-term benefits right now think about that that's on one side that's as a consumer but think about the other side if you have an application that you work on that you need to provide an API for what is it going to be what is it going to take to create something that is better than the competition right you're going to be on the flip side of that you're going to say what can I do to make my API awesome make it well-documented make sure that it works make sure that it's obvious and accessible right to developers so there's two sides of that coin because at the end of the day API design is user experience for developers now I thought of that yesterday and I hurriedly typed it into google like oh this is a cool thought and then like I found out a hundred other people had said this already so I'm pretty sure I read that like six months ago and thought oh this is original idea but it really was a really made sense to me because if you're making an application a web application WinForms whatever you're going to keep your user in mind because you want them to have a good experience you're going to make sure that the form is laid out properly and at the button there in the right place and that they have good visual cues to make sure that they're progressing to the application naturally and you want to do the same thing and you want to have the same thing done for you when looking at or crafting an API it's the same principle user experience for developers because it's not hard I mean we're not we're not shy folks right we're not shy people if something's wrong with it we're going to say something right I think this quote does a good job of summing it up you don't make usability a priority you'll never have to worry about scalability which essentially means like if nobody wants to use your API because it sucks that bad then you're not going to have to worry about how quickly you can scale up 40 Azure servers to handle the additional traffic cause it's probably not going to exist right there here are some common schemes in this talk there's a few common things you're going to see over and over again you're going to see these you're going to see a green checkmark and a red X you're going to see this a lot the green checkmarks is a good guideline then the red X is something that maybe you shouldn't do or maybe you should avoid now these aren't hard and fast rules nothing that I'm telling you is but for 90% of them you're going to put you're going to apply 90% of what I tell you probably to your API and it's going to work for you there may be one or two exceptions here and there and that's okay you can manage by exception a little bit sure you're also going to hear me talk about simple is not easy making something that's really simple for your consumers to use is not an easy task crafting good so yes you could make you could make an API you can do a file new project in Visual Studio and make an API pretty quickly and then install a package that displays help Docs for that API right and that's good you can do that in like 10 minutes right it's quick but it's not enough because you're going to need to talk about authentication you're going to need to talk about exception handling you're going to need to document what weird little things about your API exist right crafting good documentation takes time and it takes thoughtfulness and it's not easy right making an API that's consistent consistent from endpoint to endpoint you make sure that you use put requests every time you want an update an object right having those conversations with your team and with your manager that takes time and it takes thoughtfulness and it's not easy but it's so critical if you want people to use your application and use your API you have to make it simple for them but simple is not easy you're going to hear me say that a lot I'm also here to tell you there's no silver bullet anybody who stands in front of one of these stages and says this is the this is the way and the light you know you ought to think twice about listening to them because I've never found that to be true there's good ideas there's bad ideas there's some times when bad ideas are good ideas right so most of what I'm telling you is applicable it's awesome it's good information but you're going to have your own exception and like I said there's no silver bullet there's no magic answer I can't tell you that there is one way one light right so we need to talk about we're going to talk about restful api is we ought to talk about what rest is Right rest stands for representational state transfer and it was described in a paper by a guy named Roy fielding he did it for his PhD dissertation and it essentially describes the architecture that is the web okay it just it essentially it's not tied to a protocol and it's not tied to a particular format right it's just a set of constraints a set of things that if you have these things in common with a system it can be considered a restful system and here's what they are we have six constraints we have the client-server constraint which means mainly just specifies that there's a client and there's a server that's it we have the cashable constraint which means that a response from a server can define itself as cashable or not it doesn't have to be but it can define itself as cashable there's the statelessness one how many folks are asp.net users ok ceremony how many of you are ASP now that web forms users okay come on now if there's that many hands you got to raise them up I know there's more of you and there you're shy I still use it too it's okay all right web forms is all right it's at its time I still use it right and when you use web forms you store things you store data between page requests and sessions right and then is stored on the server you session state all the things that is decidedly not stateless stateless means that all the state that's contained for is for a given web request is contained within the request itself right so the request sends all the information in a purely restful system the the server does not store anything right all the data that it needs is made in the request a system can be layered which Smith simply means that a client can make a request and it could come from the response to that request could come from the web server a load balancer a cache server a CDN and it doesn't really care and it the client doesn't care as long as it gets its information code on demand is the only optional constraint and it simply means that at demand a server can send additional code from itself to the client in order to enhance the experience or change the experience the easiest example of that being JavaScript right then there's the uniform interface constraint which itself is made up of four constraints which are important to talk about so we're going to talk about resource identification is the first thing that means that a given resource can be identified by a URI right a URI or a URL right and so when you make that request the server goes and it gives you back some data in this case I'm making a request for employee 1 2 3 4 and I'm getting back jacent object with the first name in the last name right and it's important to note that these are representations of the data these aren't these aren't the data itself right it's not if this comes from a sequel server database you know it's not the API is not telling you oh this is a sequel server and here's the table that it lives in and here's the row number and here's every attribute on that right it doesn't have any of that information it doesn't give you back that it gives you back a representation but that's okay because representations have meaning and those representations can be used to manipulate the resources on the server right so if you did pick that and you change the name and you send a put request to the server you can change in theory change via change the employee object content is self descriptive which means that the server tells the client what kind of content is being sent back it could be Jason it could be XML it could be a CSS file it could be HTML right the point is is that it described so it typically describes itself in HTTP inside of the the the content type header inside of the response right then the final one is Haiti OS or hyper media as the engine of application state which is important to talk about because in the restful system a client doesn't know everything about what's going on in the server right if you go to google.com the client is getting information from Google to say I'm going to navigate to the I'm going to navigate to maps or I want to navigate to the shopping at the shopping area of Google or I want to do a Google search the client doesn't know all that stuff intrinsically the server provides all the information that it needs that the client needs to navigate that's Katie OS and we're going to talk about how that applies to restful api s okay speaking of rest what's the restful api right a restful api is just an api that follows the rest architecture which I know is probably mind-blowing but really is that simple but the term is a little bit been co-opted it's been kind of kind of brought on a 10-2 taking a life of its own right because rest isn't tight remember rest is a set of constraints it's not a protocol it's not a it's not a tied to a particular format right it's not tied to Jason it's not even tied to HTTP now granted most restful systems are HTTP systems but they're not tied together and when people say restful api usually what they mean is adjacent an HTTP api that returns Jason or sometimes XML and that's what people think for the purposes of this talk we're going to talk as if we're going to go with the the common definition or the peep the well understood definition when I say restful api I'm just going to refer to an HTTP API that probably returned some kind of JSON or XML we're going to use JSON and all of our examples so we're gonna stick with that just a just for the sake of clarity right so I'm here to tell you though you there's pragmatism involved right a purely restful api does not make it a good api write an api that strictly follows the rest standard now the rest constraint model does not make it a good HTTP api okay or a good restful api and i'll give you an example hey Theo Oz is a perfect example hypermedia is the engine of application State so a lot there's a lot of debate out there whether adjacent API or any API in general should send back links to related content inside of the JSON response so for example if you make a request for a customer a customer if you're an accounting system has invoices associated with it right so you might send back a link to say here's where you would get those invoices right you'd get you it would send back that link in the in the header or sorry in the response but that has really limited usefulness because from an API consumption standpoint you probably need the invoice API you probably already know how to access it but that's a purely restful thing so if they say you know what we've got to do pure rest we mean it can't be a RESTful API without haiti hola so now we have to spend all this time and by the way that's not an easy thing to do to implement on an AP HTTP or a restful api right it's not it takes a lot of extra work and what we have to wait we have to because it's restful but if you get everything else wrong if you're if it's poorly documented there's a lot of downtime right then your api your api is probably not good right so I'm here to tell you to do what makes sense and throw everything else out okay now let me ask you is that vague enough for you right like that seems pretty vague that's not very helpful and it's mainly because again there's no silver bullet there's no ant there's no one way one path what I say works for me for most gates for the most part when I design API it may not work for you right so we're going to treat the API we're going to talk about how to build an API now the restful api let's get to building it or designing it right we're going to talk about the design process now I'm going to talk about it as if it's siloed to design implement document maintain in reality you're probably doing all of these things at once right you're probably iterating and there's probably one big circle right but for the sake of this talk we'll just talk about these in the siloed way right all right I've been practicing so when it comes to API design I have one rule okay I actually have two rules but that sounds a lot cooler and then I can put the Dark Knight up on the slide right and it's keep it simple stupid or if you're nice keep it simply keep it stupidly simple right and and simple isn't easy what we're going to talk about some ways that you're going to make you can make it simple and again our Navy but you want people to use your API right so first rule keep it simple don't be creative let me give you an example of creative so when you're making an HTTP request to a resource it's very common to get back some kind of Eric or some kind of response code other than just 200 to say everything's good right you might send a bad request to an API and they say actually you're missing the first name we're going to send 400 bad request one example of creative is I know of an API where every single call that you make returns 200 okay and the body of the robada of the response actually contains whether or not there was a problem with that response right it'll actually contain whether or not there was an error that API is also managed by a company called Facebook so they can have they could be creative right they can be a little creative but for the most part you shouldn't be should follow the general rules and general guidelines that I laid out do what developers expect it's the bottom line provide what is necessary and no more and no less now this is another example of it's really hard simple is not easy right so but there's some general rules so if you're an accounting application and you have an employee end point and you want to return to list of employees it's likely you don't want to return their social security number appearance from the United States I don't know they have an equivalent here I'm sure they do some kind of identifying number that's important that is pretty sensitive information that you don't want to send back on the other hand you want to make sure that you send back enough information about that employee to be useful right you don't want to leave out their first name right that wouldn't make a lot of sense but knowing what this looks like can be really hard again simple is not easy so you have to provide enough information for your consumer for the information be useful right and then use a handful of HTTP status codes the best API is that I consume used less than 10 right there's about a hundred plus HTTP status codes there's even one called I'm a little teapot and I'm not making that like for 18 or something you could use that one but nobody does and you shouldn't be there and you should just use a subset use a good subset right and he a few that you could use that are good examples 200 okay you send it back with a get request to say everything's cool here's your response right everything's good 201 created when you do a post request and you create an object right you could send back 201 created to say yep everything's good your resources created 400 bad request another common one and I would argue the most important when doing integration work or doing API work because if there's an exception if there's a problem getting this request and everything around it right the bad 400 bad request getting that response correct is very critical it's just basically a way of saying your request wasn't any good just change if and ideally it would tell you how to change it and then send it back right and then it'll be good and you can get 200 ok and move on with your life 404 not found of course if a Reese if you're asking for an employee that doesn't exist 2 3 4 5 sent back for form and then 401 and 403 unauthorized and forbidden which folks tend to get mixed up right 401 unauthorized says I don't know who you are 403 forbidden says I know who you are and you can't do that right you can't look at that social security number here's an example so this is my favorite part these are the part where I get to tell stories stories that are real these are things every example that I'm showing you of a bad API is an example that comes from a real experience ok so let's talk about keeping it simple in the context of this so there's an API that I interact with where every one of their objects has a separate has a name ID and that name ID points to a separate ID on a name resource little literally only returns an ID in a string with the name right so in order for me to get the complete picture of this customer I either have to do two requests right or n plus 1 request if I'm getting a list of customers then I have to do if I get a list of customers and then I have to do to get the names of that that's horrible why would you make me do that that's not keeping it simple that's awful that's two requests per get and if I'm making the request because the opposite is true if I'm trying to create that customer I have to create a name object first and then I have to create the customer that what what's the point why would you make me do that why would you make me do two requests for every seeing one of your objects awful but the bottom line is don't let your specific implementations leak into your abstraction because it's ibadah at the end of the day an API is an abstraction right it's an abstraction over your system and a lot of people say that abstractions leak things like enemy framework right that are good Oh RM tools but they're leaky because they try to cover up all the you know parts of sequel server that nobody wants to know so usually it's they say abstractions are leaky but the others true - they've let their implementation leak into their API because I happen to know I asked them I they said oh yeah we store names in the separate table I said okay I can't really criticize that they probably have a very good reason actually for this particular company they probably don't they probably have a very good reason or if they thought they had a good reason for doing that so I'm not criticizing their implementation I'm criticizing the fact that they've not kept it simple for me as their consumer I'd much rather see this right just one request one post request or get requests to get the name and then oh you know the developer on the other end says but but but then I have to like manage the name object myself yeah yeah make it simple you want to make it simple on me you don't want to make it hard I'd much rather see something like this right wouldn't you you want to make two requests for every object I don't how about this I've put three words up on the screen theory Anakin threshold I've given I've told you nothing about them you know they're English word right and not American words they're English words but I didn't tell you anything about them I just put them on the screen and I just expect you to know or don't what they are what if I told you that and this is true this is the name of my former neighbors kids okay how would you know that unless I told you first of all it's really weird okay they also have lilia but lily is like a normal name right it's like the most normal of the names right the examples not nearly as funny with her first but I didn't tell you this I didn't give you any context I didn't give you any context up front you're left wondering what the words mean how does that tie into this I'll give you this okay so I put four more words on the screen and as a developer you look at that as engineer you say okay those kind of mean the same thing like inactive and deleted or inactive and retired that kind of similar so maybe they describe different states of an object right it's either inactive or deleted or visible or retired right what if I told you that on several one of these several objects these are four separate properties these are four separate properties on each of those objects right here's the best part not only is it not well documented what each of these individually mean the developers don't even know what they mean in combination with each other so if oh if something is inactive and visible well it follows this set of rules what is that like that's more that's like 16 or 24 permutations right and they don't they can't tell me what each of these mean if the object is in this different state that's not keeping it simple and they haven't even they haven't even proved to me that the complexity of this is worth my time to manage they haven't even documented it they didn't they don't even know honestly so that's not keeping it simple right it makes me go like oh this is just a gross awful awful API design or if you knew this company you would not be surprised second big rule be consistent and honestly this is really saying the same thing as keep it simple right be consistent with accepted best practices and be consistent with yourself right now accepted best practices is a bit of a well best practice is a subjective thing right but it's up to you and your team if you're designing a restful api to do some research do some talking right just kind of figure out what's best practices apply typically speaking you want to return 200 okay with with a good request and not 200 okay with a bad request right like those are pretty common things it gets a little murky but you can you can form your own opinion and then if you do it one way stick with it and if you have to deviate even a little bit document document document right but try to be consistent with yourself if you say I'm going to create all objects with put requests which is would be creative and bad then do it at least at least be consistent across your endpoints there's one in particular API that I can think of where instead of using put requests to update objects they use patch requests and that's unusual and speaking of which let's talk about some HTTP verbs because they're at least the most one's right because there's like more than this but I don't know what they are because I don't need to know because I'm trying to stay consistent right so get requests just get data that's all they do put requests are typically used to update data so you're trying to update an employee you give it up you do a put request and then you update that employee right typically with put requests you send everything you say send all the properties if it's missing a property it assumes that you don't want that property anymore and in theory and what people expect is that the property would be set to null or whatever that equivalent would be on the back-end system right post requests typically used for creating objects okay I also see post requests you sometimes in place of put that's less common but I have seen it to me I use put requests separately because it's just what developers expect right delete usually use for deleting individual resources I saw an API once though where they had a delete request that you could issue against a whole resource so API slash employees and it would just delete all the employees okay I wouldn't do that yes if you could if you wanted to but it seems like a bad idea and then patch request which patch request just says I just it's like a put request but you don't have to send everything back it's less common to see out in the wild but I do see it and it just basically said I just want to update these one or two properties right remember to be consistent pick away and stick with it if you're going to insist that you do all your get requests with posts and if you're going to be that mean at least like D consistently mean right and don't mutate data with gifts get I've seen enough I've seen enough to call it out ok I've actually where when you do a get request developers expect that it's not going to change anything but you're only getting data from the server but I've seen people do this I've seen people mutate data which gets and you shouldn't do that resource identification so we have a concept of mound versus verbs right so we have nouns employee would be an example of an out right get all employees would be an example of a verb based system I'm not talking HTTP verbs I'm just talking word verbs right and here's what they might look like you could get employee get employees get a single employee or post to the employees end point or you can create verbs right you could say get all employees get employees with ID get employee with ID and so on generally in restful so the one on the right example on the right is more used in like soap esque systems and that's not a bad thing like I've used good soap api's and bad rest api to leave me but when it comes to creating a modern today api that people expect to use use plural nouns okay stick with the plural nouns because it's consistent it's what people expect now I promise if you use singular nouns and you get everything else right I promise you I will not stand up on the stage and make fun of you I really won't but most people expect it to be plural so if you're starting something Greenfield stick with plural nouns to pick one or the other remember be consistent yeah so you get a customer you want to get the employee or you want to get the invoices under that customer right so there's a few different ways that you might consider doing that you can give them you can just return the set of invoices within the parent object that's an option typically that doesn't work very well unless you're returning a short list of things that doesn't change often when you're talking about employees especially in the context of an accounting system sorry invoices in the context of an accounting system usually a customer will just keep recurring invoices and invoices and invoices so you probably don't want to return it with the parent object because that list could grow to a thousand or more and then you're sending back data that they may not even be using right especially if you're getting a list of customers and you really don't want to do that much more common and much more what you should consider is just getting a sub resource using say customers no idea the customer and then say I want to get the invoices under this particular customer it's a lot more common it's a lot more common occasionally I run across an API that uses expand typically this is used for higher volume ap is where they're trying to control what data they send back they want to be flexible and not have like a hundred endpoints but at the same time they want to give the developer an option to get the invoices back with the parent object I would typically shy away from this for greenfield stuff I'd stick with the middle one just said make it a separate request right the expand for ammeter I find too many consumers just say oh I'll just take all the things you know I'll just expand every possible option and then what's the API consumer to do it's nice for higher volume API is likely probably not necessary but whatever you do be consistent right and I'm just going to say that till I'm blue in the face that it's simple isn't easy and keep it simple right but consistency is key but be flexible where it makes sense and again it's pretty vague right but like I can't come up here and tell you that the answer to this particular scenario is the right answer for you when we're doing get requests there are some things that we should consider about the implementation of our get request we may want to sort the data filter the data or page the data this is where I'm getting into a little bit of Microsoft D Web API ish stuff so you know bear with me if that's not your bag but in this case we're doing we're doing a request to the contoso API we want to get some people and we want to order by name so what would what we would end up with is a list of people ordered by name right and this is using something called OData this isn't built into web api but you can use new get and install OData and hook it up to your controllers it's very convenient very easy I like it you could also do things like this or order by name descending and you can also order by multiple fields so it's pretty handy again it's OData you don't have to remember that because you're going to wreston is that net or twitter right to look at this all up because you don't want to remember this don't write down anything that you don't have to remember right filtering filtering is actually pretty important so this is using the Oh data filter and API you don't have to use this but we're and we're going to talk about where you wouldn't maybe but in this case if you're if they know the names of the fields on the other end you might do something like this where you say I want to filter I want to say name operator and then whatever you're comparing it to right in this case we're saying name equals milk and this is extensible as well you can do something like this that's really useful it's really handy and we'll talk about how that applies in a second but again you get this for free just Google this right take a picture grab the slide deck whatever Google this you get it for free and web api is awesome paging is another important consideration you should make right if you want to get customers it's likely something that you will have to worry about you will have to think about paging at some point especially if you're returning a million records you probably don't want to return them all on one go right so you're getting customers you might want to page the data you say I want page 1 I want this many in the page and here's what the result might look like it might have a page number it might have a list of the results and it might have a link to the next page because you're a nice developer and you're like I just want to make them give them a while while next page does not equal no and you know keep going to let them get as many as they want I also see limit offset used commonly in lots of API either's fine just you know pick one and stick with it be consistent right and typically if you're implementing paging it's because you want to put a limit on the number of records I've used api's where they gave me a page and a page size parameter I had to use it but they didn't put a maximum on the page size so then I could just get all the records anyway so if you're using paging it's likely because you want to do some kind of filtering and keep them keep your API from returning too much data right there's a good paging example on my blog again link linked below but I have a paging example that I wrote up Oh data has paging in it it's not my favorite implementation I'm not exactly a fan of how it returns the data so I usually just roll my own okay do you need this do you need to sort a short page filter maybe I don't know what are your consumers need that should be the first question in your API journey right is what do your consumers need I will tell you a couple of my opinion so paging probably is something that you should consider sorting and filtering so the thing about filtering is is if you're giving them the power to filter on anything if that query is being trained if you're using it with entity framework even better because that translates to a sequel query but if that's not indexed and you're trying to filter on that that can get a little hairy right it's very common to include extra query parameters to program it to make it so that you include extra query parameters to say things like I only want the tools in this particular category or I only want objects that were modified after a certain date right so that's pretty common sorting weird weird and not common for integration scenarios right because most of the time I don't care what order the data comes back I just want the data but it might be useful if you're making like a front-end application write an angular or aralia or something and you're making an API for the backend you might want to implement sorting for yourself right that might be an internally consumed API where sort of makes sense versioning is really critical it's really critical to at least think about because your API should stand a test of time but note I didn't say the test of time I just said a test of time because you have to keep and keep in mind the lifecycle of your REST API it's not going to last forever now my mom she's a COBOL programmer and she works on systems that use as/400 and have since the 60s okay a little bit different your API is probably not going to last that long right but you have to keep that in mind you have to keep in mind is this going to be useful for an extended period of time do I plan on making a new one to address consumer needs in a couple years you have to at least think about that right and there's definitely there's different ways to version your API these are the ones that I see that are most common so a lot of now I wouldn't say a lot a fair number of API implementers do something where they do a get request and you're getting or posting to customers you post to the same URL but you provide a version number in the header of the request okay it's a little bit I would I see it but it's to me it's not obvious it's not obvious that especially if the objects have a different structure if I'm expecting something different back on a get request it's not entirely obvious I don't like this strategy but I do see it I'd much prefer something like this where you're putting the version number in the URL right so that way you're saying I'm running version 1 of this customer's API and then I can say if I need version 2 great I can just call a different end point it's much more obvious here's something here's an example of somebody getting creative so stripe is a payment processing API it's pretty popular and they use a mixed stress they have their major versions segmented out by a URL but then if you have a minor version like a tweak that you need like some some additional thing they'll have minor versions of their API and you can distinguish between those inside of the header which i think is kind of handy you likely won't need to do that but the creative example so I threw it in there it's kind of cool use URL versioning it'll save you trouble it'll save your consumer struggle it's obvious well it's much more obvious errors are going to happen problems with your API are going to happen the question is how are you going to manage those problems right so let me show you an example that's a bad example and it's using a real API that change you know to protect the innocent or not but I need to create a vendor so I do a post request to create a vendor but it requires name and the state right and I give it the the name of the vendor but I don't give it the state right I don't say Missouri or whatever then I get back a bad request that sister returns application jason says this is jason and then it returns a string that says state is required okay that's a Matson that's an error message that's something I can do something with useful limited usefulness we'll talk about that in a second right so let's do in a post to a different end point so we're going to create an employee and requires a first and last name all right and I just give it a first name because I'm just trying it out and see if I can break it then it returns back 400 bad request it's also returns back Jason but it returns back to Jason object that wraps inside of an error message it just says your request was invalid okay now both of these examples are pretty bad examples and this is a real API again this is not something I haven't seen right where they return one format in one end and one on another and this is like this is weird to me so they're bad so the first one is bad because what if there's multiple properties that are invalid I want to know about each of those so I can fix them fix the problem that much quicker then on the other end it wraps it in an object which is sort of like a beginning because if it's wrapped in an object maybe they'll eventually return or at least an array or something of errors right but it doesn't even tell me what's wrong right a good combination that I see a good approach is usually to return like an array of errors that say here's an error with this particular property and here's the error message you know it's either formatted incorrectly or entirely missing I like this err this kind of error reporting so again I'll say it again simple isn't easy this is pulled from Twilio documentation a little hard to see but what they return to you is not only do they return an error message they return a specific error code that's tied explicitly to that error message then they give you a link to the documentation on how to fix it and phone numbers are weird because phone numbers come in lots of different formats and actually Twilio makes it really easy because you can give them a phone number that has parentheses or hyphens right and it doesn't really care but if the bad word but but if you send in like I don't know a plus sign and you've got the wrong country code that could be a problem and so they give you a link back to some documentation that you can use to fix your problem that's awesome that's great you got to make confining and fixing errors on your consumer as easy as possible okay that's the bottom line you've got to keep it simple for them it's simple isn't easy but you got to keep it simple for them so that you'll use it talk about security so I've got two facets that I want to go over you know fairly quickly is that in encryption and authentication so a bottom line is you should be using SSL all right there's no reason not to anymore you can get free certificates via let's encrypt org right and then you can automate it so that it perpetually requests new certificates and it works in perpetuity I did that to my blog if you go to Schneids net you'll see that it's encrypted why did I have to feel the need to encrypt blog traffic and I don't really know but I did it because it was there and it took me about four hours to do so if I it takes me four hours it can take you like to write use SSL and don't roll your own encryption please don't roll your own encryption and this is just like a general rule all right let me tell you a story this is real so there was an encryption library that had a vendor name and then it just said encryption DLL right it was the name of the software company and then they said ok you need a key here in this text file and then in your application settings you need another key ok so very very cryptic very like mysterious like you need multiple keys like this is really cool and we were using it to in encrypt social security numbers sensitive data and so I was looking at the social security numbers one day not the real lunch that the encrypted ones and I started noticing kind of a pattern it's like okay they're all roughly the same length no they all are the same length and see the characters repeated over and over again what they had for us was a library that essentially was a substitution cipher they literally were substituting nine for like the Y with two dots above it and I and I noticed this and I told my manager and he kind of laughed because he used to work there thankfully didn't touch that but don't roll your own there's plenty of encryption out there that you can use it's plenty of encryption libraries you will do it wrong they will do it right I would do it wrong I just wouldn't try and then pick an authentication strategy that isn't basic basic authentication meaning with your API you send a username and password which is common and pretty easy to get started the problem is is that basic authentication is like giving you keys to your house to your house sitter and saying I'm going to be gone for a week so watch my house and you're letting the the sitters like okay and then you hand them the number of your checking account when you hand them the combination to your safe right you're just giving them all access privileges to your house you're giving them free reign and that's not very manageable Twitter use basic authentication for a long time they eventually got rid of it because they didn't want people to be passing their username and passwords to a vendor who might store them improperly and then use them to make requests and then you're just giving them the keys of the kingdom now you can tweet out all sorts of weird stuff right they didn't Twitter said no you want to be able to oh oh office a very good strategy for consumer-facing API applications where you need to where a consumer needs to interact and give permission right a loss is what Twitter uses what Facebook uses you basically give direct them to a login and then it says here's what this application wants to do here's what it can't do and then it sends back a token for that application to use to do those things right that's much more scalable because those tickets or those tokens can be refreshed they can be revoked by the user at any time much more scalable and much better for security alright so let's look at some code example I'm gonna look at the screen here because oh good okay so that says that doesn't look too bad I was worried that it would be too small but let's go over what a controller looks like so that's we're actually looking at some Web API code so we have here our employees controller it's just a class declaration that inherits from API controller if you're using asp.net core you would just inherit from controller and then we have our route at the top we say we want this to be API version 1 of employees alright so cool we're on the way we're implementing a good versioning strategy I like that and we got our get requests which get data we have the top one which just returns a list of employees and then we have the one below it which returns ones particular employee and it has a little route attribute to say we expect an ID of type end to be here and then we get that as an argument to our method and then that gets executed awesome then we have our employee post which takes an employee in now if you've ever made an API in visual studio you can create a new project and then right click on the controllers and then add you know create your model and then right click on the controllers folder and hit add controller and then you can do something called scaffolding where it just generates all the code for you and if you're using entity framework it's like double the awesome right because then it just makes a controller for you that implements or gets your puts through your posts and your delete and it does it all against an entity framework database which is awesome right actually not awesome so one of the things that's really bad and there's a lot of maintainability problems around that a lot of security problems - such as how are we controlling what the employee object has on it so now is does this mean that any property that they post back to this employee endpoint can be updated what if there's a social security number right or the opposite could be true they get requests to include those by default right so that's bad that's insecure the better option is to use what's called a dto or data transfer object or even a per request object when I create api's all of my controllers each of the requests has a different class associated with it for that request so if I'm creating an employee I'm I'm creating a class called employee post request it takes extra code but it's very explicit and it's very maintainable we'll talk about why in a little bit what about this okay so we've we've implemented that and we just we've said let's D TOS all the way right DT of all the things so let's separate our concerns right this is a little little harder to read so I'll break it down for you a little bit so we're taking an order this is an order controller so we're taking an order DT oh so that a customer can make an order right so we're going to create a new order we're going to add all the items in the order DT Oh to that order and then we're going to save it to the database okay and then your controller you know your controllers done some magic and that's and that's awesome right the problem is is that the controller knows too much the controller knows how to - too much and you see the bottom line is a controller should be a traffic cop they should be able to point out where things go direct traffic like this right but they should never know how to do something they should know where to go to do something but not how ok and we'll show I'll give an example of that in just a second we skip this part the part about bad requests right we're up there it says if model state is valid it's check in that order DT Oh to make sure that it's a valid object then send back bad requests and that's good because we want to send back bad requests so they'll fix it and redo their order maybe there was no cart items in the cart for this order or something right so then we implement validation on our DT oh right we can add those little attributes that say this parameters required here's the range right you can do that you can also inherit from I validate able object which just provides a method or not inherit implement I validate able objects which provides a method called validate and then you can say you can do some custom validation logic that's that's maybe more custom than just using those data annotations like required the problem with this is that now the DTO knows too much about how to validate itself right what if you need to access a database right you don't there's there's no hooks for us to create a new order dto passing in our database container right you could do it up inside of there but that's not really a good idea so what are you supposed to do we'll talk about that in a second the bottom line is is that better that this is better than nothing right this is better than nothing you should validate validate validate validate all the things assume that all data that you're getting is bad until you validated it and you should separate your validation logic from your object your dto should not know how to validate itself I like this library it's called fluent validation and what you end up doing is for than order DTO you would create an order detail validator class and then you can test that independently here's what the architecture of one of an API that I would make uses so we have a controller the controller gets a request the request gets routed to a validator right and then that validator once it's passed that it passes it on to a handler or service that then processes that request you notice everything is broken down yes it's more lines of code but as your API grows in complexity and you need to maintain it it will save you tons of hours it'll save you tons of time and then of course it's just good for separation of concerns and testability because we're all unit testing all these things right right Google mediator if you know if you use a library called Auto mapper which I use Auto mapper all the time especially in web api mediator was written by the guy Jimmy Bogart it's an awesome library it's a very simple low API surface it's a good it's a good one to implement the pattern where you go request handler that kind of thing mediators awesome documentation is so critical and there's a lot you have to think about you have to think about the endpoints that you're documenting you have to think about the parameters those endpoints take you have to think about the schema of the data that you're sending and receiving you have to talk about how it's formatted because if you're because if you're using JSON and you're expecting a date right you wanted an ISO 8601 format or maybe you wanted in you know short date time format you have to specify that you have to talk to that you have to you know engage with your users and tell them this is what you're expecting and then you have to tell them about how to fix errors or how to manage exceptions right and there's so much that goes into this making the doubt Navigant page easy-to-navigate right making it easy to read making it so that you document everything that allows them to go soup to nuts down your API right so you could document authentication for example really important part to document the bottom line is is a good API lives and dies by its documentation by far I'd rather consume a bad API with good dot with awesome documentation than a good API with no documentation at all every time because if it's well documented at least it's at least I can expect I can kind of work my work my way through the muck work my way through the weirdness right but it's a good API and I encounter a problem and the message that I get back is vague and there's no documentation that sucks but if it's not a good API anyways has got good documentation it should be if it's a good API it's got good documentation or you should tweet that out because that's awesome it's like I thought of that it was like great maintaining your API this is kind of a big one this is a conversation that I had recently with one of the API vendors which we have a lot of customers under write they said hey we're making under some under the cover the changes they're not changing any of the they're not changing into the objects they're not changing you need to get there just making some under the cover changes but they shouldn't impact you but let me know if it breaks something let us know if it breaks something okay that should send up a red flag it's end up like a hundred for this company it's no this is no different right just this is just a normal day well we said hey okay you know can we run our integration test can you release it to test so that way we can run our test suite against it and make sure everything's cool no we need it in an hour so we're going to deploy it in an hour right so not only did they warn us that there could be breaking changes is that they couldn't even anticipate but they said we're going to release it to production in an hour anyway and you know screw your customers if you have customers right and this is like so totally wrong on so many levels right this is just terrible idea this is just terrible API practice and I asked them about unit testing they're like how are we supposed to do that unit test what's that right so I knew that they weren't doing that and that just made this even harder thankfully there weren't any issues at time maintaining your API a large part of it should be fixing bugs and optimizing so you don't want to optimize too far ahead of time right you know premature optimization is the root of all evil I live by that but if you're if there's opportunities for better performance and they're significant then take them right you know fix some bugs if there's a bug with your API fix it right do what they expect don't do things like remove properties or add properties or even add properties away because I said we actually had that happen to one of our vendors they added properties for their API much after they were released and we actually had a property on there that on our class and our c-sharp class that that shared that property name and so what it tried to do is it was was giving us a string and we were trying to deserialize it into a complex object and then of course Newton soft-touch jason said you know naughty I'm magic but I'm not that magic so then that broke everything didn't break it broke that one particular endpoint and that was kind of sad we fixed it but keep your API is consistent right if you release it if you've provided that contract don't add and certainly don't remove okay so it's got eight minutes left so this is the end of my talk if you don't want more resources go to rest nine sneck follow me on twitter look at my Twitter account it's got a link to this as well you can go to my website I've got lots more information if I'll take some questions since I'm asked to have some extra time so if anybody has any questions if you want to leave please feel free but if you want to ask questions by all means but other than that my name is Spencer thank you very much I appreciate your listening and have the rest of us eat [Applause] so the question was what about a piece away showed Asia API versioning in the URL we showed it in the header what about in the query string for like get requests right I don't have any particular experience my experience is that it's better than my first initial thought is that it's better than header versioning but still not as good as like putting it explicitly at the beginning of the URL but at least it's a step in the right direction so but I would probably avoid it I mean if I were making an API I might use it for minor versioning but I have not even had an opportunity to do minor versioning on an API so probably wouldn't do that either good question yes say that again Oh the question was about generating documentation so there's some good tools out there to generate your duck at least start on your documentation because you really don't want to sit and like go property by property like some of that can be done for you swagger is a good option so what I use but it's often used in substitute for like not documenting at all and it's good but you should still fill in the gaps with like here's the exception here's how errors should look when you return it when I'm returning a problem here's how errors look here's how you have sent a case you still have to bridge those gaps but it's at least a good start good question yes how do you oh great question how do you handle versioning in code me personally so the way that I structure my applications heavily relies on dependency injection so what I do is I actually have my controllers in a completely separate library and then when I start up my application I use dependency injection to read though to read that library and then inject those different version controllers into my asp net runtime so I so I you don't have to use dependency injection you ought to but to answer your question specifically usually I just store them in a separate project and just differentiate them by using different routes do I have any code examples I think the let's see if I can find a good one here the one that I think would be most applicable if you could use your imagination just a little bit is if you could have an employee and employees v1 controller right that has that route prefix at the top and then you can have another employees v2 controllers that has a different route prefix API v2 you could keep them in the same library I put them in separate libraries personally can I like to keep things separate separate is good great question great question yes so the question was about validation like if I don't the object doesn't validate itself how do I validate it so I use fluent validation and fluent validation gives me gives me a tool where I can just I create a class and I inherit from their validator class and then I define my validation rules in the constructor so it would say rule for first name is that it can't be empty and empty means not an empty string and not null so that's how I handle that I keep my validator separate from my D POS or request objects yes so so the question was where do you pass the validation so I have it hooked up in my pipeline such that my controller routes my request through about through all the validators that it can find and then it goes if all the validators pass then it goes into my handler and actually does my service great question yes great question so the question is how do I handle deprecation right if I'm forced to break something how do i how do I handle that typically in an API we're in the API world what you would do is you give there first of all you'd give your consumers a lot of notice when you deprecated it that means that at some point you're in the near future you want to retire it if you're going to do that it's best to create another version of your end of your API and another version of that endpoint and a lot and then point them to that and say you use that version at that point you probably think it's at the point where you're probably thinking about doing that you're probably looking to the future anyways to say I'm going to implement API 2.0 but the worst thing you can do is give your consumers like very little notice nothing would piss them off more seriously like if you gave them we're going to set this API down in a month like even six months isn't really enough like more like a year but if you're doing that you're probably looking at the next version of your API great question yes right right okay so the question was is the ordering and filtering using the query string because that in the query string yes and then and then right okay so the question is about having a single query filterable query parameter versus multiple using it so you can use the filter parameter if you're using oh data you can use that single one much more commonly I don't see Oh data out in the wild much I like it because it's convenient and it works well for what I use it for but it's much more common to have multiple query parameters on an endpoint that filter it in some way and they're all usually optional so they could say it might be modified after or part of a certain category and then you can filter it out based on based on the query parameters that you provide and I see that much more commonly all okay and is it a single get it yeah we typically a single get yep well now I say typically but I've never seen that no usually it's just one get with multiple query parameters great question all right well I'm out of time and I want to let the next speaker up on the stage so thank you so much for coming thank you very much
Info
Channel: NDC Conferences
Views: 57,811
Rating: 4.8375001 out of 5
Keywords: web, architecture, Spencer Schneidenbach, ndc, ndc london
Id: x0yNKU-tz1Y
Channel Id: undefined
Length: 60min 37sec (3637 seconds)
Published: Fri Mar 17 2017
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.