 Can you hear me now? Oh, perfect. Yes. Whoo-hoo Excellent perfect. You know what if we push enough buttons and something will happen, right? All right, now take it away to talk about graphql and that net core Excellent so I like to basically talk about graphql and sort of an introduction of it in dot net core most of the talks I've seen around the internet mostly focus on this around Sort of the dot node ecosystem and I thought it'd be good to talk about it from a sort of a dot net perspective So we're gonna talk about today. We're gonna talk about sort of the basics of graphql In terms of introduction to why we want to use it and how it kind of works And then we'll talk about how to sort of build it within a dot net core ecosystem And using sort of the hot chocolate graphql library. So let's get into it My name is Nigel Samson. I work at a company called push bay here in New Zealand And we're using graphql across a number of microservices and applications My GitHub handle and Twitter handle there. So I don't get a chance to answer your questions later on hit me up on Twitter Sort of graphql. It's a specification originally written by Facebook Really quick, can you close yet the little box for Skype on the rubber right-hand side? Sure done Excellent So as I said, it's a specification for Korean data from the service Facebook originally wrote this internally and then shared it as an open source They also shared a an implementation in JavaScript of that specification And since then it's been picked up by the open source community And there's a number of libraries almost almost every language that support graphql in Dot net we've got probably two major libraries you're likely to see one is hot chocolate and the other one is one called graphql.net So what's really interesting about graphql is that it supports as I said a strongly typed schema with a Karebel API So this means that you can actually look at the schema of a service You're gonna know what data you're gonna get back from it in what fields it has and what sort of types you expect from it And the graphql server actually enforces that type specification So you're not gonna have a problem where the spec or the docs say one thing and the service actually Returns something else in terms of databases or storage Graphql spec has absolutely nothing to do with it You can store your data in anything It's a database the graph database relational database flat files or even hard coded or even delegate them out to rest calls in other ways So let's get into it some actual demos So the tool I've got in front of me here is one called insomnia. What this is is basically a normal sort of Request tool much like postman where you can use it to send requests to a server I'm using it because it's got some excellent graphql support So for this scenario, we're gonna talk about this idea of you know, so a blog most of us sort of understand the domain model of a blog In terms of posts authors comments images, etc So for our normal front page scenario, we're gonna want to click get the collection of posts We're gonna get the date the title the author Important thing is we don't want things like say the HTML content of that post for the front page scenario So on the left here is the the graphql query. So this is what we end up posting to our server You notice up here. We're actually just sending this to a single endpoint to slash graphql and We post this query and on the back here on the right hand side as the results we get So as you can see at the top we're marking this as a query And we're gonna query from the posts field on top of the posts endpoint And that's gonna return a collection of posts and from each post we're gonna ask for the ID the title some other fields the image Which and the URL for that image the author and the name It's you notice on the right-hand side here the data that we get back is in the same shape or Structure as the fields on the left So we can send this we get back the data nice and easily What's already important here is that we're we're deliberately Querying for the fields we we want the specification for graphql has no way to say get me all the fields or the equivalent of slick star And that's really important from a from a usage point of view and we'll get into reasons why in a minute So another scenario but slightly more advanced query the users clicked on a post and we want to actually Get the details for that post and show it in a page So again, it's a query And we're querying from the post field now rather than posts and this post takes an argument called ID And what we're doing here is called a variable. So up the top here We've declared a post ID variable of type ID and here we're using that variable That's like the post We're asking for the title of author name again, but this time we're asking for the HTML and the comments on that post Down here in the bottom of insomnia is where we're actually providing the value for that variable for post ID So why we want to use this idea of variables is that it what that means is that query up the top here can be static It won't change in terms of usage We can have this this query then stored in some sort of resource document file Whatever that becomes constant and it's only the variables that need to change This means we're not trying to build up our query via strings or anything like that which could be susceptible to some sort of injection problem Again an image this time. We're actually providing an argument for the size and We can go from here Comments we can make a list of comments And here we can see the again the data on the right returns the shape of the data on the left, which is excellent so why From a sort of introduction point of graph QL. Why is it? Why is any of this a good thing? Well from An application point of view. We're only ever getting back the data that we care about for any given scenario We're not getting extra data and we're not we're able to get all the data We care about within a single request so most times when people talk about graph QL And the problem it solves they talk about it in this idea of under selection and over selection If we imagine a post like this Trying to do this via a sort of a deep very denormalized rest request We might end up doing a number of requests one to get the post content One to get the comments on the post one to get the the details of the author of the post etc This is this idea of sort of under selection that a single request can't get us all the data We care about so we have to issue multiple requests to multiple resources to get our data Conversely in the first scenario If we were getting all the posts and that posts in point and a normal rest request was actually returning the HTML Which I was promptly discarding This is this idea of over selection that I'm getting more about data back on the response than I actually care about for my scenario Now that may not seem like much but when you're building things like mobile applications This means you're consuming bandwidth. You're consuming someone's data cap or battery life But doing a lot more work on the on the wire than you need to so this is One of the sort of main benefits in terms of applications is Being able to get all the data you need for a given scenario in a single request and making sure you only put the data on the wire That you really care about for your application From operability point of view, this is also really good. This idea that you don't have This notion of select star means that Applications are only ever going to query for the data they care about and let's say we wanted to remove a field Author post for instance, we could market as deprecated put out an API notice to say hey We want to remove this field and you can actually monitor via your logs Which applications which queries are still querying for that field and you can make a considered effort to migrate those applications across To use in a different field or whatever you're doing for your migration strategy here And then again once you've got no logs of people using that field You can kind of remove it safely knowing that you're not going to cause breaking changes with an application So as I said before the GraphQL is a strongly typed system And so most GraphQL Implementations have a way for you to pull the schema in some way. So this is called the SDL or the schema definition language It's part of the Facebook GraphQL spec We'll go into some detail about it in a moment But this is essentially the the more human readable version of the schema we can see here types authors comments, etc We'll go into some more detail in a minute The second really interesting thing is all GraphQL in points Implement an introspection schema. So this lets me actually inspect the schema itself I can say give me all that in the square. It's giving me all the types the name of that type The fields on that type in their names. And so if we go down here We can see things like Post post as an author and comments and HTML and so on. This is essentially a really good way for Software tools to to get access to that schema and they can do it all sorts of number of things with it One in use case is generating TypeScript So TypeScript can use these introspection schemas to essentially generate strongly typed types and your client side And think tools like insomnia here Provide IntelliSense over other things And what's doing under the covers essentially is that? Insomnia is using this introspection API making a request to your GraphQL schema to pull back all the information it needs in order to better provide IntelliSense And last but not least we have our mutations Mutations are a way for you to modify state for GraphQL That clearly marked at the top has been a mutation different than a query And ultimately though that the only thing that is actually the mutation is that top level thing that in this case it's submit post the rest of this Queries and she's a query on the result of that submit post which is obviously the post itself Again, we're using a variable here. In this case a complex variable of type submit post input And I've got our properties for that input down here and ultimately the result of that mutation on this side Cool. There is a third thing. So we talked about queries and mutations just now But there is subscriptions, but it's probably out of the scope of a 25 minute 101 talk So The GraphQL schema as I've said has a strongly typed schema like this The other thing it also consists of is a resolver. So the resolver is what happens when each of these fields is queried So when you're implementing a GraphQL service You're basically declaring a schema and attaching resolvers to that schema But first let's take a little bit more of a in-depth dive into what these schema looks like So here you can see we've got things like types really simple types like author And these are just sort of what we call object types all types have fields These fields can be Of types scalars so scalars are things like ID string Boolean And the like or they can be more complex objects So if we look at something like a post it has an author which references back to the author type You can also if you want create your own custom scalars if needs be we have enough support as well You notice there's a lot of exclamation marks through the schema. So what that is is that? Most GraphQL now the GraphQL speak has the notion of null ability. So if we have an exclamation mark here It means that This property cannot be null So an author must always have an ID. It must also always have a name if it's no exclamation mark It means that it may not so it might it might be null in this case a post has a null HTML It might not have HTML at the moment We also have this notion of lists so in here we have a go here take a look at this one Post of comments and the square brackets indicate that this is a list so post obviously has a list of comments and it kind of gets a bit confusing with these double exclamation marks What this essentially means is that the comments field on the post can't be null and The values within that list can't be null. So it's a non-null list of comments Well, sorry a non-null list of non-null comments, which is a little confusing, but it doesn't matter too much Excuse me. Sorry. The last thing is the input type. So the input type It's essentially the complex types that we're going to be posting to our mutations or posting to more complex queries And that defines separately than sort of your regular types Because they've got slightly more restrictive rules on what you can do with them and last but not least We have a sort of schema declaration And this defines our top level query in our top level mutation All right, so let's jump in to see how we can build some of this stuff So I've got a normal sort of dot net core Web the blank web app that I've kind of added a lot to so we're going to be calling using EF core and talking to a local Postgres database running out of docker For our data, but ultimately the the data source as I hope you'll see is kind of irrelevant for this so What I've done is referenced our hot chocolate ASP net core And then obviously a few other libraries for some fake data Some markdown rendering and again EF core in order to talk to Postgres So that's all we're going to need to reference. The first thing we're going to do Is set up our endpoints so In our configuration, we're going to create two different endpoints here The first using GraphQL to do post is setting up the actual service itself We're going to post our queries to I've just got that out slash GraphQL And I've got this here use graph HTML get schema, which is essentially Set up a second endpoint where I can get Do a request to get that stl which is this thing here So I want to set that up because I think it's quite easy Quite good for developers to call that and look at their schema But so that's all the setup we need now. We need to kind of start defining our schema and our resolvers So let's take a look at a really simple one first. What you're going to see is a pretty common pattern of things like a type In this case author So this is our my EF core model with an obviously an ID and a name And we're going to see a matching type here. So we've got an author class up here And we're going to see an author type down here So this is how we're using code To define the the author type within the GraphQL schema Jumping back about there's actually two ways we can define this the schema in GraphQL The first is What's called schema first and if you watch a lot of dot-net sort of node ecosystem GraphQL talks They often do what's called schema first. So this is where you define your your schema using using the stl define a Define it basically as one big string That's your schema and then we're going to bind resolvers to that which we'll get into in a minute What this works and it's pretty actually really good for demos But it gets pretty unwieldy as the as the schema gets larger and larger And so one the other approaches you can do is code first. So code first is what we're kind of showing here This is using c-sharp to define the schema of our GraphQL library And you can mix and match the approaches, but you tend to find Yeah, you go sort of all in on one or the other One of the other benefits for me in terms of code first is it means that some of these types can be shared between different microservices in different ways Especially when we get down to sort of custom scalars Right, so we've got this author and author type here. So again, author is my normal ef dto Or entity and author type is the the declaration or definition of that author Within our schema now hot chocolate. It's got some real good capabilities around this idea of sort of inferring this schema So if I didn't do anything and I didn't create this class at all Author hot chocolate could still infer a lot. It would probably still get in further be a type called author It's going to have a property called id and a property called name But what it might get not quite right for me is I want the in my schema I want the type of the id to be id not int and I want the string to be non mullable So this is why I've created this author type here and I've defined for the field id It's a non null type of id type And again, you see the sort of type suffix happening here And for the field name it's a non null type of string So this lambda is actually really important. It's going to do it's doing two things right now. One is it's telling Hot chocolate what the name of this field is it's inferring it from this expression id and name respectively And the second thing is this is actually what the resolver. So this is the bit of code That gets executed when this field is requested. So when someone asks for the author id It's this lambda that gets executed Which pulls it from the id property on the author and returns that integer or string in case of name So let's move on to a pretty um, but more complex scenario. So let's look at the top level query We're actually getting our post and posts from the database. So here we've got a query class It's got two methods get posts and get post And you'll see it's basically just using the db context to pull from that data What's interesting is more of the the arguments to this So we're actually doing this what's called a service level or a method level injection to the the method for the db context And i've marked this up with an attribute from hot chocolate to basically say this is a service I want you to inject this using dependency injection The reason i'm getting injecting this at the method level rather than the constructor level Is because db context is a sort of a scoped dependency. I want a new one per request So that's why I don't want to do constructor level injection at this point if I had some sort of singleton Dependencies then I might declare them as constructors, but in this case I want them to be Scoped dependencies. So I'm going to inject them at the method level. You'll also notice for the get post that We have an id and it's automatically going to be injected from that argument on that field back of Here this value will automatically be injected into that method call for us So again because we have our query class we have our query type describing this within The schema again we have get posts So this is the same this is the method to call when this field is recalled And hot chocolate is smart enough to get remove the get and turn get posts into just posts And again, this as we said, this is a non null list of non null posts And again for get post we're saying that there's going to be an argument called id and it's a non null id So we're just doing a bit more of sort of tweaking that inference that hot chocolate can do So this has been all pretty standard stuff we're basically just sort of mapping things that already exist And tweaking them on the way through let's look at a more interesting example So we have our post type And we're going to be doing a number of extra things to this again So we're doing some extra things I've got a helper method here to tweak some of that syntax to get rid of the non null id stuff But ultimately this is the same thing I'm tweaking the ability for id and name I don't want the author id that's on a post to be in my graphic quell I want an actual fully strongly typed author. So I've told in this case Author id ignore it. Don't put it in the schema And this is the really interesting one here is html. So on my post In my database, I don't store the html I'm storing the sort of edited markdown But I want to return the html as part of my schema So I'm creating a new field here and you feel that exists in the schema, but not in the database called html It's a string and I'm attaching a resolver to it. So this is what I want to call When someone requests the html and it's simply Taking the parent post Getting the markdown Competing it to html. So now we have this sort of being computed on the fly and only when requested And we're doing repeating this pattern for another number of things as well. So here We're adding a Resolve comments So call resolve comments Uh, we're going to name it comments and it's going to return a list of comments If we go down here again, we have a method. We're doing service level injection to inject the db context We're going to ask for the parent post at the same time. So hot chocolate is going to inject both of those And I can go to the database and retrieve the comments So this is where I'm sort of attaching more complex types to my uh, my post And I'm getting some good sort of strong structure to a lot of my graph ql This more complex scenario here for resolve author is using a data loader I don't want to get into too much of the implementation of this right now Probably a bit much for a half hour talk, but ultimately Using data loaders is a way to prevent sort of in plus one problems within Graph ql So if you have this idea that I'm doing a query that's going to pull multiple posts from the database and those posts are asking for author I don't want to have 101 calls to the database to get 100 authors out of out So a data loader is a way to to solve this, but sort of the implementation of this I don't think really we've got time for After that, let's quickly look at mutations. They're pretty much the same thing We have a method here Called submit post again taking a db context and that's strongly typed that input we've defined in this case. It's submit post input So it's just you know, what we want an authority some title markdown And we're creating a new post saving at the database and returning it Up here, you can see I need a clock from notetime and so this is where I'm going to construct a level injection of that So this is a sort of a common path and you'll see you'll see things like Mutation mutation type post post type this code first sort of approach code. Sorry Yeah code first approach in order to define our schema From there, we just need to register it So you got going back to our startup code We're doing our work here. So we're doing a couple things We're calling that add like a day loader registry, which we don't need to go into right now But ultimately the important part here is add graph ql We're using a schema builder And we're registering that query type and the mutation type we've defined As the top level queries and mutations and I've got a custom scaler here Which we can probably a little bit of time to go into which is essentially a new class to represent offset datetimes at another time And it's a way to kind of it's using extended ISO to render them down as strings This means we can have sort of the idea of a strongly typed offset datetime within our schema Going back to our startup You'll notice here. We're not registering things like the post type or the orthotype And we we get that basically by the fact that query type talks about posts and post type If we go back to that It talks about comments and authors and lists and images So we don't need to go through and be meticulous about making sure we've registered everything because ultimately As long as everything is reachable Through the other types Then we only need to reach those two level things Once we've done that we create our schema and give it back to graph ql And we're done So we have this notion of a schema we've defined using C sharp And we have this idea that we're attaching resolvers or methods to each one of these fields to call now Some of these Resolvers are complex. They're going to databases to do work or to file systems or whatever And a lot of these resolvers can be Pretty small, right? A lot of them are just going to properties to get values Or they're doing some sort of in-memory computation for read our computed fields In effect if you try and start up a service in hot chocolate that doesn't where a field doesn't have a resolver This would be an error every field needs to have a resolver essentially To know to know what happens when it's called So that's it. We've now got a sort of out of the box ef core To postgres database happening. We've got graph ql sort of the top of that In a pretty strongly typed way taking mutations as well as doing queries So jumping back I just want to give you a couple of links Uh, the first is for hot chocolate itself. Uh, it's a great library. I highly recommend you're going to check it out And the second is the github repo that will contain all the source code from this talk So, um There's a bit more than I've gone over today So have a have a play around have a look and see what see what you're like As I said, I'll be around on top of the questions, but I think we've got some time now as well again, so the The constructor injection Well, actually all of it's provided by hot chocolate, but the notion of sort of attributing a service The the resolver level injection With service like this is a thing from hot chocolate itself The the reason why you want to do this is as it is because of scope dependencies But ultimately, um, it's hot chocolate that's using the di container to Construct or to sort of create these these classes for you And ultimately it's the thing that's going to be responsible for working out where where these injection points come from and so on