 and welcome to this week's episode of the Visual Studio Remote Office Hours. As usual, I'm your host for the day. My name is Matt Christensen, and today we have a great, great episode because this is all about web APIs today. And I used to be a web developer for many, many years. I used to work on the web tooling in Visual Studio, but I have not looked at web APIs for quite a while. So I'm very interested to learn what type of web APIs are people doing these days? If I were to build a new one, what kind of technology should I be using? And what kind of tooling do I get in Visual Studio? Like I care about this stuff, it's important. And there's no one better to help me learn about these things than Mr. Brady Gaster himself. Hello, Brady. Hey, buddy. I have to say you're getting better with the opening music. Something really good. What do you use in the record all that? It's a, I have a keyboard, like Yamaha. Thank you. No, I didn't make that music. It's like stocked music down on some website, I'm sure. Nice. It's good. I'll have to make you some music, that'll be fun. Yes. I'll do the guitar part, and you can do, you have a guitar in the back there too. You can do the, we can do like a thing. Each play a part. I was talking to a gentleman the other day who we'd never had a conversation. I'd never met this jump before. We just had like a customer call real quick. And we get on the call and I was like, what's that? What's that behind you? And he was like, oh, it's my Yamaha. And it was this piano. And he was like, I really like your Gretsch historic and your Fender Strat behind you. And I was like, you're better than me at this. Like he could identify exactly what those two guitars were. I was like, I want to mess with this guy. Thanks for that introduction. This is great. Nice to be here. Yeah, good. Yeah, you are a return guest. One of the very few people that have now been on the show twice. So congratulations. It's cool, man. Yeah, I think- I was talking about the soft skills talk. It was really about like evolving from dev to PM. That was fun. That was a lot of fun. Yep. And this time we're going to talk about, instead of talking about being a PM, we're going to talk about a specific technology that you are the PM for, or at least part of it, part of your job. And maybe just give a quick introduction to like, what is it that you're doing and how did you get there? I can do that. So as Mads introduced me, my name is Brady Gaster. I am on the Azure Developer Experience Team. I really focus on the.NET side. The products that I tend to PM within the ASP.NET area are SignalR, and I work on this cool template called the Worker, which is what you would use for like background processing and microservices. And over the past year, due to some partner movements and partner work that I've been doing with our friends and the Power Platform and our other friends in API management, I have been working pretty extensively on, I don't like calling it that because it always, it always evokes a debate, but I've really been concentrating on REST APIs. I try to say ACTP APIs because when you say REST, it conjures up, you know, all kinds of like quarrels and that's not what I'm here for. But primarily what I work on is Web API. And I've also been stepping into the Azure functions areas a little bit more because an area in myself and a few people within Microsoft are pretty passionate about this concept of the open API specification, which recently hit a three one milestone recently. We have a mutual colleague here at Microsoft, his name is Daryl Miller. Daryl works on the open API spec. So I like to bounce a lot of ideas off of him to make sure we're doing things in a well-designed mindset. I think Mads is one of the people that shares my affinity for this old tech that we used to love a lot called ad web reference, which actually was the predecessor to ad service reference. And Mads, that was when we were talking about SOAP and WSDL. And then when we started getting into ad service reference, that was when we started talking about things like WCF. Yeah, this is what's commonly referred to as the good old days, is that right? That's exactly right. Those things were a lot easier. Yeah. So, okay, so you mentioned something you said, you don't like to call it a REST API. You called it, was it an ACT API? ACTP, ACTP. ACT, what is that? HTTP. Oh, HTTP API. Okay. Sorry. Well, an ACTP API could be a GRPC API, which would be not REST. It could be a streaming API, again, not REST. Well, there's streaming, and some components of it, webhooks and whatnot. But an ACTP can be a heck of a lot more than a REST API. If you're building web APIs or you're using functions to do things in an ACTP capacity, you're probably doing REST APIs. I just know there's a lot of debate in the community about what it means to be RESTful versus not RESTful. And that's, I'm not the person you wanna argue that with. I'm just, it's not important to me. Right. I remember there was a big debate at some point when we started kind of with SOAP and then RESTs and JSON APIs took over. And at some point, after like, I think the world kind of collectively agreed that REST APIs are the future or something like that, it became a hypermedia. And all of a sudden, there were these kind of purists that said, no, no, if you wanna do a REST API, you have to follow very strict, you know, HTTP methods. And there was, I don't know, it was very, I don't know, I was very confused about that. And I think that's kind of the last time I kind of dug into web APIs in general. So, and that was a confusing time I found. And there was a lot of debate. So where are we today? Like, if we look at sort of the history we went from SOAP and REST and hypermedia and now you're mentioning GRPC and other things, like what are people doing today? What should I be doing today if I were to write an API? Yeah, that part I'm not gonna answer. Like, I'm not gonna tell you what to do, okay? But what I would say is people are still doing everything, like people that are doing all kinds of stuff. One thing that I found interesting is that that add web reference and add service reference button that we see in Visual Studio. I've heard as lately as, I think the last time I checked on was like two years ago, but I remember I think I was in a meeting with you and somebody told us that that number is still growing and it's growing because it's just so easy to use. So really what we wanted to do was to try to like make REST API development as easy to use as was like SOAP and web services. Now to kind of answer your question, like what are people doing? Like let's say you're inside of a Kubernetes cluster. I know it just went right off the deep end there so I apologize for that. But if you're inside of something like a Kubernetes cluster, you pretty much have control over like all the different microservices in your cluster that might be communicating. And in those cases, it's really good for you to use something like for those of us that remember the add service reference days that's like WCF, something like GRPC, which is gonna be super fast, streaming capability, channel communication within your cluster. That's not necessarily supported by every browser, every phone, et cetera, et cetera, et cetera. Way back when you and I started working together I had a different life. I was really into this thing called SignalR. I'm still into it by the way. And SignalR was a way for, it was kind of an abstraction over the top of optimally web sockets. But in the absence of web sockets, SignalR would degrade gracefully. So it would try web sockets first, then it would try Lampoling, et cetera, et cetera, it would go all the way down. So that was really important before we had web sockets. I kind of think about GRPC right now is like a lot of the different client tech can't necessarily reach out and establish a connection. So what a lot of folks are doing is they're using something like a REST API to go to the front door of their cluster to kind of get those external signals going into their application. And then inside the application they'll be using something like Orlean's or Dapper or some sort of messaging subsystem on top of GRPC HTTP services to go back and forth in real time. So that's kind of what I've seen a lot of folks doing. The other thing we've seen some folks doing recently is instead of that REST API layer for folks who have very data intensive APIs versus kind of operation intensive APIs. We've seen a lot of folks beginning to use GraphQL. GraphQL is huge in other communities. It's growing in the .NET community. I work pretty closely with Jeremy Lickness on my team. And Jeremy's getting into GraphQL right now and he's starting to look at what folks are doing with GraphQL. I am very new to GraphQL. So if you're interested in doing GraphQL with .NET I'd love for you to reach out to either myself or Jeremy Lickness, the EFPM on Twitter because we're doing research with that right now. We're trying to figure out what people use when. For me, I tend to use REST almost to default. I don't build many applications that don't have an API. Nor did I do that before I was a consultant. I mean, before I went to Microsoft, I was a contractor. Most of everything I did had an API at some point. The reason I build API, what kind of think API first or API centric is if you can just write like a three tier application that has a UI that talks to some code on the back that talks to a database, you're done. You know, like if there's no API to that database, the only thing that can talk to that database is the app that it was built to talk to. So I like to put the API in the middle so that my application can talk to the API. Mads' application can talk to the API. Somebody else can use that API in new and exciting ways, et cetera, et cetera. And we can talk about some of that stuff throughout the call. But to me, one of the really great things about the REST API space right now I don't think I'll talk too much about hypermedia. You'd probably see my jaws flaring when we were having that conversation because that was always a fun debate in our team room. But one of the things you'll hear me really, like if we're talking about REST APIs and we don't talk about open API, I kind of feel like the conversation is not necessarily complete. Because open API to a REST API is similar to what WISDL was, service description language, definition language, I can't remember, to SOAP services. So some wise folks got in a room once at Microsoft, I don't wanna say their names, but we all talked about how you can build these APIs all you want to, like Azure Management APIs or OData-rich APIs. If those APIs aren't described or discoverable by customers, they're not really useful. Open API is a specification language that written in JSON originally used to be called Swagger. It evolved into open API specification and now there's version three and three one support YAML as well. But the idea behind open APIs, you can describe all the different end points. You can describe what people would need to send a request or what they would expect to get as a response. And I really kind of adhere to the HTTP spec. For instance, if I were to do an HTTP get on something like products forward slash list, I would expect to be getting back a list of JSON objects. So I'd probably expect to get an HTTP 200 and okay response. At the same time, if I were to do a post, I would expect to get back an HTTP created response. We've got that kind of stuff built into web API and what a blog post I'll show you here in a moment. We've actually got this cool thing called web API conventions that will kind of interrogate your code or understand how your code could respond and give out the right potential response codes. I've got a blog post. You wanna share that whenever you want to. Yep. And this is on our team blog. You can see this month is the month of APIs. So Mr. Galloway is asking me to do a couple of different posts. Can you zoom in a little bit on that? Sure. Plus your blog post, yep. Yep, there you go. So essentially this first post is really about and I called it discoverable at first. And in the comments, there are some folks who use API discovery mechanisms inside of, say, microservice clusters. And they said, well, to me, discoverability is different than describability. That's really good feedback. I kind of wish I'd called it well-described. But in this article, I kind of walked through, this is the first of four. We kind of walked through like thinking design first. I've joked about the curse of the ASMX file. It was essentially when I would start building web services, like the tooling just made it work. I didn't necessarily have to think about the description. Later on, when you get to like swagger and open API, that's something that you really have to kind of manually craft. So it becomes more difficult. So what there exists is tools like Swashbuckle and Enswag that will essentially interrogate your web API controllers and output open API. That's kind of inside out. A lot of folks don't like that, myself being one. I'd always try to do to default to making a clean API first. But that can take a lot of time. So a lot of folks really just wanna dive in, get coding, and then kind of have the code generate the description. If you do that, there's some practices that you can kind of implement that I kind of walked through in this post. One of them is the concept of Perl's Consumes. In this case, let me zoom out just a little. In this case, you can see that my API will say that it can respond with three different ways based on what my content type is gonna be. I know I'm always gonna be sending it, Jason. So really the only thing I would ever need would be this. So what we can do inside of web API controllers is you can literally decorate a method with produces and or consumes. And when you do that over the top of a method, and I did this inside of some compiler switches so people could see before and after, I kind of walk you through all the different experiences in VS and VS code, how to turn that on and off. But essentially when you turn that on, you basically say the only language my API is gonna speak is gonna be Jason. So what you end up getting is one third of the Jason payload in your description that you had before when it comes to describing each response. If you think about an API that has a couple hundred methods on it, that could drastically shrink the size of that description file, which means things like code generators or things like logic apps or power apps that actually use that open API to know how to call the API will load the API faster. And we go through some other stuff like response codes. If you think about the idea of just something like a get product API, I might wanna return a 404 if you ask me for a product that doesn't exist. I would wanna do that because the idea behind rest is you wanna kind of borrow all those gestalts from the ACTP spec. So I would wanna say I found it or I didn't find it. If you do that inside of your code and then you look at the potential response codes, it will only give you an okay. That's because I haven't told it to give anything else and it doesn't know how to kind of guess. So that's why we came up with this thing called web API conventions. And with a one line of code, if you apply, and this is just the default convention in which to sort of make some very opinionated assumptions about what you mean when you say conventions. If you were to apply that at an assembly level for your whole web API project, what ends up happening is now you will get all the potential response codes. You see, I've got a 404, which would match that not found that I would output. You'll see that I get a 200, which would match the found situation that I would output. And it will even go as far as to give me a default saying, you didn't give me a 200 or a 404, something went wrong. So for whatever reason, my service response was a 401 or a 500, like the client should know something's wrong, something's wrong. Just by looking at the response code, it knows something's wrong. It doesn't even have to interrogate the payload of the response. So this basically just describes the HTTP return code, status code. Correct, correct. So this just says like, from the get method, from the get specific product method, if you will, I could respond with a not found or I could respond with a 200. When you get into things like, I might throw you a conflict, you imagine them while that could begin to grow. So could you think about this as a method signature, Brady? Yeah, in a method signature, and let's say C sharp, you return an integer, right? That would be your, when everything works fine, it returns what it says in the method signature. But you can also specify using the triple slash comments above your C sharp method. You can say, hey, this one can throw an exception, a system IO exception, it can also throw a web exception. So prepare your code for those things. If you're assuming this, can we recent about it the same way? Yeah, exactly. That's a really, it's kind of like throws and Java. You know what I mean? If you're saying every single thing that could happen, and we get into like client generation later on in this blog series, we talk about things like the autoresse code generator, which you and I worked on quite a bit in the past. And then the N swag code generator, which is fantastic. You can actually aim the N swag and you can actually use the code to actually aim the N swag code generator and an existing web API assembly, you don't even have to reference it. That's pretty cool. But that's the idea of, I wanna basically like an HTTP, just like with methods, you invoke a method. You know, if you pass it a certain set of parameters, you could get a couple of things back. HTTP is the same way based on HTTP conventions and the HTTP specification written by our hero, Tim Berners-Lee and friends. You know, these things are expected outcomes. So those code generators actually know what to do. It says, hey, I got a 404. You didn't tell me I would ever get a 404. I literally have no idea what to do here. A lot of times those code generators are extremely narrow-minded. They're like, you told me to do this, I wanna do this, you told me to do this, I wanna do that. And when you don't have those response codes, those code generators have no idea what to do. So it doesn't feel like what you're talking about is building REST APIs. But what you're talking about is building REST APIs that can be used later. So that's important. Like I could build these APIs all day long and the only person that knows how to use them is me. Cause I didn't describe them well and nobody knows what they get back. You know what I mean? So that's what OpenAPI does is it gives me that way actually describing what's gonna happen. So Brady, there was a lot to unpack here. So I got a lot of questions for you. I wanna start with what you were mentioning about being inside a Kubernetes cluster. So if I can paraphrase that a little bit, like you can use like stuff like GRPC, things that are not supported by all clients yet. You can use that internally as glue between your different microservices and internal application components. And then you can offer sort of a public API that is consumable by all clients that sits next to that. Exactly. So that's one way of doing it. And so if you wanna be on the latest and greatest internal, you can always do that if clients don't matter in that case. Did I understand that right? Yeah, totally. You totally did. I mean, you don't typically put like a GRPC endpoint on like if you've got a cluster or got a firewall, you wouldn't necessarily put a GRPC endpoint as the outermost catcher's mitt where requests are gonna go. Because you're going to be limited by the number of clients that can call to it. You know, like you would be able to write code on say a Apple watch or Raspberry Pi is a bad example because it's pretty advanced, but on like a lower level IoT device, oh wait, you do a lot of this stuff. Do you think that many of the devices that you use in your home automation scenarios could support something like ACTP3 streaming? Of course not. They don't have the bandwidth. They don't have the memory, but they can make a simple ACTP request. And they run different protocols. Right, right. Oh yeah, you've got all kinds of protocols in your house. ZigBee. ZigBee Z-Wave Threat is a new upcomer. Cool. Not that new, I guess, but. Let's see, that's a really good example. Like if you think about those things, those three protocols or those three things, I guess they're protocols, right? Yeah. Those things are running inside of your house. So that's like our cluster. So you've got all these different devices that communicate with Z-Wave inside of your house, but your phone, like let's say you've got all these things that are wired up and now you want to like open your garage door. Does your phone speak Z-Wave? Probably not. So you would have to like have something that your phone could hit using REST that would then hit the internet and then the internet would make a call back down to your Z-Wave device and say open the garage door and then it opens the garage door. That REST API is kind of your way in, if you will. Cause it's kind of the most ubiquitous availability of clients that can actually make calls to it. Like anybody can make an ACTB get, it's pretty easy. So that's a great example that I totally understand. So when we, okay, so now I'm gonna consider making my API, right? And then you were saying, well, if you're doing just an app where you have, let's say you have a UI layer and then you have your business logic and then you have your data layer, like a classic three tier app. You say you wanna stick in an API just in case that someone else wants to connect to it. Yep, usually that's kind of the case. So I like- You would end up with four layers or would the business logic be your, or the data layer be your API layer? No, the API layer would absolutely not be my logic layer. It might be my logic layer from the, let me actually just say something. Can we flip the cut? Yeah, yeah. Oh, that's not right. No, we're gonna watch you log in. We'll do that, right? There we go. All right, yep. So in this case, so I've got this, this is the solution from the blog post series. So you'll see that I have a couple of things in here. The first one is my actual web API project. We've also got an Azure Function project in there, but we won't talk about that right now. So essentially what you'll see is that I've got this project and if I were to open up, let's say I open up the shop controller. So what I would show you here is you see how I've got the shop controller and now this is not, I wanna be very clear. Like I don't give advice. I tell you how I do things. I just ask you to like use what you know about things and about me and decide whether or not you think it's a good idea for you. So in this case, what I'm doing is I'm basically passing in an instance of essentially a like a service interface. Now this is not a ACTP service interface. This is a logical service interface. If I were to look in my abstractions, we'll see that that lives here. And this is essentially like the interface for a service that I would expect to be able to do all the backend stuff, that my API would need to call to do everything in the database. All right, now I did that. And in the first implementation of that, when I implemented it, I built it on top of Memcache. And that was really just, and you can see here, this is my Memcache implementation of that store service. My implementation relies on an instance of memory cache being in my server. So at this point, I'm just like reading and writing things back and forth to memory cache. The moment I stop debugging, all my data's gone. That's great for just testing my API. It's not great for when I want to deploy my API. So what I do next is in my data providers, then I would actually build a provider on top of say, in my case, Cosmos DB. Now, this is where I would probably do a lot of my data business logic. You'll see that I don't have much in here. I actually have more logic in my Memcache implementation than in this one. But this is really when I'm basically just taking the stuff that I get from my API, from my web API and feeding that through my data service back to my data. Now, if I was building this, this is the layer where I would do the majority of my business. And I actually did one of those right here. So in ship order, this would basically get called whenever the person in the warehouse actually ships my order. So what I would do is I would get that order. I would get a list of all the products. For each one of the products that I'm getting ready to ship, I would call my API again. I would just update the product inventory for that particular product, setting it to whatever its current inventory is, minus however many is in this particular order. Then I would market a ship, then I would update the record. But I'm not doing any of that business logic inside really of my actual app. Really what my controller does is it uses those logical services to do the business work and then it kind of handles the HTTP stuff. So I would really think of my controllers as the layer that receive the requests and hand off to services to do work and then respond with responses, which would be response codes and or response checks, like if I were to do a, you know, give me a product, I'm gonna hand you back a product, give me an order, I'm gonna hand you back an order. And that kind of thing. So does that kind of answer your question? It kind of does, but I do wonder what is by having a service layer in between, I understand it's really cool the way you can very easily kind of swap out your underlying data storage and all this sort of stuff as you develop and maybe as you look, difference between production environment and test environment and whatnot. That's super flexible. But what's the overhead of introducing another mechanical layer? Like now we have to go over HTTP even though we're on the same server farm potentially as my UI code, if I had all the DLLs and everything loaded up in my ASP net website, instead of having to go over HTTP to do a network call, even though it's a local network call, like what are we talking about here? Can I, is there, what's the latency? What's the downside of this? That's a great question. I mean, if you've got a web app, I mean, that's, you could skin that in a couple of different ways. Like the first way, let's say you've got a web app and you want to have, you know, essentially like, you know, is post-back kind of scenario where like, you know, you just do a post-back and everything happens. In that context, you're going to have to post the data back to the server, you're going to have to do your processing, then you're going to have to do the additional processing to re-render that entire page and then send that entire page back down the wire. That's a much larger, like request response conversation than give me, I'm going to give you a four and you give me an object back. Like that's a much smaller representation. It's also much chatter. So there's that. Like instead of you doing one ginormous call, you might do four or five little calls throughout your entire lifecycle. One customer that I spoke with as a, for instance, they were doing something where they had an application, trying not to disclose anything about the customer that's specific, but they had an application that would really take over at a particular point in their business process. So like a thing would happen and at some point in time, like they would basically release control from whatever was controlling it beforehand, like a controller situation. And now like these people are going to be taking over. So the, these people segment would essentially take that resource through the rest of the process. And they would estimate that about 5,000 customers or excuse me, 5,000 users were on that app at any given time. And that app was worldwide, primarily being hit through a web browser. So pretty complicated like web forms looking UI. And they said that the first time they would hit the site, they would kind of have a spinner because they would download about a mega and a half of data. It was all the markup and all the imagery and all the stuff needed to render the screen. After that, they would set up a signal R connection and every other set of communication that would happen from the client back to the app would be a small web API call followed by something that has server and then respond with some sort of a signal R push. So they went from having to hit refresh however many times a day to download a mega and a half two megs, roughly of like view data to having many, many, many, many, many calls which means they had to kind of scale out horizontally so that they could support all those individual requests. But that said, that experience was much better for their users than having to do a post back every single time simply because of the amount of time it would take for the post to happen for the response to happen and for the rendering to happen. And in some cases, they were actually connected outside kind of in poor connection environments. It was kind of an inspection app and they would just be waiting and waiting and waiting for the old way for the app to download but with the new stuff happened a lot faster. At the same time, we've also talked to customers who use that kind of an approach incorrectly and let me describe what incorrectly would be and the code that you saw in my window most of those requests would be a post request with like two or three properties not a lot of data, four or five K, very small. We have talked to customers before who will do that kind of thing but they're transmitting 380K size messages. That's not a good use case for a frequent chatty type application, it's when like chatty is okay to me when the messages are tiny but when you're doing 380K either in real time or streaming or chatty, you would want to second guess that. You'd want to start thinking about that. And then Maz, one other question you asked is like on the performance, that's when you start adding things like caching on gets so that the different requests that you would be making that would be getting potentially a lot of data those would be cached so that you wouldn't have to make those database hits you would just make a trip back to the server for the memory. But that does create a chatty scenario. So you have to think about that in a request response paradigm. Okay, yeah, that makes really, really good sense to me. So for instance, if you're website front end is static website and you're using like some like React or whatever it might be some sort of Angular or front end where you just talk basically just talk REST API JSON with your server, right? Or Blazer Web. Say it again. Or Blazer Web assembly. Right, or even like, I guess back in the day with the update panel, we kind of have a look. Yeah, no, not at all because it would actually post back the entire. Oh, post back, yeah, post back, yeah, it was weird. Yeah, even though it did it sort of without reloading the page. Was that, was that anything that Ajax? Yeah, yeah, yeah. It was the Ajax toolkit. It was, was it in ASP.2.0 maybe? I think so, yeah. Would be. Yeah, yeah, good. Yeah. Visual Studio Whitby. And you know what else was in Visual Studio Whitby. So for people who don't know, Whitby was Visual Studio 2005. That was the internal code name. Actually also external code name. Visual Studio Whitby. And Brady, do you remember the code name for Visual Studio 2008? No. Orcas. Orcas. Orcas, Visual Studio Orcas. I should have known that. I would associate that with SQL for some reason. No, they had, I think Denali was one of their, right? For SQL Server 2012. That's it. That's it. I'm trying to give anything else over here that I'd want to show you. I showed you the stuff on, showed you the stuff, some of the tooling and whatnot. The one thing I would call out in that blog post, and this is one that I've talked to Darrell Miller, our good friend in the Open API Board about, is this concept here emitting open, excuse me, emitting open API's operation ID. Okay, operation ID is a really important thing in open API speak. And I remember a while back Mads and I were, I really tried to find that mockup. Mads and I had an idea where we would basically ingest all manner of like open source generators. We were thinking of tackling, I think we even talked about GraphQL then. We were like, let's not do it with just open API. Let's look for a thing that would generate clients for like OData, Open API, all of it. And then we were like, that's a bad idea. We can't do that. It's a big, big feature. But essentially, if you look at this kind of a payload, what you'll see here like, and this is when we got into some of those rest zealotry arguments. When you start looking at these payloads, you'll see here I've got orders, then you'll see I've got orders with an ID. But I don't necessarily have anything that identifies like what each one of those operations is. I could look at it and I could figure it out. But there's nothing definitive. What an API does that looks like this when you throw it through a code generator, I'm just gonna pull this up real quick, is that you end up getting code that looks like orders async, orders to async, orders all async. And then if you were to look, there's products async and products two. That's because each one of those operations doesn't have its own name. So if I happen to have two operations that go to WAC products, one of them throwing at a parameter, one of them not in the generated code, it just goes, oh, okay, I was just calling both product. And I'm just gonna increment it with a number. So if you were looking at this code, if you were the person that inherited this SDK, you would have to look at the arguments for each one of those generated code methods to figure out whether it was a get or a get all or whatever. But hang on, this is because that we don't have, so you weren't mentioning like a descriptive, like a description of the service, right? Like we used to have WSDL for SOAP services. Right, right. Or WISTL. And now we have open API specification. And what you just showed on the screen, if you scroll up a little bit, it did not say anything about what those methods return. But we're down, down, down, down, down, down. That one, that right here. Not that one, it's actually this one. I've shrunked it. This is me taking out all the response codes. So this is me, this is the subset of the operations. Just so you can see what this looks like. So yeah, you're right. So if I look at these all the response codes, yeah. If I was to take this JSON, and I'm saying, okay, this is the API surface. This is how I can query the API. Then if I were to write a generator of that, even if I do it manually, let alone if I were to do it automatically based on it, right? I don't know, does it return an integer? Does it return like, what is the nature of the object that is being returned to me? Well, like I said, this is a subset of the overall stuff. If I were to go up, that's when you see things like this. So it's actually got schema refs. This is the full open API. This is me taking out a lot of stuff to just show you the operations. Sorry about that. All right. So is it one big JSON document that contain all of it, the whole service endpoint definition? Yep, it's one JSON or YAML. You can do YAML with open API three now as well. How do you do YAML over HTTP? Like you can't remove white space and compress the size of YAML, can you? Because it's indentation dependent? I tend to use JSON meds. Yeah. Don't get me on that one. That's the tabs where spaces are here. Uh-huh, I know. But if you think about this, like think about what we have here and then you saw that generated code, it doesn't know what to do. What operation ID does is it puts a specific operation on each one of your APIs. The way you get that in web API, this is what most people do. They'll just do HTTP post and then give it a endpoint. All you have to do is this second part here. You actually use the name argument and what it will do is it will take whatever you pass in to that value and I'm using name of and just, I've got a one to one here, you know what I mean? And now, when I generate code using Nswag or Autorest, when I generate code using an operation ID inclusive open API spec, you don't get this check inventory to stuff anymore. Now what you get is create product, update product, get products, get product. Yeah, beautiful. Create order. Why don't you do that by default? Why do you have to say name equals? Why can't you just use that by default? Take the name of the method. Not everybody wants their API to be that descriptive or wants their descriptive file to be that verbose. And not everybody wants to use something like a code generator or to use something like an integration layer, like Power Apps or Logic Apps or something like that. Okay, this is me showing you kind of the way you would do this if you want very seamless like integration possibilities later on. Like the fourth series is gonna come out and we're gonna show you how to do this with Logic Apps and Power Apps and some other stuff. If you don't do this and you're open API spec, the generators and the consumers have to do a lot of guessing. And once they start guessing, they start having unpredictable output. So if you, like me, are opinionated as heck about your APIs and what you wanna do is mitigate the tool having to guess. You wanna tell it what it's called. So like instead of it going, I'm gonna call you products one or products two, you wanna be called get products. Yeah, right? Yeah, yeah. So back in the good old days with soap and I know people hate soap and that's fine. I wasn't a fan of soap itself, but what I did like was the ease of use, like the user, the usability, the discoverability, the, like it was just fantastic. And just so just to set the stage for people that might not be aware of how that experience was back in which was to do Whitby and Orcas days, is that you would write a web API and you would, well, soap service. And it was just a simple file and it was kind of like a controller action, not really, but kind of similar, I guess. And a whistle description would automatically be generated on at the runtime. So you could query and see, here's the description of the API surface. And so now what you could do is that I could expose this service to the world, put that out on my web server. And now Brady could come in on his Visual Studio and say, I'm gonna write an app that's gonna interface with that soap API. And you could literally in Visual Studio in the project, you could right click the project in solution explorer and you can say, add service reference or add web reference, pointed to that whistle document that auto-generated from my service and have all the proxy code generated for you. So in your app, you just wrote C sharp to communicate with that auto-generated proxy code that did all the soap communication back and forth. Now we can talk about soap and how inefficient it was and how like verbose it was and so on. But from a developer's perspective, that was easy. And the way I see it is that it kind of completely democratized service oriented architecture, which then nowadays we call it microservices, but they're kind of similar to those two concepts, right? Exactly, exactly. And so when we look at that in the lens of history, like how, where are we today? Like, is it as simple or do you still have to do like manual steps more so than back then? Like, where are we? What's the, yeah. It's funny you should ask. So let me share my screen real quick or let me push the button real quick. So I bet the other thing you missed about those and you're gonna make me say it, aren't you? You're gonna make me say ASMX files because you weren't necessarily editing the wisdom file, you were editing the ASMX file and the ASMX file would generate your description, which is exactly what we're doing in WebAPI. So in WebAPI, we have, there's two options. The option we ship in the WebAPI for .NET 5 template is an open source package known as swashbuckle.asp.core. It was simply a numbers game. Swashbuckle just had a bunch of downloads because it's integrated in a lot of different stuff. Also integrated in a lot of different stuff is NSWAC. The NSWAC team has actually got generators for clients, generators for servers, all kinds of good stuff. So essentially what you can do inside of Visual Studio after .NET 5 WebAPI projects is when you hit the F5 button, I've got mine starting up in Kestrel. When you hit the F5 button, you get this fantastic thing called the swagger UI test page and the swagger UI page will look at that open API that I've got and it will essentially generate a test for each one of those individual things that I can try out. So right here, I actually want to do a get on my products. So I'll go right here and I'll say execute. And if I scroll down, oh, looks like that's gonna fail. That's probably my fault. I probably don't have my connection string wired up. But you can see here that essentially it would make a call out. I would get back my data. Yeah, I just don't have any because I'm probably running my memory cache implementation and not my backend implementation. But the way this whole thing is generated, I'll show you two things here, is using very much like you talked about with WSDL, it uses this open API. So on the back, this open API gets generated. This is all dynamic. You can actually do this at published time too if you want to. The sample code has some of that in the CS prod files if you want to look around. But essentially what I can do is I can wire my project up so that each time I build my solution, I build this swagger file, this open API file, dropping into my path. And then what I do inside of Visual Studio is I've got one right over, I don't, where do I have it? Got it somewhere. I got it right here. So what I can do here is you see, I've got this open API is the way I got that. Brady, can you talk into the microphone? Oh, sorry about that. What I was able to do is I right clicked here and instead of saying add service reference, what I did was say add connected service because this is part of the Visual Studio connected services stuff. And when I stop, you'll see right here, I've got this service references for open API and GRPC. And all I had to do was basically hit plus, go to open API and I could provide a file or URL and this will generate that client code directly into my project for me. This is, we talked about this five years ago and now it's here. It's there. Wow. It's there and it's also there for GRPC so I could do GRPC and this is cool. I can generate a server or a client side using a proto file. Now, Brady, can I extend Visual Studio to add different generators to this? So let's say that I wanna spit out, react to JS JavaScript interface to that open API. Could I then generate that sort of API layer for my in JavaScript if I wanted to? Like through a Visual Studio extension or a new good package that could hook into this? No, but that's a great idea. You and I talked about some time ago. I wish I could do that. I would absolutely love to do that. Now we do have this thing that was actually put up by the developer division as well called auto rest. Auto rest is written in TypeScript, I believe. So you can use auto rest and auto rest, you can build your own template generators. Some folks worked on something inside of the VS code extension for Azure functions and Azure API management call. We were calling it Project Stencil when it was a hackathon project last summer. I love that. Now it should stand for Sarab because Sarab is the one that drives GRPC but I like that. But you can actually open up auto rest, write your own generators and then you can point those generators at an open API spec and have it generate whatever you want. Like I said with Project Stencil, if you were to go inside of the API management or the functions tools in VS code, there's an experimental feature that you can party on that will basically give you the ability to generate Azure functions from open API specs. Why would you wanna do that? Let's say you're working on something like a Power App and there's somebody who's building a front end for it and they realize they have an API that they need built. They could go into something like the Azure API management portal blade. They could design an API, that API outputs open API, you can generate code from open API. So the folks on the Project Stencil team essentially put that into VS code so you can actually let somebody who's not technical design the API that their app would need to call, then generate a scaffold project that you could hand off to a developer. The developer just fills in the important code, right-click, commit. Maybe you already have it already wired up so that it does a publish. That could be on the horizon. That's something I'd like to build. That's something I'd like to use. Wow, so let's say that you're now consuming, so I'm now consuming your service and I'm using that piece of UI that you just showed where I can add a connected service and I'm connecting to your GRPC service, let's say. Now, that generates some, in my case, C-sharp code for the server. Now let's say you change your API. So now one of the calls, let's say, no longer works and I get an arrow back as we talked about how you define the different errors and all that sort of stuff. You get some sort of arrow back, unhandled exception, whatever comes out of that. And so what I have to do is that I have to update my connected service reference so I regenerate my server proxy code, right? Correct. So when I do that, is it literally producing C-sharp files on disk that now will fail? Like if there was an update, they will now fail my project from building, from compiling, because the signatures have changed? Sort of, yes. I mean, like everybody's had to deal with a breaking change in an API. It just, it's gonna happen, you know what I mean? Like, software's never finished. Let me share this one more time. One thing you'll see if you look at this sample code is that I'm actually using something called API versioning, which is a fantastic open source package. It's actually used by tons of projects. And what I can do is I can actually specify individual API versions in my, you know, for my API. If you saw when I hit F5 and the Swagger UI came up, actually had a version selector. So I can actually change versions and see how things change. I saw it said version 1.2. Yeah, it's cool. If I were to go down here, you can see like I can use the map to API version to actually specify which version it shows up in. That comes through in the generated code too. So I could call version 1.1 or I could call version 1.2 or whatever. Now it is conceivable that if I have something wired up like this, I'll show you real quick. So I'll double click my project and you'll see right here, but I'm actually using the Swashbuckle CLI and there's an Nswag CLI as well, but I'm using the Swashbuckle CLI to output my open API file to disk each time I build my project. That will actually put the JSON name with Contoso online orders.api.json into the bin folder of my output directory. Now, when I did my client stuff in this project, when I right clicked and I said add connected service, well, look at this. It actually puts all that directly into my csproge file too. So if I were to do a solution build right now, it knows the dependency chain. It's gonna build my API first, which means it's gonna output that open API file, then it's gonna go and build this, which knows it has to go grab that API file and bring it in before it does its build because part of the build is to generate the client code right before it builds the client code. So you can literally wire it up on the API side to output your open API and you can wire it up on your client app side to ingest that open API file on disk and then this just does the build. If I were to... How does it know how to do that build time? I would imagine it would need runtime to understand what the URLs, the final URLs are gonna be. Like let's say you have some URL redirection mechanism, load balancers or something else or like how does it do it on build time? I think what you're thinking of is like when you've got like an ASMX project and a front end project and you hit F5 and they both run at the same time, this doesn't have that level of fidelity yet admittedly. It was not so much that, but I guess your discovery document, your JSON file, your Swagger document, what is it called, open API specification? Yeah, yeah, yeah. It has all the relative URLs to those different endpoints. And so how do you know at build time what those relative paths or URLs are to those endpoints? Couldn't you have something in between that like puts different paths in first? Like if you have, I don't know, some sort of logic for routing that goes beyond your API? Well, if you think about the way that the API looked, it knew that it's forward slash products, forward slash ID. The only thing it needs in front of that is the server URL. Okay, so that doesn't change. So it's kind of statically defined kind of at build time. That's why, correct. And see in the client code that you get, like see here, I just knew up an HTTP client. I can actually set my base URL on that. I could run this code and aim it at localhost, stop the debugger and go back in and change that URL to be my Azure website and rerun the code and it will just point there instead of there. Yeah, I can actually do that. Cause like from the server port, whatever you call the scheme, from the scheme forward, it's not going to change. It's all described in that API file. Nice. Okay, so Brady, we're kind of running out of time here and this is so much good stuff. I'm really surprised and so happy about like all the progress you've made on the tooling for this in VS and just it looks so easy. Good. But back when I was dealing with REST, it wasn't easy. I didn't find it easy. It's still not as easy as I'd like it to be, but it's getting better. I think the end of this year, I'll be very proud. I think the end of next year, I'll be like, you know, on fire. So I just, I think we have a lot of good progress to be made and it's really good to see teams like Power Apps and Logic Apps and API management and everybody like kind of getting on the same bandwagon and just going like, let's just go forward. Let's just do the best we can. We know people don't always build clean APIs. We can't fix that, but we can make it easier for folks to make them ugly or harder to make them ugly. Yeah, right. So is there any, I know that .NET 5 and you know, .NET Core in general has had a lot of performance improvements over time and all the benchmark tests that keeps getting better and better. What about Web API? You were mentioning just regular like JSON over the wire, ACDP, but also GRPC. Like how does .NET 5 or 6 or whatever is the latest that we have available out there? Five. How does it stack up against like the past? The past? Well, 5 has gotten much faster. I mean, every single version of .NET Core has gotten considerably faster and more performant than the previous one. 5 is definitely not only, and this is exciting to see. It's not only like, you know, faster and some perf benchmarks than even 3.1 was because we were going thousand times faster than some framework tour at that point. But we're also seeing faster adoption. Like people are really responding to .NET 5, which is exciting to see. We're seeing curves that look more like hockey sticks than like gradual, gradual inclines. It seems that folks are not only gravitating to the new framework, but that adoption shows us that the move to 5 isn't as difficult. Like the jump from 3.1 to 5 is easier than the jump from 2.2 to 3.1. Easier than the 2.2 jump, et cetera, et cetera. So, you know, with each release, the performance not only gets better, but your ability to improve gets better too. In terms of the future, we're just going to continue to adopt things like GRPC and push that forward. There's some talk about some things with ACTP-3 moving forward and the REST API space. A lot of what you've seen me do today in web APIs, we're bringing to Azure Functions as well. There's some open source projects that are going to make it easy for you to output open API from your Azure Functions, which is currently a gap. So that'll be great because then you'll have that integration possibility across web APIs and functions, both written in .NET. So. All right, well, that is super exciting. Very, very cool, Brady. I'm glad that, because I remember with back in the day with SOAP, that was kind of slow. It was, it was. I'm very excited that the web APIs get to harness all the performance benefits that you've been putting into .NET in general. Yeah, it has been fun. It's been really, really cool. But yeah, it's been great. It's been a fun time to deal with it. I can't believe I've been working on all this stuff. I was looking at some of the prototypes that I did and the connected services for API. I think it GitHub in 2014, and I moved it off of CodePlux after it had been there for like a year, because CodePlux was going to go away. And now it's cool to see it show up in the real product instead of it just being an Oob and out of band. So it's been great to see. Well, fantastic, Brady. Thank you so much for coming here. And sharing this story with all of us. Thanks a lot. So to everyone out there, see you next time and have a great week. Take care.