Intro to Blazor in .NET 8 - SSR, Stream Rendering, Auto, and more...

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
in net 8 Blazer has become a full featured web framework that is modular and adaptable to your needs over time in this video we're looking at how Blazer works now and how to utilize serers side rendering mode stream rendering Blazer server components Blazer web assembly components and components that transition automatically from server to web assembly using auto mode that's a lot now before we dive in I want to share a couple things with you first if you're interested in improving your C skills be sure to subscribe to this channel there's lots more net8 videos to come as well as a whole Library full of other C topics as well second if you're looking for more free C resources go to IM timc cory.com and go to the resources tab you'll find my podcast which is advice for developers in the industry or getting into the industry on how to become better as well as a c project p page and much more and finally if you're looking to dive deeper into a specific C topic I have a variety of courses that can help for instance I just launched today the Blazer in.net 8 course so blazer from start to finish course that covers all of. net 8 it covers all this new stuff we go in a real depth into how to work with us in the real world so not only you receive a worldclass education whatever topic you buy a course in but you'll also help fund my free content so everyone can have a great education c not just those who can afford it so let's Dive Right into Blazer in.net 8 so I am going to create a new project no I am using the preview version of visual studio just because I'm recording this right before the launch so the launch hasn't happened yet it will happen by the time this video goes out and you can just use the regular version of Visual Studio as long as you've updated and and make sure you have net 8 which will come with that update so we're going to choose the Blazer web app project this is the new single project for everything it has SSR it has stream rendering it has server it has web assembly it has Auto so it's all in here let's choose Blazer web app or call this intro to Blazer and the source code is available if you go down to the description there's a link you can download the source code what's going to do it's going to ask you for email address it will email you a copy of the source code so inbl your app hit next and the framework iset 8 now yours won't say preview mine says preview because it's not yet out but we're going to choose no authentication type for now we're I'll leave that for a separate video yes to https the interactivity mode this is where you say hey this is the kind of stuff I want now if you say just server what that's going to do is it's going to have just Blazer server components which means you won't be equipped for web assembly or Auto if we choose web assembly we will be equipped for just web assembly and auto you have both I would encourage you that if you're looking for any interactivity at all just put Auto now there is a bit of a downside in doing that in that it's going to create two projects instead of one if you want just one project really simple and you don't ever want web assembly then you can just choose server that gives you just one project but the the two projects aren't that difficult to navigate and this is where you can have that flexibility to expand your app over time to include other uh render mode types so we're going to choose that this is not mean that your application will always be server or web assembly you don't have to have either of those things in order to get your web application off the ground this just prepares you and puts the Scaffolding in place for server and web assembly so want make sure we're clear on that interactivity location you have per page or component or Global this where get to choose do I want to set a global setting for server or web assembly or Auto and my suggestion is to say no you want per page or component you want every page to specify how it's going to render and the benefit there is that by default if you don't specify something it will get rendered with serers side rendering meaning you will have all the speed in the world it'll be very very fast it be very very efficient and you won't have any the overhead of an open connection with server or with the downloading of the source code like we have assembly so that way you could just choose I want to add some overhead in order to have more interactivity so that's the way I prefer to do it we're going to include the sample pages and that's because this will you know give us the the best view of how this works we're not going to go deep into code today necessarily um so this will gives us a starting point rather than trying to write the code ourselves and then this checkbox I want to leave unchecked so this check boox a little confusing it says do not use top level statements and that's unchecked so we're going to use top level statements which they have been a thing since net 6 I would encourage you to leave this box unchecked so you use the current and modern way of doing things but if you really really really want top level statements to go away then check the box hit create and like I said this is going to create for us two different projects so we can close out of the the initial uh pages and here we have intro Blazer and intro blazer. Cent so what's the difference here well intr Blazer this is where all of our serers side code lives and all of our server side or Blazer server components will live so we look at our components we'll see here that under Pages we have the homepage and we have the weather page so notice the weather page has code in here we're going to run code against this but it is not running with blazer server or Blazer web assembly since that is true we can put this on the server side that way our this code down here will never go to the client the client will never see the C code and that's not true for Blazer web assembly projects web assembly projects send the C code granted in a dll but they send that c code down to the client and the client could read that code directly so that's that's true of all client side fully client side project types you know angular react they use fully client side code which means you can read the raw JavaScript yes you can try obfuscation you can try minification but the reality is you can reverse those very very easily so you're always going to put your actual source code on the client if the client is running fully client side so just just note that but in this case we're in the server project and the server project kind content does not go to the client so the homage no no specification for what type it is so this is going to be a serers side rendered page so everything here is serers side rendered or is Blazer server if it's specifies it's Blazer server now in the client we have pages and there we have the counter we're famili with the counter if you're familiar with the the um the components from a normal Blazer project Blazer server blaz wave assembly they both came with a counter component as a demo we still have that but it's in the client project and the reason it's in the client project is because it requires some client side in our activity and it's not just Blazer server it's Blazer in this case Auto so we have this attribute up here it says render mode interactive Auto this is telling the the Blazer system that this component will render with blazer server to start and then in the background it will download the source code and then the next run it will run Blazer web assembly so this way we can have our component that changes over time but because it does change over time to web assembly we can't have that in the the main project because of the fact that it will download the source code to the client and so that's goes in the client project okay so let's just run this real quick because I want to show you first of all it seems very very similar we already have seen with blazer server for the or or Blazer assembly for the demos but at the same time it is different so let's see how it's different once it launches okay let's load the page up here and this looks a lot like a typical Blazer project we have hello world we have our counter which we can we can start clicking on and when we do it starts increase in the value and then we have the weather app which if you notice let's go back to it notice it says loading watch real quick it says loading and then it loads the page but wait a minute if we go back to the weather page let's move this off for a minute go to weather there is no attribute at the top here it says attribute stream rendering is true but that's it there is no attri attribute like the counter has for render mode it's not render mode interactive it's Auto it's not render mode interactive server or interactive web assembly so what's this stream rendering well this page gets loaded and built on the server so this is all server side rendered as is the homepage the homepage is serers side rendered but yet the weather page changes over time so we get the the loading first and then it has the weather in there how' that happen well what happened was when the page was built on the server and compiled we come down here and we have an await now this is an await task. delay just to put a delay in here so you can see that loading page it's just a simulation or a demo so and actually we can probably increase that um over to make it like 2 seconds something like that make it easier to see but what happens is because there's no wait the page gets rendered as if it's null to begin with so we have the loading dialogue and then because we're doing stream rendering it will get the new values when they're done and it will inject them just in the spot in that component's space which means that it will not disrupt the rest of the page it's not a full page reload it's just reloading that component when there are new values to put in there it's a lot like a client side application but there's not quite the same interactivity so this allows for a much more flexible application that feels like a client's application but it's fully server side and it's doing very very little work on the client and it's not opening BR a full connection back to the client now I want to demonstrate this doesn't kind of show off how this works and and what's going on so to start off what I'm going to do is I'm go over here to our layout and go to the nav menu so this is the navigation and inside the navigation I am going to make a mess I'm going say div with a style equals background color of white all right and then in this div I'm going to put the counter which notice I have in blazer. client. pages. counter so I can shorten this if I put this using directive in my imports so using and there's the the link of the pages I can get rid of then this okay so with that now notice that my my server is referring to a component in the client that's okay but the reason I'm putting this counter here is because I want to show off the state so let's hit no here and find out uh using not oh we don't have it's not uing it's using if you don't spell things right things don't work quite right let's um run this again and see if we can get it to run there we go so now I got the really ugly counter in the middle I put the background of white so you can see it otherwise it takes the background of the purple and you can't see the the the words so if I click the counter and I have a value of 10 right and then I come over here to the weather page notice the value of 10 did not change even though I loaded a different page so I go a different page and first of all this counter is different than that counter so you can click this value and put it a six but notice that this did not get reloaded this is because of what's called enhanced navigation so enhanced Navigation says that when I navigate to a new place and notice that this Navar is always going to be here it's just this inner component that changes when I go there that it's going to just inject the component into this section not refresh the entire page this is something that server side uh systems like PHP or MVC or razor Pages they don't do they reload the entire page every time you go somewhere new or update data well with the stream rendering enhanced navigation that's not the case we can render just the component that changes so that it's not a full page refresh when we go somewhere new so that's one one benefit but then this also helps with the stream rendering helps with this weather component because notice that it says loading and that changes just this component not the counter value which is currently at 10 let's turn this all off so the easiest way to turn it off let's close out of navigation close out of Counter and I'm going to turn off the stream rendering so this will no longer render the uh the weather page as stream rendering so by just turning this off you see see what's going to happen when we try to load the page so first of all we're going to increase our counter now it says eight we're go to the counter page that still works we go to the weather page and do you notice the the delay and there's no loading here let's make it a lot more clear so I'm going to change this from 500 to 2,000 that's two full seconds so we're putting an intentional delay and getting our data back for two seconds just to show off that in fact there is this delay so we're going to change the the counter page now it says nine we'll go to weather one two loads okay so I didn't click again it just went there after two seconds that's a little bit frustrating right that's what happens when we don't have stream rendering turned on and we're asking for asynchronous data from say an API that might take a while to respond is we have that delay in it it's not something that users want to see they want to see the immediate page load and know that something happened otherwise I click that weather link over and over and over again and say hey your stuff is broken so this is why stream rendering is so valuable is because it can Rend the page initially with some placeholder data where the the um asynchronous call will finally populate and we can get that page rendered very quickly and the user can see that something is happening but let's go even further notice that the counter hasn't changed it still says nine that's because of enhanced navigation so let's turn that off which we're going to go all the way over here to app. Riser this is the this is your actual document so this is where the actual HTML document lives we cover a lot more in in the course about hey you know what this is a very small um Library bootstrap is but we make it even smaller in the course by updating it which it's down to I believe 37 kilobytes uh which is tinier than every one of your images uh or any one of your images and yet it's very very powerful and I'd highly recommend that you still use it but we cover you know what app.css is and how this is a per component style to override app.css but down in here under the routes this is where our actual page gets rendered we have this right here script and this is blazer. web.js this is the the script that handles all the Blazer stuff when it comes to the stream rendering enhanced navigation and more if we comment this out and we're going to run this application again so I've taken out the blazer. web. JS file and launch the application and notice it still looks like it works and in fact if I click the click me on the counter nothing seems to work okay there's there's no interaction here and on the weather component okay you can you can load it but it's you know it's taking a long time so we can render our site without that JavaScript without any client side interactivity and our components still load they're just slow if they're waiting for asynchronous calls but it's just a fully server side project now I would recommend not doing that because this interactivity is as you can see it really changes how your application works even if you are just fully server side rendered so if we forget from minut that you want to do Blazer server Blaze we assembly and say Hey you know want to do server side rendering we can take out JavaScript well you could but then when you go to weather page well it's a full page refresh and your your updates have to wait until that asynchronous call is done before they load the data so I would recommend against doing that keep that JavaScript in there and then you get the enhanced navigation out of the box and whenever you want it you can also have stream rendering so that now your components update cleanly the whole page doesn't have to refresh and you can see the the loading screen let's just update our counter um the five and go to weather notice the loading and then it loads so we can go right to the Loading page we can come back go right to the Loading page go right back we can go to loading page and it loads the data when it's done and it doesn't refresh the rest of our page so this is where these new tools the the stream rendering and hand navigation are really really powerful and you can do some enhanced navigation or enhancements on your forms as well for form posting so really cool stuff there um when it comes to creating new components you get to choose but if you're going to have a component that might be web assembly or Auto I would encourage you to create the component in your client project so you can just you know control shift a and call something . Riser so demo. Riser and there's your new component and then you can utilize this component um let's just put a a paragraph hello everybody okay and then you can just you know pop that component wherever you want so let's go to the homepage and we're come down here and say demo and now we can have that demo component on our page and right now it's serers side rendered so it's not even being rendered um with anything special there's no um there's no stream rendering e even it's just putting the data there and that works and then you know down the road you can say you know what I kind of want to have some interactivity so I'm going to put an attribute on here and I'm going to say the render mode is and I recommend saying Auto all the time because this is the best of both worlds now there's always going to be the it depends okay whenever you you see someone that says okay it's always this that's a problem my recommendation is you start from here so start Auto think about you don't have to like build your component yet but think about it as by default we're going to do auto but is there a reason to only do server or only do web assembly and there can be there are certain components that maybe you want to have directly access to database that you say you know what they should be only server and they should live on the server side but if the default probably should be Auto because that's the one that's most likely going to give you the best benefits and that's only for if you want interactivity so if you want to make this into our own counter we can say int Uh current count equals zero that's a private in we can mark it as private and in Blazer if you're not familiar your code behind this code right here which is technically a code behind even though it's on the same page it's still a code behind in the actual behind the scenes the code behind everything is private and yet can be access on the page so that's the default you want to do only make it public if you're going to be um making a parameter in or out okay so we're going to say uh paragraph the current count is at current count like so and then we'll create a button down here button we'll put a class on it BTN BTN D outline D primary this is bootstrap by the way and we'll close it off for now and say increase count like so and and then we'll create a private void increase count method and we're going to say current count plus equal let's start with one um like so and then we will call this so at onclick equals and this is a delegate this is going to uh why you don't put the open and close parentheses it's not calling this uh as a method it's calling as or it's putting in as a delegate that will then get called okay so it's a little bit different but beond click we're going to increase the count and we'll render mode act Auto that's really all we need to do unless I forgot something but I don't think I did um it's probably just G to look poor because of the fact that I didn't really do much um styling but so we now have our hello everybody our current count is zero let's zoom in here a bit more um and we're going to say increase count and there we go there our counter goes up every time I click it and we have our own little counter component we've added that auto uh render mode so that this can now be changed for right now it's be server and it's going to download in the background it's PR already downloaded and now it's going to be web assembly the next time it runs so really cool stuff there let's go through now uh I want to talk through the various parts because we cover this in the course but again I try to cover a lot of stuff for free because I'm not about just the you know here's a teaser now buy the buy the full stuff let's talk about the full stuff because I think it's important that you understand this when you're working with blazer so the start of any application is program.cs this is where the start happens and we have a typical program.cs with our services first and then we have our use static files use anti-forgery this is something newer that what it does is when you create a form it's going to create a hidden field on that form that has the um a like a key in there it's it's a it's a very long string and that's hidden and it'll get posted back with the form and this just proves that the user went through the form on your page and didn't just try to hit the API directly so anti- Forge is a great thing it's built right into edit forms so if you're using the Blazer edit form it's built right in you don't have to do anything if you use a form and turn it into a Blazer form then you have to add the anti forer token which is very easy to do okay now app. map razor components it starts at app so under components you'll see the app. Riser this again is your entire page this is your actual HTML document and the only one you'll see here the rest is going to be partial things that you put typically in this spot right here now once you've got the components since we said Auto it's going to add interactive server render mode which is Blazer server it's going to add interactive web assembly render mode which is web assembly and then it's going to add additional assemblies which is our client project now it says type of counter. assembly what that's doing is it's saying hey I just need to know some uh some file some um thing in that namespace so it it knows the counter is there so it's going to call that but it's actually getting the Assembly of counter which means the entire project so everything in there including demo will get pulled in you could also say type of and reference the imports. Razer file instead and that would work okay so that brings in the entire assembly so it gets everything gets mapped properly for for our um for our routing okay so that's all there is to starting up your project then we go to app. Riser that's where all of our actual HTML document is which means if you wanted to add some more meta information which you probably should you would go there probably there is this Head outlet here which allows us to put more head content on a per component basis that allows us to do things like change the title or to change other meta information like the description on a per page basis which is very very good for search engine optimization for when you have a page you want to be sharable that's going to show up nice on say U you know Facebook or Twitter or in Google search results or whatever else to show up nicely with a nice image and a nice description a nice title that's where you would set that all up is on the per page component most likely so we have our routes we look at routes. Riser we'll see that we have our um our routing and how to the found context and the routing the one thing that's important to note with this new blazer web type is we have this thing called found this is a little bit Legacy in the fact that this is only we only use found found now in the new blazer web app there is a tag called not found and we used to use this in the previous Blazers to put our 404 pages to say hey page not found we can still do that in the the Standalone Blazer web assembly project but we don't do it here in fact this is not used at all in our new blazer web app you would create an actual 404 page not uh create a a razor component like that for and you don't put there for not found okay so just kind of a quick note there now when it comes to our layout we have our main layout and this is the typical structure this is pretty much the same as has always been as is the navigation menu it's pretty similar um this is where the navigation menu gets set up for um putting navigations on pages which if you notice in the main layout we have nav menu so that's the component which is the navigation menu and if you want to get rid the navigation you would just delete this section and there you go there's the rest your body goes right here so again there's an about bar at the top you can get rid of that by deleting these three lines from lines 9 to 11 because that's just part of the main layout that you can change you have full control over how this works now we have Pages here we have error home and weather you won't have all of these if you're using the um the template without the um the sample data but note that everything in Blazer is a component so even though we have an app page here we could still use the home component somewhere else kind of like this our demo is being used and conversely our components can be pages but they don't have to be this demo component right here there is no page direcor at the top so you can't access it by doing our URL demo in order to do that you'd have to add that page com page uh directive at the top page and then say slash demo or slash demo slashy demo and that be the full path whatever you choose here you can have more than one of these and you can even pass in data or get you know pass in data um or have default data on those routes as well so lots of cool stuff you can do there with your routing and then we have our app settings. Json in the main project this is where you would put things like connection strings or other secret information and yes we still have the concept of user secrets so you right click on your project and say mag user Secrets this Json file which is not part of your project it's only for your local machine but it will override with an app. Json that is the place to put anything for local testing or local development so I encourage you to use that and just note that's in the server project it is not accessible from the client project and this is where things can get a little tricky let's um let's figure this out okay so I'm going to inject the I configuration I'll call it config now in app settings. Json let's put a a new node where I say um demo info and we're I say this is our demo info from App settings. Json okay so in our code now we're g to have a um a private string uh demo info we'll call the same thing we'll start off of the empty string and we're going to have a new paragraph that's going to say at demo info and I'm going to create a pro U protected override oninitialized I'll use the uninitialized since there's no async call being made and this will get loaded once the page is loaded so I'm going to say that demo info equals config doget value and I believe by default it's string but let's just um do anyways and we're say uh demo info I believe that's the the case I'm we use let's just look I like to be consistent it is okay so that's going to put the string from the app settings. Json file into to this string which gets displayed on the page this is on the homepage let's launch this so when this launches what do you think is going to happen Okay well it says this is our demo info wait what happened we we had more information on this page let's launch it again and see this now we're in development mode which it turns off a lot of things but if you watch this is our demo info from apps. Json and it goes away so what happened well the component initially rendered as Blazer server and like I said because we're in development mode with Visual Studio that kind of changes and tweaks how a lot of these settings work so it's uh it's not going to save our web assembly information not going to cach that between calls otherwise what would happen is it'd be very hard to debug because we'd be using the previous version of the component every time made a change in so it's going to always refresh that cache and start us over at Blazer server and then launch Blazer web assembly after it's downloaded so the page initially the component initially for demo launched with the uh the Blazer server version and Blazer server has access to the configuration however Blazer web assembly does not so when it's switched over from one the other it reloaded the page and wiped out this value now it kind of it handled it gracefully because there's technically IE configuration on the the client side as well it's just that we don't have anything in that configuration because we're not storing anything sensitive there therefore we didn't put any apps setting. Json file in the project but because of that transition it ends up with an empty value and it overwrites what was in there because we've switched over to the Blazer web assembly mode so you see something quirky like that it's probably because you're rendering it in a way that the web assembly does not have access to something that the server does let's change this interactive mode over to server and now let's run this component again and when we do we'll see that it maintains this our demo info is from App settings. Json this is still here and you we can we can play around changing the account it's still here it's not going away if we change this again from server to web assembly and launch it we'll see that we never have access to this data so we we don't see the value well actually we do see it temporarily in fact we refresh this again it shows up and it goes away well why is that because the first time it renders is actually rendering on the server even though it is web assembly so there's a little bit of a difference there it's a little you know little frustrating there but at the same time What showing us is we don't have access to it all the time and in fact if there is something that let's change it back to Auto if there is something that we can only access on the server that doesn't have a equivalent on the C client then it will crash so we need to know that because I configuration has an equivalent on the client but not everything does for example if we talk directly to SQL Server well that'll work on a server but not on web assembly it will crash that I think is probably one of the biggest gotas when working with these systems is when you use Auto you have to remember that it's going to be web assembly therefore it cannot have direct access to a database it cannot have direct access to your secrets it can have direct access to your app settings okay so now you've seen that let's close all these tabs and go look at the client project we have the server project and that's you know pretty simple but we have the client project and in here we have our Pages which we've seen and by the way the naming Is Not Great inside for our folders We have components up here with layouts and pages and then we have just Pages down here but they're not all pages they're some components so you might want to change the name a little bit it's not going to hurt anything you don't have to have a specific you know call it you don't have to call it Pages have inside there you can call whatever you want um and then it'll be picked up just fine but just know that the name is not great but we still have our imports. Riser notice this is a different imports. raiser that we have up here in our server project so this is different so you can have both um this one down here in the client project applies to the client project so if you have a using directive in the client project it won't be applied in the server project okay we also have a program.cs which is very simple but we do have one why is that well because there are times when this will be launched independently in fact if you run a component as web assembly this is what would be used so this is what's going to be used for running our client fully client side C stuff so just note that that will be important to understand you might have to tweak this file as opposed to the other program.cs file if there are certain things you'll need for web assembly okay finally there is a www route in both of these projects projects so we in this www route we do have an app settings. Json which this is for the client side and it just has logging information again you should not put anything sensitive here the client will be able to read all of this text so do not put connection strings do not put Secrets because web assembly should not have direct access to a database anyway you need to talk through an API which This Server project is kind of an API okay so in our server project we have www root and this is where we have the bootstrap by the way um the template brings down a version of bootstrap and does it locally that's version 5.1.0 in the course I showed how to upgrade but basically you just go to your app. Riser and replace this line right here with a call to a CDN with the with a bootstrap it will change the size from I think 160 kilobytes down to like 37 kilobytes um to go with a CDN and it will make your um your version be the the latest version which time that's recording is uh 5.3 point something um so improvements all around and he has not a for the most part A breaking change and then um also note that we have our app.css this is our sitewide CSS document you can make changes here or just you know wipe out Microsoft defaults we do have a favicon for the application which right now is the default Blazer fabicon you could change that if you wanted to and for production app you definitely should but anything else that's like a a standard file that's a static file like a images or JavaScript files or anything else like that you can put in this www root folder now speaking of JavaScript I do want to point out some people don't realize Blazer has full access to JavaScript and JavaScript can have full access to Blazer meaning you can set up a a component in Blazer they can talk to JavaScript and you can have you can call JavaScript and get data back out and put it into Blazer so you can have that two-way interaction which means that you can use pretty much any Java script library or component out there with blazer so you're not saying I'm only going to use Blazer and I'm cutting off all JavaScript no you're saying I'm going to use Blazer and if I want I can use whatever JavaScript I want so you're leaving that door open for whatever you want to do whatever works best for your application so I always encourage you that if it's an if it's a uh interactivity with a screen where you're changing manipulating things maybe start with blazer because you already have something built in a lot of times people Overlook the current you know built-in power because they find something flashy that does the same thing but adds more dependencies to your application that you really don't need so I encourage you to figure out if you actually need those dependencies before you just go adding them like crazy on the other hand I would encourage you not to say you know I'm never using JavaScript because there might be a better option out there for certain circumstances than trying to reinvent the wheel so it does interact really well with JavaScript we cover that in the course um I'll probably cover in a future video as well but this is Blazer this is blazer with auto it has server side rendering we have we've seen stream rendering we have Blazer server we have Blazer web assembly and we have Auto that transitions between server and web assembly so lots of cool stuff this thing is very powerful very fast and you can take your existing knowledge of c and build out a user interface that is fast that's either server or client side or that transitions from one to the other and you can do so in one PRI this case two projects um very very easily so really great project I think this is probably the way I move forward with almost every web project I do in C because it just covers that much ground it's it's got enough in there that I don't think I see a reason to go to an MVC project or razor Pages anymore um there's still definitely reason for API but I think that Blazer has come out with a an all-in-one system that allows for such flexibility that I don't see a reason not to default to it okay so that's my thoughts on Blazer it's a it's a great project type I would encourage you to check it out learn more go deeper really understand how Blazer works if you have questions leave them down in the comments let me know what your thoughts are on this new version of Blazer and if you tried it out let me know you know if you come across any stumbling blocks or things you want explained more thanks for watching and as always I am Tim [Music] [Applause] Corey [Music]
Info
Channel: IAmTimCorey
Views: 35,517
Rating: undefined out of 5
Keywords: .net, C#, Visual Studio, code, programming, tutorial, training, how to, tim corey, C# course, C# training, C# tutorial, .net core, vs2022, .net 6
Id: walv3nLTJ5g
Channel Id: undefined
Length: 46min 0sec (2760 seconds)
Published: Tue Nov 14 2023
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.