>> ON.NET, we are looking at
the power of OData and Blazor together to build rich APIs that use C# on the client
and on the server, you'll want to check this one out. [MUSIC]. >> Hello, and welcome to
another episode of ON.NET. My name is Jeremy Likness, and I'm here today with Hassan, and we're going to cover two
powerful technologies that I love. We already had an episode
talking about OData, and OData is what I would call, I know we don't like
head-to-head comparisons, but it's like the
GraphQL that has been around a lot longer than GraphQL but capabilities are very similar. We're going to look at
some advanced features of that and combine that with Blazor which is .NET running in
the browser without data plug-ins. So before we dive into
this awesome topic, tell us a little bit about
what you do at Microsoft? >> Hi, Jeremy, it's
nice to meet you again. My name is Hassan Habib, I am a Software Engineer
here at Microsoft. I work at the SEAL organization, we are the legal system
here at Microsoft, we handle all internal legal
matters, applications, internal systems, and we get an opportunity to work with
a lot of cool technologies. Every once in a while, we get so
excited about these technologies, so we want to tell the whole world
about what it's capable of. >> Well, that's awesome. So it's not even a case that
you're on the team building, you're using this to build
business applications, you're not building the tool
itself but leveraging the tools, tales from the actual
real-world usage of it. So tell me about what
you've bought today? >> Yeah, absolutely. So first of all, I couldn't thank people enough for
the comments, and the feedback, and the responses on our first video, that's what really made
us want to do more of OData and talk more about
such a powerful technology. Like you said Jeremy, there's competitive technologies
in the market, this is almost 13, 14-year-old technology that handles the processes that support billions
of users, Microsoft Office, SharePoint, if you're
using Microsoft Teams, all of this is building on top of OData like Microsoft Graph
and other technologies. Some of the comments that I got, a lot of people started
to adapt OData in their actual application inside
and outside of Microsoft, and some people wanted
to leverage OData for more functionality and
leverage the power of OData, things like count, how do
I get the count of data? How do I get a next link
out of OData? How do I leverage what this amazing technology is capable of doing with the four lines of code? So today, I'm coming
here to tell people, here's how to take OData
with something called the EDM Model which is Entity Data Model. It's like a map, that's going to leverage
that technology and provide the functionality that
they're looking for with their day-to-day applications. >> Awesome, let's check it out. Tell us more about EDM and
how we would approach that? >> Absolutely, so EDM stands
for Entity Data Model. It's a pattern of technology
that OData relies on to map whatever data source you have into something that
OData engine can understand. So it provides you with
the kind of functionality, and filtering, and
expansion, and count, and all the kinds of good stuff
that I'm going to show you today, regardless of what
your data source is. This is a great opportunity to
start talking about something, a lot of people think
that OData actually is dependent on the Entity
Framework, that's not true. You could have any data source that we're going to show in different
episodes other than this one, you can have any data source
out there and you can still map that and have OData
understand what this is. So there's no dependency there
on any of the framework at all, it's good to leverage
that technology, you don't have to use it
if you don't want to. >> Okay, sounds great. >> All right, so let's jump in. So remember last time we had
the WashingtonSchools API, I'm just going to run it real
quick and show you that it's still running the exact same way. I hope people can clone that repository on their computers
and try it themselves, it should be a plug and play, just to run the application
and it should just work. So from the API, I could still go in and say, "Give me all the
students that I have," and then I could also do some good
OData stuff like question mark, select, give me just the name, and I will go and
filter the name and do all the kind of stuff that
we were doing last time. >> Okay. >> But there's a trick
here, some people say, what if I want to measure
how much data is coming in? I don't want to pull all the data, like say you have two million records and you want to know
how many records on your database without
you having to pull all these records with all that data. >> Right, don't pull down
the whole world and then count it. >> Yeah, I just want to do the count, how can I do that on the server
instead of having to iterate? So if you do something like this, "Count equal true",
what's going to happen, is it's not going to
give you anything. I'm going to tell you now why it's
not going to give you anything, because OData builds a
wrapper when you use EDM, it builds a wrapper
around your data model, and that wrapper gives you that metadata that you
need to use to know count, what's the next link and all kinds of different metadata properties. So it's not a part of
your existing model, it's something that OData provides in its own model that wraps
your existing model, your existing data model. It's not exactly a Photoshop or the best kind of graphics out there, but it's something
I built real quick. This is your data model, and
this is your OData wrapper, and I'm going to show you now
how this comes into play. So in addition to the four lines
of code that we did last time, now we going to
implement the EDM Model. Let me go ahead real
quick in here and build a little private method, let me shut that guy down first. So you see here even though
we have the count in place, it's not showing the count because
there is no OData wrapper. So I'm just going to
go in here and say, "Private IEdmModel," so this
is what we want to return. If you do control period,
that pulls in Odata.EDM and then you can call
this method whatever you want, so I'm just going to
call it GetEdmModel." This is the mapper, this is what we care about, so let's see here why does it matter? Because I'm building
it inside the method, it's like a scope thing,
so let me go back here,. >> Yeah, you also aren't
returning anything yet. >> Right, so this guy here, yeah. >> You lost the break. >> All right, let's do that, space that in here, there we go. So now I want to build
that mapper for me. We're not doing any magic here, we're just telling OData, "Wrap the model and give me that additional
information that I need." So all we're going
to do here is that, I'm going to have here
a convention model builder, so ODataConventionModelBuilder. >> Okay, and so this is a builder pattern that we see
in a lot of Microsoft products, where you're setting up an object
that you can interact with to provide configuration and
metadata and other information. >> Yeah, and now I'm just
going to give that builder, the model which is the EntitySet, which is the student, which is the model that
we built last time. >> Okay. >> We're going to tell OData, these EntitySet are the students. >> Okay. >> Right, so now OData understand
that there's the source of data that were returned as a list of
models that are of type student. The last thing I want to do here, is just go and say "Give
me that data model". So builder GetEdmModel. >> Okay. >> Voila, so now we've
built our wrapper. The next part here is to have that to be a part
of the routeBuilder, so that OData understands that. So I'm just going to go here and say, "Wrap your existing
routeBuilder", routeBuilder, I know how to spell, then
MapODataServiceRoute, and then there's three parameters in here that we want to care about. You can give it a name, so what we're doing
this is the route name, you can use that as
a configuration to go find a particular route but since we're really doing a very
simple operation here, we're just going to call it OData. Then in here you could either
choose your route to be slash API or to be slash OData. >> Okay. >> What I personally recommend
from a best practice perspective, since this is OData wrapped model, it's better to say OData as a prefix but you also
can do slash API. >> Right, and you're just looking
to keep this separate from regular RESTful on points that
aren't necessarily OData enhanced. >> Yeah. So this is OData, and then the last part is
our mapper that we built, so this is GetEdmModel. >> Okay. >> Right, that's it. Now, OData doesn't
need you to tell it if you're putting this on top
of an existing controller, OData doesn't want you to tell it
that this is an API Controller, so you don't need
that additional annotation to tell it which route and
this is an API Controller. >> It's smart enough
that when you go-. >> Inject that, it
just knows about it. So we're going to get
rid of these two, I don't need to tell
it the route anymore, it builds its own route and it knows that this
is an API Controller. >> Yeah, caught up in the braces. >> Yeah, and everything
else stays the same, so you have the EnableQuery, you have the HttpGet. >> Okay. >> But these three lines
of code that we added, maybe four lines of
code that we added. >> Magic. >> Four lines of code,
that will give us a lot more power than you'd
think OData would give you, like it honors something that we call the [inaudible] Model or [inaudible] Model, which is giving you ref
links to where this object is, you can enable a lot of stuff. Let's go back here and say, this is now that
we're choosing OData, it's going to be
OData slash students. >> Okay. >> Everything works, right? >> Right. >> Now, what's happening
here? Look at this. It has odata.context, and it's giving me a URL to something about
these students, right? >> Okay. >> If you follow this a lot
of people are going to love this part because it saves a lot of time and work about
particular things here. If I hit this, do you
know what it's doing? It's giving me the XML
for the model itself. >> Now, is that, if I requested
for a JSON payload will? >> You could get it
as JSON if you want. >> But it's basically
given me the schema, so I just hit the endpoint. Without knowing anything about. >> The model. >> The model. >> You already know when. >> It's going to pass
that back to me. >> So why is this important for some developers? Why
is this important? Because normally, like in a lot of
applications distributed systems if you're building bunch of
microservices or something. People build a NuGet
package that have the model or they shell the
model in source control. When that model change, things break. >> Right. >> But if you have the schema
in your API coal, what happens? You could build the model on
the fly out of that schema. So your application, your client
will never break out of that. Because you already know what kind
of model you're getting back. >> Is that's something you are doing? >> That's something I'm
doing personally, actually. I'd like to call it like, it's
not the right scientific term. I'd like to call it fluid
API client, meaning that, it adjust itself
automatically based on what kind of contract that the API, the source is sending. >> That's something that I
mentioned the correlation because it's the big buzzword with GraphQL but that's a similar thing. You can ask it, what is my schema? We've got this just with
a few lines of code interspective the model and provided
that information very good. >> Yeah. Absolutely. In addition to a bunch of some useful information, I'll take you back to the docs
to open data protocol. Go back, see what it's doing, see the types, the name of
the property, everything you want. >> Okay. >> So right. So this is great. Now, but the thing that
people were asking about, how do I get a count out of that? So if I go back here and
say, "Count equal true." What's happening here,
you have a new property. >> Data count. >> Data count. It's telling you how much in
your database do you have. Even if you're pulling right now, it's not exactly matching
the entire set in the database. So there is more to that though. I'm just going to, there's
a lot of properties. Hopefully, we're going to do
some OData series around this, but there's a lot of
properties that you can enable to pull in all what
OData can offer you. But what I'm going to show you
here is just one more thing, just to show how powerful the EDM model is when you integrate
it with your existing API. So I'm just going to go in here and go to the student's controller. This enable query is
not just a simple tag. It has a lot of
properties that you can leverage if you do
control, just second. If you do Control Shift Space, you can see how many properties, what functions you can allow, what properties you can enable. You can do a lot of stuff in here. >> So you're starting with
open and enabled query. But what you're saying is,
if you want to constrain the queries with
special parameters or whatever, this is a list of ways
you can tamp that down and prevent people from
asking for the Word security? >> Security. Yeah. Security.
To make sure that, and also in addition
to that, look at this. This is on the route level on
the controller method level, so you can secure, you can open some
security things for, some properties for some endpoint, you can close it from others. It's up to you if you want to allow anonymous goals with additional
functionality, it's up to you. But anyways, I want to show
you here, just another thing. There is something called page size. I can say page size equal one. Just return one at a time. >> Little unpractical page size,
but we'll roll with it for now. >> Right. Yes. We need more data to show
how much phase size will do. If I do this, let me show
you what this will do. It'll keep adding in more. This is why I like to
go, it's very popular. API where it comes
from something called HATEOAS link or HATEOAS link. People pronounce it in
all kinds of different ways, just referential to go get
more data, relational data. >> So if I'm thinking of this, I think of my Twitter client. When I have refreshed information, there's so much information
that the bottom load more. I click that load more. So what you're saying is, this is going to
follow that where it's giving me some data but
saying, "Load more". >> Yeah. >> Okay. >> Absolutely. >> So let's see it. >> So what's going to happen
if I go in here and say, odata/students, it's only going
to give me a Python hypothesis. It's one student at a time. "Hey, do you want
the next link for more data?" If we go to this, it'll give me the next student. Then, again, and there's
something really cool about this, it'll give me the next student. Then, the next student, but look what happens
at the third student, there's nothing, it's
not there anymore. >> So we're at the end of the list. >> You reach the end of the list. >> Okay. >> So it's already taking care. If you're building your client, OData will help you keep
that client as simple as possible. We don't have to worry about
calling when there is no data. It's already telling you, "If there is no data, I'm not
going to give you that link." So when it's null until you're done. >> You'll reach the end of
the bottom, the barrel there. >> Awesome. >> Right. So all right. So that's what EDM can do
for you, but this is great. Pagination is great. We can do all of that. But if we can display
that on a client, that would be better. I'm going to show you
now how we going to display that on a client. Let's go back here. So I built, this is really cool technology that
everyone's talking about. I'm personally shout out to Daniel Roth and everybody
around, Daniel. >> Steve Sanderson. >> Steve, yeah. All these geniuses, they're building, and
a technology called Blazor. It's the ability to run C-sharp
on.NET, and the browser. For a back-end developer like myself, now, I have this new realm, a new field where I can actually
build software in the browser. >> You can use the full stack, writing in the language
that you're in all day long which is C-sharp on.NET. I know I bring it out too
often people, tell me not to. But it's a dream that Silverlight began back in the day of being able
to run C-sharp in the browser. This is a technology that enables, and it does it without plugins. It uses a technology
called WebAssembly, that is available on every
modern browser including phones. So I'm pretty stoked.
So I'm assuming you've built us something in Blazor. >> Yeah. You bet. For starters, you'll notice here that there
is a new project that I have called a WashingtonSchools.UI. But before I dive deeper into the details here, there's
a couple of things. If you want to try this at
home and do try this at home, first of all, you need .NET
Core 3.0, the preview version. You won't have to deal
with preview versions for long, because in .NET Core, they said they going to
announce the final release of .NET Core 3.0. So that's great. Once you have .NET Core 3.0
as an official release, I have it in here. You want to make sure that you're enabling that in your Visual Studio. Because I know a lot of
people are going to be like, "I downloaded .NET Core 3, but I don't see." >> This is the enabled
preview version. >> Exactly. So if you
go in Visual Studio, you want to make sure use previews
of the .NET Core SDK. You won't have to do that for long, but these are the little details. I don't want you to stay an hour or two at night trying to make it work. It's just something
as simple as that. When you do that, I'm going
to show you a real quick. If you go in here and say, "Create a new project," and
you go to ASP.NET Core web application and you select
a project like this. I hope we don't lose our project
when we look up right. So you see in the dropdown here, you have ASP.NET Core 3. That's because you installed
the.NET Core Preview 3.0. I think they just released a
Preview 7, which is great. You have the Blazor
option server-side. This is what I'm using today to show you how we can leverage
OData page in any server. >> That's great too, because
there's multiple flavors of Blazor. We're not going to
give into them today, but server-side is the
one that will be released as a stable release with 3.0. >> Yeah. >> Okay. >> Absolutely. >> Great. >> All right. Now, since
we closed the projects, go back and try to open
our project real quick. I think "File," "Recent
Projects," "WashingtonSchool." Preview as newer recommended. Yeah, sure. All right. So what do I have here? When
you start a Blazor project, you have pages that you
can write C-sharp code in. You need to teach your UI about the model that
you're working with, so the student model in this case. You need to build a service that
will make that API call for you. So the service that we'll call
that local API that we just built. The OData wrapper that
wraps your client. I call it students API response, and then the student itself. So I'm going to show
you. Let me walk you through what I did in here. So first of all, everything
starts with a model. So the first thing I wanted to
start with is the student model, which is exactly identical to the model that I have here
in my API. So this is. >> I'm just going to interject
that with production project. If you have your model, these are demos who are
keeping them simple. But if you have your model pulled
out in a separate class library. >> Because that we're we used. >> You can share the exact same. That's the beauty of Blazor, even though it's client-side code. The exact same DLL you
use on the server, you can use on the client. So you would share that same model. >> Yeah. Absolutely.
Or, you could just pull the schema and build
your model on the front. >> Right. Exactly. >> So there is that. So all
right. So we have that part. Then, so if you have
the student model, you have the student API response. Why did I have the student
API response here? Is because I want to
leverage that count. If we're showing you
pagination today with Blazor, then we need to know
how much students are in the system and how
much we can paginate until we get to the end of the data that we have,
the stack that we have. All right. So you're building a model and we're
building an API response. The most important thing you
want to go after to build, after that is the student's services. That's just a typical API call. I didn't bother you, having you wage while I'm typing
the whole thing. It's just a simple HTTP client
that's making an API call. This here is the URL from best practices like Jeremy says
from a production perspective, you want to keep all that stuff
in a configuration file, and then use that back
in your system. But because this is a demo, I want everything to be
right in front of you. >> We're keeping it simple. >>Yeah. We're keeping it very simple. >> What C-sharp developers will love, is there's no crazy Fetcher XML, HTTP, or any JavaScript library needed. You're using the straight HTTP
client to fetch the data. >> Again, you can share that client with any other projects you have. It's all C#, we will not write
one JavaScript code today. >> Okay. >> That I promise you.
So what's happening, real quick, we're just
doing the client. We're making that API call. You'll notice in here I'm
passing in skip and top, which is basically if you see the next link that OData
was generating for you. It's saying, "Skip how many?" Here's the count, skip how many, and give me the top count of
that person. We're calling here. So this obviously, won't work because we said it's
OData instead of API, so I'm going to change
that real quick. So now, it's OData call, that catch, that you and I would be scratching
our head for second there. But that's the OData call. Everyone's probably
Newtonsoft, JSON libraries. We're just de-serializing
the response that comes back from the API into a student API response. Now, when you're building
this in Blazor, please, do not forget to
register your service. So there's down here
something called startup.cs, this is where you need to add
a Singleton Students Service. So when you're
initiating your project, it will initialize a copy
of that as a Singleton. You don't have to renew a whole new client every
time you make a call. >> You just ask for
give me this service. You could even put
an interface in front of it, say give me the service for this interface and it
hands it off to you. >> Yeah. Normally, like people use
something called AddTransient. If you want to enable
dependency injection and pass in, if you want to add in an interface and then pass that to the controller, and then you get to unit test
that, just drive that, that's very important
from a TDD prospective. So anyways, so don't forget to
register the students service. Now, let's get to the cool stuff
about OData today. This page that's called fetch data. Before I dive into the HTML, which is not much, there are three functions down here
that I want you to see. There is a wait students service,
get students async, which is the function
that API call that we built back here in
the student surface. >> Yeah. >> Then what I'm doing on init async, when the page is starting to load, go on make that call, give me the count, and give me the students. >> Okay. >> So that's one part.
These variables in here, they play the role
of global variables. If you're building a
JavaScript application, you have a global variable. If you're building any application, it's a global variable that
you're adding things in. The beauty about Blazor,
it's using state, so you don't have to refresh the whole page in order
for you to get new stuff. >> It's a single-page application. >> It's a spot. Yeah. It's
a single-page application. So I'm passing it top to one
because I want the first student. But you'll notice here
two more functions, I have next, which makes the same call when
it adds to skip, so it adds one. So skip one and give me top one, so you're moving forward. The previous is skip minus, minus- skip back and
give me the top one. So these are three functionalities. This is all C# running
in a.razor page. That's all back-end. That's all the buildup. Right? >> Okay. >> Now, what are we going to
do with these students list? If you go on the top here, you'll notice that if
this students is null, you're just loading the page, you're saying I'm still
trying to retrieve data. But then once you get the students, you get to break down in C# code. You get to do a foreach. People who are familiar with razor
pages or razor an ASP.NET MVC, this is exactly the same thing, except that we're breaking down. We're iterating through
these students unpopulating these properties in
a sample HTML table. These are the headers
ID, name, score. So that's that part. Now, I
want to label to tell me how many is left as I'm iterating. So I'm adding a label in here
that says, give me that count, which is also another variable
that updates itself, and this is the skip plus one. So when you're skipping,
you tell me what's left. So there's four by two, four by three, and
so on and so forth. >> Sure. >> Now, we want say if we have
more data left, show a button, if you have more data
in the previous, like, if I'm moving forward
than previously, there's some data behind, then show a button
that says previous. >> All right. Don't show it
if you're at the beginning, but if you've navigated forward,
go ahead and it shows up. >> It starts showing it up.
So this is also C# code. In here, I'm doing the same thing
for the next button. So moving previous, so
when the next button, when you reach to the end
of your set of students, if there is no more left- >> Don't show the next button. >> Don't show the next button. >> This is nice too because just
by wrapping it in that condition, Blazor will handle all, they show the attribute, hide the attribute,
everything for you. There's no you've got to tweak
CSS or do anything crazy. I'm just conditioning it, and it's removing it or adding it. >> Yes, sir. So the last thing
here is how do we hook up? This is the most amazing part. How do you hook up
C# function written in pure C# code into an HTML button
on the event of onclick. If you do button onclick, which is something I think
standard HTML onclick, if you call the functions
that we called in here, which is just like
very native C# code, async task and async previous, it'll execute that, and
update the states for all the global variables
that you have up here. >> Nice. >> So let's see how that works. Before we do any of that, if you go to your solution, how do I run two projects
at the same time? You go to "Properties,"
and you go "Startup project," and you say I want to start multiple projects at the same time. Some people do right
click, start debugging, and they kick off an instance out
of Visual Studio independently. You want to leverage
that play button, and you're saying run the API for us, make sure the API is running, and then run the UI. So this is a little configuration
we're making here, and now comes the- >> Moment of truth. >> Moment of truth. I don't know. We're making a theory. Let's see if that's going to work. >> I can tell you from
dealing with tables, and paging, and grids, the old-fashioned manual JavaScript
way that this comes together. It's a beautiful thing. >> All right. So this is our API. We know that our API is
working because it's set to retrieve bunch
of values and whatnot. But if I go to "Fetch data," it's loading, and nothing. Let's see what happens. So let's go back here and see what happened. Let's make sure we're calling
the right end points, so this is slash OData, OData. See, here's the thing. I don't have Max Top,
I'm calling top. >> The way you did had enabled it. >> So I got enable Max Top. >> We talked about that before,
you even have [inaudible] >> Isn't that the same thing that
happened last time? So Max Top. Let's say Max Top and I
will give you like one. You can't get more than one
outside of my API. >> Okay. >> Let's break everything and
start over. That's a deja vu. That's exactly what
happened the last time. I swear, this is not premeditated
or anything. It just happened. >> You just wanted to show the opt
in nature of the interface. >> Probably. So what
if I do it right now? More debugging? It's giving
me one student at a time. I don't have a previous button, and it's giving me the count. >> Sure. >> It's probably 1/4. I don't know. I speak
Arabic. I go right to left. >> That's right. Right
to left is fine. >> I don't know. >> We welcome all the purchase. >> They're Arabic numbers.
So we're fine. >> Okay. >> So if I go like this, and then as I navigate,
what's happening? The student name is changing. >> Yeah. >> But there is a previous button. >> Sure. >> Then they just disappeared. The page is not refreshing, but the data is working with you. >> Perfect. >> That's it. You can do, of course, a lot more leveraging Blazor. Just the idea that we didn't write
one JavaScript code and we have fully functional
navigation pagination in a table without having have any previous knowledge about
JavaScript is just amazing. >> It is awesome. We covered a lot of material
in this short period. There is a blog post that you can access that gives you step-by-step
instructions in details. We've given you
a very easy link to access it, it is aka.ms/odata-blazor. That's, O-D-A-T-A hyphen
B-L-A-Z-O-R. Check that out. It's got all the details of
recreating what we showed you here. This is the power of
OData and Blazor. >> Yes, sir. >> Thank you, sir. >> Appreciate it. >> All right. [MUSIC]
Good thing odata is busted in .Net core 3. And won't be released until after 3.1
I love odata. I implement it in all my back ends. I wish microsoft would increase its support for it. And i actually use it with blazor web assembly since blazor was in preview. It works like butter.
Advantages of OData over GraghQL from my opinion. 1. Odata does not require special syntax. You can use the normal C# web api you know and add extra capabilities to it like paging filters expanding select and more without having to write extra code. 2. Odata is very compatible with entity framework and IQuerables. Which makes it light on memory and guaranties Optimum memory use. 3. Odata has the potential to replace WCF if someone invented a library to dynamically generate client proxy to call it like it was possible in WCF. Unfortunately this is not implemented. I would love to implement such a library but i dont have enough time for it. I suggest such a feature so you dont have to regenerate the odata client everytime you change something in the api models or the end point in general. Imagine an odata endpoint being called as if youre calling a method like it is in Wcf, that would be amazing.
Does anyone actually use odata?
Odata is great, provides a lot of flexibility on the endpoints
Add in something like Linq and it'll be even better since you can write OData queries like this on Blazor.
All in idiomatic C#. Though I'd expect someone might try making GRPC / WCF Clients to work with Blazor to remove WebAPI altogether from the equation and all you'd share is a common interface and we're back to web RPC world lol (Though most Rest endpoints today are like that anyways imo).
Maybe OData can add some client code-gen as well (as a separate package of course)? It'd be great, and it'd make making web apps fast and easy to get things done for a full stack .Net experience.
Ugh. I hate odata endpoints. 😒
the "O" stands for "Oh god, no!" :)
Hi /u/HassanRezkHabib, great video as always. I have a question: What is in the Student model in the UI Blazor project? Is this duplicate code from the Api model?