← Back
IAmTimCorey November 2, 2026 37m

Intro To Webhooks in C#

Not yet indexed — Search & Ask will be available once this episode finishes processing.

Read full transcript 31 segments
  1. Communicating between systems, especially systems where you don't control both ends, can be tricky. One solution to this problem is a web hook. In this video, I'm going to introduce you to web hooks in C, show you why they are valuable as a tool to understand, and get you started building them. Now, if you don't know me, my name is Tim Corey, and my goal is to help you be the best developer you can be. Instead of faking it or pretending that prompting an AI makes you good developer, I will teach you how to be a confident, prepared developer, ready to survive and thrive in today's marketplace. This channel has over a thousand videos dedicated to just that. But if you're looking for even more, go to devforge.com. There you find free and paid resources to help you wherever you're at on your development journey. So, let's jump right in. And as you can see, I already have things running. Now, this is a very demoheavy uh video. So, there is a link in the description to get both of these projects. These are two different projects. And the goal here is to simulate the fact that you don't always control both sides of the equation. So, here we have on the left this red site, which is our external site. Now, of course, I'm controlling both of these, but this is a demo. So this external site is something that may be doing some work of some kind and we want to find

  2. out about it on our site. So my site is a site we control in theory. So let's make this really practical. If you were to go to devforge.com and you were to open up a um you know a purchase, you make a purchase for one of my courses. Well, I use a tool called Fastspring to do the actual purchase. That's because I really shouldn't have my hands on the money. That's a a whole incredibly complicated system for dealing with money. And there's a third party I pay for that service. But when that purchase happens, let's just say that's essentially the external site. This be representing Fastpring. The purchase is made technically on Fastpring. Well, how do I find out about it and do something with it? I get a web hook. So, what is a web hook? Well, there's a couple ways of getting information from external site. I could on this site, I could say, "Hey, you know what? I want to call out to external site over and over again and look for new data." So, I could from my site ping over to external site and say, "Hey, is there new data?" No. Okay. Hey, is it new data? No. Okay. And the problem is is that either I'm going to be bugging the external site over and over and over again in a way that is kind of overwhelming. And when I do that, I have to ask for all the data,

  3. not just the data about a particular transaction. I got ask for, hey, are there multiple new transactions? Give me all of those. That's one way of going about it. And that can work in some circumstances. But imagine if the, you know, the the way that the system works, it says, "Hey, you know what? We don't want to be overloaded with thousands of our customers all pinging every second for new information. So, we're going to limit you and we're going to say that you can't ask for data more than once every 15 minutes, which might not be totally unreasonable, but the problem with that is now my customers who are on my site are waiting on that 15minute window. may have purchased in minute two. Well, they have to wait 13 more minutes and that's not ideal. So, there is another way of going about it. So, instead of this site right here going out and saying, "Hey, give me data." And then, you know, and then pull that data back over to the site. Instead of doing that, we can do what's called a web hook. And what that is is we say, "Hey, you know what? This site has a an API."

  4. So an API of some kind or an API endpoint. And we're going to do is tell external website, hey, this is my URL. And when you have a new transaction, call that URL and send it the data. That's a web hook. So, the external site doesn't have access to my site. It doesn't have uh built-in code that's like tying into my site. It just knows I can call this website and send it data. That's all it really knows. So, that's what a web hook does. You may say, "Well, that sounds really simple." Yes, it really is. It's just that simple. It's the external site. You'll put in a a URL and on your site you process the data that comes from it. Now the my site doesn't control what the data looks like. So you have to figure out how to process that data. And the external site it doesn't know anything about my site except here's the URL call this. So the two systems don't talk to each other directly. Not really like they don't know about each other directly. they do talk to each other through a call. So, what we're going to do in this lesson is the basics of web hooks. Now, there's a lot more that you I want you to think about when it comes to security and processing this that you

  5. need to start processing and thinking about yourself. And we're going to do follow-up videos on how to make things more secure. But, I want you to think through what's happening. the external site is calling a URL and that URL really should be HTTPS. There's no reason not to. Um, in fact, there's really good reasons to do this. So, if it's an HTTPS URL, then the data being passed along to this site is secure. It is secure under that SSL certificate. So, there is no reading of the data. Now the URL itself, yes, that's readable by anybody in the middle or or something else, but the actual call um is not readable. Therefore, all the data in the package on the on the body of the message is secure. So from a security standpoint, the external site done, there's no security even at do. Now, on my site, you're going to have to have an API URL, and that API URL has to listen for calls from external sites. Maybe just one, maybe multiple.

  6. That's where things need to be a little bit more secured and locked down because what if somebody else got a hold of this URL? Well, they could send calls to that URL as well. and [snorts] they could send different packets of information and then that could be a security risk because you could be injecting bad information into it. So you still have to have to secure the client side URL and we'll talk more about that in future videos, but for this video we're going to keep that wide open where it's going to show the basics of web hooks. Then we'll get into locking it down, making it more secure and other options for your web hooks. But this is the process we're going to work on today. So, let's close down these uh websites. There's one, there's two. Um I'm going to show you really briefly the two sites. I've intentionally kept them separate, totally separate, separate solutions, separate projects. That way, it's very clear these are two separate things. So, my site, this is the the client site.

  7. This is the site that I would control. This is they're both Blazer web apps with just server side. So what I've done is I've added a model the purchase model which is item name item price and quantity. And then for uh pages I took out the weather page and I added in a purchases page here. It's blank right now. Nothing to it. And um the one thing I did change you notice the colors are different. If you go to main layout and expand that to main layout.razer.css, CSS. You'll see here the sidebar. I changed that to background color of dark green. I did the same thing to the other one only it's the background color is dark red. Okay. So, that's all there is to this this uh site is different. Uh I did update the nav menu to point to purchases. So, um but that's it. Was this a stock project? Okay. So, let's pull up our external site which has a little bit more but not a whole lot. Um it's the same thing. If we go to um component main layout.razer, we can see the dark red there. Um and then the nav menu, we changed to purchase items. And again, we deleted the the weather page, but we add on the purchase items page.

  8. This page is a bit more. By the way, we have a model here, purchase model, which does have some validation on it. Uh required minimum length, uh a range with with a decimal type. By the way, if you're doing a range, notice range down here is 1 to 10 for an integer. No problems. But for a decimal type, you have to do type of decimal and then put things in as strings, the minimum and the maximum. And the reason for that is because this range only takes double and integers. And if you want other types, then you have to specify the type and then you put the values for the the range in as strings. they get converted and then they uh that is the enforcement of the range. Just so you know that's a little bit different um in how range works. Okay, so that's the purchase model. Now we have the purchase items page which is an interactive server page and I have here um if the submission text is false uh is not I'm sorry if the the submission text is not uh null or white space then show a submission text that's going to say hey this was submitted successfully.

  9. And then here's an edit form. really basic edit form with some validation on here for item name, item price, and quantity. And then the submission right now is just, hey, wipe out the model and say yes, it was successfully submitted. Doesn't do anything yet, but um this is simulating what that external site would do. So, we go purchase items and we say uh test item and we say the purchase price is $1.25 and we purchased two of them. And we hit submit. It says the purchase has been successfully submitted even though it doesn't go anywhere right now. This is just a shell the starting uh point for our demo. Okay. So, what we want to do is we want to be able to uh set this up as a a web hook sender. This is the thing that's going to send out the the the calls to the API endpoints.

  10. To do that, let's come down to our program.cs. I'm going to add uh one more thing to services and that is builder.services add httpclient. Okay, that's going to add the ability to call out to our um client. And then on this purchase page, we're going to add a inject for um IHTTP client factory. Always do a client factory here. Um and we'll call it uh HTTP client factory like so. And then we're going to come down here and in our purchase or submit purchase, we're actually going to call out that web hook. So we'll say um var client equals http client factoryclient and then await client.

  11. Add whoops. When I said await, it um made this async task instead of void, but then it moved my cursor up there. Um await client.post as JSON async. And we're going to pass in the URL and our model. Now, what is the URL? Um it's going to be https localhost colon uh 7170. And let's make the um the endpoint be uh web hooks/purchases. Now, we don't have that yet, but that's what's going to call when we're ready. So, that's that's the only thing we do on the external site is we say, "Hey, make a call to this endpoint and pass in the model." Now, again, there is no security here. That's okay for the most part. Um once we get you know in you know more videos in this we're going to talk about hey we could add some more things here to make it safer for resubmits and for uh failure issues.

  12. Right now we're not even dealing with failure. We just assume it's going to work. Uh this the very basics of web hooks. This is just an intro. Okay. Um but this is it. Now you might say well Tim you're modifying the code of the external site. that doesn't seem like that's something a external site would do for me, right? What happens typically is the external site will say, "Hey, do you want me to call a web hook for you when these actions happen?" And you say, "Yes." And it says, "Okay, fill this form out with what action you want to capture and then what your URL is to call." And that's what would set up web hook. So, it' be a a form. You'd fill it out. it it store this information in the database somewhere as well as what to submit because right now you have one form that we're submitting uh with one set of data but you know for example for me it's there's purchases and then there's subscriptions so if you subscribe to the let's say dev pass well I need to process that differently than if you purchase the C master course so how we deal with that is a separate web hook potentially we can do one web hook for both um in our case, but there's sometimes we don't. We split those up in a different web hooks. And so the the site lets us say, hey, what event do you want to capture? And then what do you want? We're going to call for that web hook. So in this case, we're going to call this thing uh for this one event

  13. which is going to send this data over. Okay, that's all the external say has to do is just call this when an event happens. In this case, the event is the submission of our form. Okay. So, let's go over to our my site demo and walk through what do we do over here to actually capture this information. So, what I'm going to do is um on my site, I'm going to do control shift A and say services. I'm going to add a service. Um let's call this uh purchase store. So what this will be is it's going to be a a class you put in dependency injection as a singleton and then use um for that way if we have more than one web hook we can capture more than one value and then show all the values on the page instead of just refreshing over and over again. It's a kind of a cheat, a shortcut for instead going to the database, which is where you'd probably do this purchase store here instead, is you'd probably store this in a database somewhere and then display the database records instead. But for our case, we're going to kind of shortcut the database here and just do it in memory. Uh, so we're going to say let's do a uh a prop and we'll say concurrent uh Q.

  14. concurrent Q here which gonna add a using directive for system.colction.conurrent and we're going to say concurrent Q of uh purchase model which will add that using directive as well and we'll call oops we'll call this um uh purchases and we're going to make it read only. We're not going to let people modify this in our application. And we're going to initialize it to be a new concurrent Q. Now, why concurrent Q and not say a list? Well, concurrent Q, if you mouse over it, you'll notice that it says it represents a thread saved safe first in first out collection. So, that way we know that we were processing things in the correct order. If two come in at the exact same time, it'll make sure that it process it well almost exact same time. It's going to process uh both of those but keep them the right order.

  15. So, we're also going to say public uh event action. So, an action is a type of event and we're going to say purchase added. And this will allow things to subscribe to this purchase added event. so they know that the Q has been updated. Last one is public void add and we're going to pass in a purchase model. We'll call this purchase. And in here we're going to say purchases in Q purchase. That adds it to our um concurrent queue. And then we're going to say purchases added. Let's try this again. Purchases added. If it's not null, dot invoke. So it's very important when you do um events that you say, hey, if someone's listening, then invoke it. But if no one's listening, don't don't invoke it.

  16. So the um the list here is going to look for hey is anybody subscribed to the purchase added event? If someone is then go ahead and invoke it. But if no one subscribed if no one's listening then don't invoke it. Okay. So this is our store. What's going to happen is every time we get called and we say hey there's a new purchase that came in. We're going to add that to the queue. So, we take we're going to call it we're going to call this ad. We're going to incue that purchase in a list and then we're going to say, "Hey, let anybody who's listening know this is an event that happens internal to my site." Why? Well, because I might have one or more, actually zero or more, but one or more places where I'm listening for new purchases. And when the web hook captures, when the API endpoint captures the new purchase was made, I want to let my entire application know, hey, there's a new purchase in case anyone wants to know that and do something with it immediately.

  17. Okay, so that's our store. Now, we need to do is we need to add that store to our our um services. So, we're going to say builder. Wow. Builderservices add singleton. And we're going to say purchase store. We're going to add that using directive up top. It's you have to hold shift down to have your u open and close parenthesis not always get 90. Okay. So now we have our purchase store added as a singleton which means every time we call it we get the same purchase store which is important. All right. Now, what we're going to do is we're going to add our web hook. And to add our web hook, it's really not hard, but you might think, wait a minute, this is not an API. This is a a Blazer a Blazer really technically a Blazer server, but it's a Blazer web app. Um, where do how do you do an API?

  18. Well, remember that whether you're doing Blazer web apps or you're doing Razer pages or MVC, it's all the same. So, it's all based upon a web application, which is an ASP.NET core host. That's kind of the foundation of all of this, which means we can use things other than just the main product type we're in because the foundation is ASP.NET Core, which means down here after map static assets, we can say appost. And remember the web hook we called it uh slashweb hooks slashpurchases. I believe we made both of those. Let me just check real quick here. Um I believe we said web hooks and purchases. Yes, both plural. Okay. So that's our map post. And then we're going to pass in the purchase model.

  19. We'll call this purchase. And we're gonna pass in the purchase store. And we'll call this store. And we'll have our arrow in our curly braces. And we should put our semicolon at the end before I forget it. So in here, what this going to do is going to we're going to have a a post call. This is an API call and it's a post which means that the the contents the data will come through in the body which secures it so no one can read it even if they can see what actual URL we're calling. So that's going to come through in the purchase model. Now notice that my purchase model maps what was the original purchase model and it before you kind of go in the comments and say hey this should be a shared project. No it shouldn't. Um and I want to make this clear notice that this doesn't have any data validation. Now it could and we could do validation on it but um that's not really wise when you're doing external call because of the fact that if the external site decides to change the data model well you don't want to say no I can't take that data if if they change it slightly. So I don't put validation on my models here because I get what I get. So I just have to check the data before I do anything like put

  20. in the database etc. But what that means is this purchase model is different than the purchase model from our external site. That purchase model is about validation. It's about you. It's about a front-end uh userfacing model that has to be validated. That's different than this model, which is why I don't do a shared project. Otherwise, what you're trying to do is is try and force two to be the same and they're not. And yeah, you could ignore the validation. That's that's just bad. Don't do that. Okay, so they are it is a different model, but it looks the same. It's the same shape. Now, I don't have to make it the same shape. I could drop off quantity or I could drop off price or, you know, I could change this model if I wanted to. It would still map over what's available. So just note that sometimes a lot of times with my web hooks when I am capturing web hook from an external site I won't capture every bit of data. I might capture only part of that data because I only need part of it. So therefore I don't need to capture all this extra information. I just capture what I want. So just know the models are different. Okay. So I'm capturing this purchase model. That's the shape of the data I'm expecting. But then notice I'm also passing in purchase store which comes from dependency injection. APIs are smart enough to know oh that doesn't come from dependency injection therefore

  21. it must come from the the uh body. Whereas this I can find dependency injection therefore I pull it from dependency injection. Okay in the post really simple we're going to do is say store add purchase. Now I do want to be a good citizen and return results. Okay, so that just says that yeah things were successful. Here's a 200 back. Now note that there is no error checking here. There is no validation here. There's no, you know, making sure that it processed properly. This is the intro to web hooks, not the the in-depth everything to web hooks. you still have to think about making sure that you handle situations where bad data comes through etc. So in this case we're just returning okay because we're doing a simple example. Okay that's it. There's our API or at least our endpoint and that's what the external state's going to call and everything else we're we're good. So now we just have to actually process that or or display it on the purchases page.

  22. That's it. Okay. So let's do that. So let's start with um making this u uh render mode is going to be interactive server. And then we're going to say implements and we're going to say I disposable which we're going to get into but this is when you're dealing with events you should probably almost certainly implement I disposable which I don't know if this does this uh it does nice uh it doesn't always do this properly um but you can you want to implement I disposable whenever you're dealing with events. So, we're also going to inject the purchase store. We'll call that store. And we have to add our using directive for that, which I'll just add a using directive instead of putting it into uh imports.

  23. Okay. So, let's come down here to our body. Um, and this is important to dispose of this, but we're not going to get there quite yet. So instead we're going to do is say protected override void and say uninitialized. And in here we're going to say store purchases added. We're going to subscribe to this and say plus equal let's call it onpurchase added which we need to have a method for that. So private void on purchase added. Okay. So what are we doing here? We are subscribing to an event. The purchase added event. Remember the purchase store has this purchase added event that gets fired whenever you add a purchase.

  24. Okay. So why do we have the dispose? Well, because we want to take this exact same line right here, copy it, paste it down below, but change it to a minus equal. What does that do? It unsubscribes this page from that event. That way, we are sure that we remove any any subscription to any event instead of having that live in memory. And so, we'll make sure you always unsubscribe from any event that you subscribe to. And this dispose makes sure that we are unsubscribing whenever the page closes. Okay. So what does the purchase added do? Well, it actually just says invoke a sync state has changed. That's it. So what does this do? Well, we're going to have up here in our our HTML section, we're going to um have a a a list of all of the purchases that have been made. And that list is based off the store. So that store which is in right here the purchases. So purchase store.purchases purchases. Um, that list right here is going to get updated

  25. outside of our page. So, it the ENQ happens outside of our page and potentially not even on the same thread. So, therefore, what we need to do is every time this event gets fired saying, hey, a purchase has been made, we just invoke asynchronously the state has changed. Now, we're not actually capturing the task from this. We're just saying, hey, the state has changed. And what that does is when we're back in this circuit um on this correct thread, it's going to say, oh, there's a new change to the uh purchase stores purchase list or concurrent queue. Go ahead and update the page based upon that. So that will make sure that our page gets refreshed. So let's go to purchases. We're going to say uh first of all if uh store.purchases is empty, then we're going to say let's just do a paragraph that says no purchases yet.

  26. But let's have our else here. So this is where we're going to actually display our purchases. So, let's just do a simple uh table class equals table. By the way, that class equals table, that's bootstrap. Um, and then we're going to have a t head and then a t or row. So, tr and then th uh for item name. And we'll do two more. We're have item price and quantity. All right. So, that's our our header for this. And then we'll do a body as well. So tbody. And then in here, we're going to have a for each that says var purchase in store.urchases. So for every purchase that's been made, every purchase entry, then I want to say TR for a row and then TD for a a data entry and say at purchase item name and then let's uh duplicate this control D by the way duplicates. So this is going to be uh item price

  27. and uh let's just do two string here with a uh C for currency. Uh so we're going to format that as currency and then the quantity. Okay, so really simple. It's just it's just three items in a list. That's it. But we're displaying these if a purchase has been made. Okay. So, let's run this. Let's get this going. And we're going to come over here. We're going to put this on this side. And then what we'll do is um let's go over here and get our external site as well. I will um minimize this and we'll put this Whoops. Um over here. Okay. So now we have our external site and our my site. [snorts] So let's come down here. We have no purchases yet on my site. But if I make a purchase, let's say test item and it's a $1.25 and I make two of them and I hit submit. Watch on the right hand side. As soon I hit submit, test item shows up.

  28. That's the power of web hook. So the external site also needs to know is that URL to call. That's basically it. Um, and now it needs to know which data to send to it in case you have more than one option for web hooks. But the your site can process those calls immediately. So again, um, if I were to say, and sorry it keeps flying out here. Um, Tim's demo and I'm going to say this is a $5.67 item with um, let's go with uh, five of them. Okay, I hit submit again. Immediately that item gets listed on the page. So that's how web hook works is the external site just knows about a URL to call and what data to send it and then the the uh recipient site, the site that you control, captures that web hook and does something with the data. In this case, it just puts it in a list. So that's how again that's the basics of web hooks. Now again you can have more than one site listening for these web hooks. Now if we were to do this um let's see if I can can do this.

  29. Yeah, there we go. So now we have two sites and let's just pull this out. And now we have this site here. And we will shrink this site down. So you can see there's two different uh pages both listening. It's the same site. But if I were to say um another test and I were to say uh 890 and I want one of them and I hit submit, it shows up on both sites. But it doesn't have to be just your website. this has that this external site is calling. This external site could call eight different places. It could call eight different sites, eight different URLs and they could all process those web hooks. So web hooks are very powerful. They're um tricky to get right sometimes because of the security and because of resiliency, but otherwise they're a very powerful tool that for example I use a lot because Teachable has web hooks. That's the site that runs my courses. And then uh Fastpring has web hooks. That's what does the payments and then my site processes these. I also use Zapier. If you've ever used Zapier, that can process web hooks um and do something with it. Now, this is a very simple demo because it takes so long to set up and show. That's all I'm going to do for today. But we're going to talk about things like securing this data so that

  30. it it comes through properly and um is um is even more secure and is not encrypted because it's already encrypted HTTPS or SSL um but to make sure that it's the right data and make sure it goes in the right place etc. Um so we're going to work on locking it down. We'll also work on um doing things like resiliency so that if you um if your site's not listening, what happens to the web hooks and on the opposite side, what happens if the web hook gets called more than once with the same data. So again, those are future videos that are going to be coming out, but um this is intro web hooks and how it works. Okay, the source code for all of this will be down in the description. Thanks for watching. Leave your comments and questions down below. If you're looking for what specifically um to do with web hooks or you know what other things you might want to think about when creating web hooks, let me know down in the comments. I'll try and create um either videos or at least reply to you with um potentially an answer or a suggestion going forward. Thanks for watching. As always, I am Tim Corey.

  31. >> [music] [music]

No summary available yet.

View original episode ↗