>> Fantastic. Thank you very much. Enjoying the conference so far. Thank you to everyone who
is tuning in at the moment. I'm really glad you've done that. I'll introduce myself.
My name is Steve, and I work at Microsoft. I'm a developer or
architect on the.NET team, particularly focusing on web stuff and with a special focus on Blazor, which is good because that's what
we're going to talk about today. Now, if you've been watching
the last few sessions, you'll already be
familiar with where we are in the history
of.NET at the moment. But just in case anyone is
just watching this session, I want to make sure you
know where we are on the timeline..NET does a major
release every year in November. You may well know that.
What the Blazor team been doing for the last 12
months since the.NET 6 release? Well, we spent about half of
our time working on.NET MAUI. That's the new Blazor hybrid
feature that allows you to run your Blazor components within a native mobile or
desktop application. You may have just seen some
of them showing you that. Then for the other six months, we worked on adding
some great new features to Blazor in.NET 7,
which I'll show you. Now of course, there is going to be another.NET release
next November,.NET 8, and we've started
planning that already. We would really love any
feedback that you've got of what things you would
like to see in.NET 8. If you can get onto the GitHub repo and give us some of
your suggestions, we'll hopefully get some of those
into the product next year. But this talk right now is about
where we are today with.NET 7. We've got a lot of great new features
for Blazor developers in.NET 7 and most of the work across all the different
Blazor hosting models. Whether you're using
Blazor server or WebAssembly or hybrid with.NET MAUI, most of these features will work in the same way across all of them. Now, there are also some
WebAssembly-specific features. Mostly, those were implemented by the underlying.NET runtime team. Thank you to them for doing that. I'll mention a few of those
towards the end of this talk, but there is a whole
talk about that tomorrow where you can get into more details about WebAssembly runtime stuff. Let's think now about
some of the new Blazor features that work
on all the hosting models, and I'm going to
demonstrate them to you. We're going to need a bit of a
demo app to get started with. Let's just switch over to this sample application
that I've put together. It doesn't use any.NET
7 features yet, but we're going to add some. This is not meant to be a
surprising or clever sample. This is meant to be as
mainstream and predictable as possible so that you can
easily relate to it. If I start this up in my browser, you will see that this is simply
displaying a list of products, which is getting from a database. If I click on one of these links, I get into an edit screen and it does all the
normal editing stuff. I can make some changes to, let's say, this category. It tracks the changes there. If I try to save, it's
going to do validation, and if I satisfy the
validation rules, then it can tell me that the changes have been
saved and I could go back. Pretty straightforward stuff. If we look at the code in that, what we'll find is that this is
a Blazor server application. Could be done with WebAssembly, but I just happen to have done
it with server on this occasion. If we look in that, here's an
example of one of the pages. This is the index page, and it doesn't really
do very much apart from just display
this products list. If we go into the code for that, this is a typical way of fetching data from a database and
rendering it with Blazor server. This is using Entity Framework, which is why we've got
this DbContext there, and I'm to the life
of this component. What that means is whenever this
component is on the screen, this DbContext will keep going, and if the user navigates away, then it will get
disposed and cleaned up. Apart from that, it just
uses normal EF code. We're getting our products. We're saying we don't
need to do any change tracking because this
is not an edit screen, so it's more efficient not to. I'm limiting it just to 50 because
otherwise there'll be too many. We'll fix that in a minute. Then to display them, we simply have a for each loop to render these
links for each of them. That's normal.NET 6 code. But can we make it a bit better? Instead of just displaying
a list of names, can we display more
information at once? Can we get around this
limitation where it only just shows us 50 items?
Can we show a lot more? That brings us to the first thing
I want to show you, QuickGrid. Now, this is actually
marked as preview in.NET 7. That's not because it's not
ready for production use. It's because we're not technically counting it as supported
because we want to be able to change the API depending on feedback
from the community. But if you're good
with the API as it is, then you can use this like any
other open-source project. The idea of it is, it's not that it's
intended to replace every other grid in the
entire Blazor ecosystem, there are existing other ones. Many of which have
more functionality. But the idea with
QuickGrid is to give you a standard basic set of features that we'll cover many
common scenarios and that it will
perform extremely well. In all the different
situations you might use it, whether it's WebAssembly server
or with a large amount of data or whatever should
work well. Let's have a go. I'm going to go over that and change this screen so it
works using QuickGrid. What we will notice firstly is
that our code gets a lot simpler. All we have to do now is we get our products from
Entity Framework there. I'm still limiting it to 50, but we'll change that in a second. We've got this queryable of
products and we can pass that to QuickGrid and it's
going to render them for us. Now, I haven't got any columns
in this grid just yet. When I switch back to MAUI, we should see that it becomes blank because there's no
columns for it to render. Let's go and add some. There's two types of
built-in columns. We've got property
columns like these ones, which just pick out a
certain property in a strongly typed way to render and we can pass
the parameters too, and then this template columns for more control over the rendering and I'll show you that in a minute. But now we've got these
four property columns. When I switch back, you'll see
we've got this nice little grid. We can scroll around. We can do sorting because I set
sortable to be true. That's good. But I want to get beyond this
limitation of only showing 50 items. QuickGrid has got the ability
to do both pagination and virtualization so that you can work with much larger
amounts of data. To do that, we will
first add an instance of this model type pagination
state and I'm going to set it to have 10 items per page, and that will keep track of
where we are in the pages. I'm going to pass
this in to the grid. Once that has access to that, it will respect the
pagination rules. Then we need a bit of UI to let
the user move between pages. You could write your
own UI for that, but I'm going to use a built-in one, which is simply called paginator. Once I've done that, if I
go back into my browser, we should see now it's displaying
those 10 items and I can switch through these pages
quiet easily. That's good. But I don't want to
limit it to 50 anymore. Now we've got pagination. I'm going to remove that,
take 50 from the end, and then when I come back
and I'll reload on that, we've now got 100,000
items from our database and we can very easily continue
working with all that data. Now, it's not super easy
actually because there's so much stuff the user hasn't got much chance of actually finding
what they're looking for. We're going to need to add a
search feature in just a minute. But before we get to that, let's fix the display slightly because some of the
styling is quite weird. Especially these prices, like I've no idea how you're
supposed to even read that. It doesn't look like a price. I'm going to drop in a slightly
updated version of this code, which uses some template
columns as well to do things like custom
formatting of the price, setting alignment,
custom sorting rules, and I've got a link into
the editor screen again. With those updates in place, now things look a little bit better. >> That is the QuickGrid, which is available as
preview with.NET 7. Let's move on to the next new
feature, @bind enhancements. Now, Blazor has always supported data binding
from the very beginning, but we've added some new
powerful ways of binding, additional ways to give you of some more flexible options in.NET 7. To have a scenario for that, let's imagine that we want
to add a search UI to the screen right now so you can quickly find your
particular product. We'll get started doing it
until we run into a problem, we need a new feature. The first thing we're going
to need is a place to keep track of whatever it is
that the user is searching for. I'm having the string field here. Then I need to add
a bit of UI to let the user type in what
they want to search for. I'm going to use a QuickGrid
feature called ColumnOptions, where we can type in whatever UI we want that's associated
with a particular column. What it will do with that is it will render a little icon
in the column header, you can control what that is, and when the user clicks that, they'll get the UI that you chose. Inside there, I'm going
to put a box that they can type their
search terms into. I'll use the normal data
binding that precedes.Net 7, that's always been available. I'm binding this text box
here to the @searchName. I've got a few other attributes. I'm saying that I want it to update whenever there's
an input event. That means every keystroke, the browser fires an input event
on every keystroke or paste or anything else that changes
the contents of the text box. Hopefully, that's enough to make some actual UI appear even though it doesn't
use any new features yet. When I type in there, it
does update that field but it's not updating
my search query. What I really need
to do is, somehow, every time this binding fires, I need to update the filter. But how do I do that? Prior to.NET 7, it wasn't very easy; you have to use some
pretty weird tricks to react when a binding changes. But one of the cool
new features in.NET 7 is something called
@bind:after. It's very easy. It simply means every time
that binding updates, we are going to call your function or your method and you can do
whatever you want in them, whether it's synchronous,
asynchronous, whatever. If you need slightly more control, we've got a more advanced version of it called @bind:get
and @bind:set, which gives you ability
to do custom logic both before and after on both sides of the binding if you want
to do any conversions. Anyway, let's use @bind:after. I'm going to say that
after the binding updates, I want to update the filter, and I haven't defined
that yet so let's put in an implementation of that. Here's my implementation. It's just going to use
Entity Framework APIs to add a where clause based on the search name
that you've entered. I can also slightly simplify OnInitialized now to
just call UpdateFilter. If that works, then
when we come back here, every time this binding updates, you will see it calls
out update method and then we can automatically
update our query. We've got a working search
and within that search, things like paging and
sorting will still work. That's nice. Next new feature, a pair of
related features, in fact. The community has been asking
for this for quite a long time. It's one of the most
highly demanded features and it's the ability to receive a notification before
the user navigates and have the power to
do things with it, such as cancel the navigation. We've added this new event called LocationChanging that tells you
when the user is navigating. In case you want to use that
with an editing scenario, we've added this special flavor
of it called NavigationLock, which is a component that
you can use if you want to help the user so that they don't lose
any changes if they tried to navigate away while
they're in the middle of editing. NavigationLock is just a
particular usage pattern for the underlying
location change given. I'm going to show you
it because, otherwise, it's not going to be very
clear what I'm talking about. Let's go to one of
these "Edit" screens here and we're going to go
into edit this product. I'm going to change the name, CHANGED, like that. I'm going to maybe change the
stock a little bit as well. Now, imagine that as a user, I forget to save my changes. I don't remember to
press the "Save" button. I just click this link
to go back to home. What will happen is I
just lose my changes, which is not very good. Another thing that
could happen is what if I leave the site entirely. Again, I might lose my changes. To show you, I'm going to go to an unrelated website, Microsoft.com. Then when I go back in here
and I start making an edit, EDITED AGAIN, like
that, at this point, I could use the back
to go all the way back to Microsoft and
it won't do anything; it will just lose my changes. Let's see if we can stop
this problem from occurring. I'm going to go into the code
for this "Edit" screen here. Now, I know there's quite
a lot of code here, you won't have time to read it all. Don't worry about it. This
is just the normal way to do editing with Blazor and
has been for a long time. We've got this EditForm. We've got a context which
will keep track of the edits. We've got a thing that
activates validation. We've got various components
for displaying the UI, for editing the data, and for showing validation messages. But that's not new. I want to show a new thing
so I'm going to show you the NavigationLock component. This deals with two
different types of navigation: external
navigation and internal. The reason for the
distinction is because the browser forces you to
make this distinction. External navigations or if the user is leaving
your site completely, using the back button or following
a link or closing the browser, and the browser will not let
you stop the user from doing that but it does let you
ask them to confirm it. That's what this is doing.
It's saying if you are doing an external navigation and
you've got some unsaved changes, then we'll ask the
user to confirm it. Let's see if that works, shall we? I'm going to go back
over here and reload. Now, I'm going to go and
start making an edit. I'll say, EDITED AGAIN, like that. I'm going to try and go back
to Microsoft.com again. This time, you'll see we get a
little message that shows up. The browser won't let you
customize this message but it does let you ask
the user to confirm it, so the user could
cancel if they want to. Similarly, if they were
going to close the tab, it will show them
the confirmation or even if they were going to
close the entire browser, they'll get that
confirmation prompt as well. Of course, they can choose to
go ahead with it if they want. Now, the other scenario
is internal navigation. That's when the user just moves
to a different part of your site. In that case, there's
no limitations. You can do anything you want; there, the browser won't stop you. We've got this
different callback that will occur for internal navigations. You can put custom logic in there. It can even do Async things, so you could force the user to save
their changes automatically at that point or you could just always unilaterally cancel
it; it's up to you. But what I'm doing in this
case, just to show you, is I'm adding a confirm prompt, that's similar to the other one. If the user doesn't confirm it, we will prevent the navigation. Let's see if that works, shall we? I'll come back over
here, and I'll reload, and that I will confirm the external navigation because
reload is an external navigation. I'll make a change, for example, I'll change the stock count, and then I'll try to click
on the "Index" link. That's an internal navigation. It will run my custom
logic and it will ask for confirmation
and I'll cancel it. Just to show you, if I do
save the change first, then when I click
the link this time, it's not going to show any
confirmation prompt. There you go. That's how you can
use NavigationLock, which builds on top of the
LocationChanging event to give you a nice pattern when you work with
editing data. Let's move on. Next new feature, custom elements. Now, if you watched
the previous session, you will have seen an example of
this where Dan showed how you can use custom elements to host Blazor components inside
an Angular application. I'm going to show you this in a
slightly different way just now. If you don't know, if you didn't
watch the previous session, what this does is it allows you to say that Blazor components will be registered as custom
elements and that lets you use them from other
web technologies. If you are doing some other
client-side rendering, whether it's with something like React or Angular, Vue or Svelte, or anything else like that, you can have those other technologies
render Blazor components. Similarly, if you're doing
server-side rendering with Rails or PHP or anything else, then, again, you can get those technologies to render
your Blazor components. To show you that, and just to have a bit of a change
from Angular or React, I'm going to use a server
rendering technology. Let's imagine we want to integrate this Products Manager
with a WordPress site. Now, I know WordPress is not exactly hot new stuff but
it is very mainstream, so that's why I'm going
to show it to you. Obviously, it doesn't
know anything about.NET. >> Which is nice because we can
show that it still works anyway. I've got this WordPress
site right here. You know it's WordPress
because it tells you that and I've got a
page on it called All products and I want to show my blazor products grid right here. Now, the way that you can
do that is you need to host both your blazor code and
your WordPress in this case, code on the same domain. It's not intended for
cross-domain hosting scenarios. Maybe we'll add something
for that in the future, but that's not the case right now. In this case, I have got my
blazor server application on my WordPress site running on the same host so I can
make them work together. What I do is I go into
whatever you use to configure your other technology
and you make it render the script tag that loads blazor. In this case it plays a server. It would also work with
blazor WebAssembly. In fact, it's slightly
easier to deal with that. I'm loading that into
my WordPress site. I'm also adding some CSS just
because I want the styling to match up and I've got this base
tax so that links will also work. Once you've done
that, you can go and start using your blazor components. In this case, in my blazor code, I have said I want to register
a custom element and it's going to be the
products list and I'm giving it the name products-list. Since I'm loading the blazor
script into WordPress, I can now use that in my pages here. Inside all products, this
is where it says to do show products grid and I'm
going to add a product's list, right there, so I'll
hit Save on that. Then when we go back to that page, you'll see we've now got our
list of products rendering inside the WordPress application
and of course it's got all the same functionality
that you'd expect. It's got sorting, it's
got all the searching, and it's got pagination and it's partially integrated the styling as well for me because I've
got both WordPress, CSS and blazor CSS loaded together here so they're working together
to control the final styling. That's nice. One
other thing we could do is pass parameters as well. Let's say we want
to have a page here called batteries that
just displays batteries. At the moment it
displays everything, even though it's trying to
just display batteries. Let me show you how it's trying. If I go to the editor here, you can see it's trying to pass
a category and a subcategory into my blazor code but the blazor code doesn't know
anything about these parameters, so it's just ignoring
that right now. But we can make it know about those parameters and
then it will work. I'll go in to my
products list component and I can use normal
blazor parameters. For example, here I'm adding category and subcategory
parameters and then I will change my filter
logic so that it respects those parameters and adds
extra where clauses for them. Here we go. We'll say if
you've given as a category, we'll add a where
clause for that and similarly for the subcategory. Now we've added that feature. If I go back to this
page and reload it, you see that the
battery screen now just shows batteries and all products, shows all products. There we go. The point of that is simply
that we can integrate blazor, whether it's server or WebAssembly
with other web technologies, whether they're client-side
rendered or server-side rendered which may be very useful
in many of your scenarios. Let's move on now and we'll talk a little bit about
blazor WebAssembly and a couple of the new features
that have been added there starting with loading progress. Now hopefully your blazor
WebAssembly app loads nice and quick but
it's always possible that some users will be on slow network connections and then might be waiting a
little while for it to load so it's nice if you would
show them the progress as it goes. That is something we've
now baked in by default. I'll show you the updated blazor
WebAssembly project template. I'm just setting that startup, I haven't changed this
template in any way. This is just how it comes out of
the box and if you are very fast, you might have seen
the loading indicator show up it's a bit
too fast to really see so what I'm going to do is I'm going to go in my browser dev tools, and I'm going to throttle the
network to be extra slow. It's going to load super
slow and I'm going to clear my browser cache so it's
definitely loading everything. When I reload now
because it's throttled, it will take a while and you
can see that it's updating this progress as it goes so that users get a sense of how
long they have to wait. Now it's styled in this
circular way right now, which we thought looked
nice but of course, it's designed for you to customize and change in any way
that you want to. All you have to do is
go to the place in your index.HTML where that markup
exists and you can change it. By default, we're rendering this SVG that renders a couple
of circles to display, and I'll show you how it
works in terms of getting the loading progress
dynamically in a second. But to do that, I want to show it to you in the context of another thing, which is the new empty template. We've added this for both blazor
server and WebAssembly and the idea of this is after
you've made a few blazor sites, you probably don't really need to see anymore counters
and FetchData screens. You might have had
enough of those by now. Quite a few people said they wanted a more empty template
so we've added that. I'll show you what that looks like. It's not completely empty. It's got some of the things that
you need functionally to make your application work
but when it comes up, you'll see all it actually renders
is just the word Hello world. If we look at the sources in that, you'll see there's only
one page in there and inside that it simply
displays Hello world. It's a slightly nicer
starting point. We've also simplified
the CSS as well. It doesn't have
Bootstrap by default. The only CSS that
it's gotten there is 32 lines and it's one
thing that's to do with accessibility and all the
rest of it is just to do with how the error messages are styled
if you have an unhandled error. That's just because if your
error messages don't show up, it's difficult to do
your development, so we've added some
default styling for that, but everything else is there
for you to sort out yourself. Now, I want to show
you how we can set some custom loading progress in the context of
this empty template. I'm going to go here in
my index HTML to where the loading message is
displayed and let's just check that we
can see it's loading. I'm going to once
again make sure that my network is throttled and I will clear the site data so that
it's going to go very slow. Now you'll see the
word loading stays on the screen for quite a while. Let's customize it. Shall we? What I'm going to do is
I don't want to circular progress bar this time just to
show you we can do other things. I'm going to add a
linear progress bar, and it's quite easy to do. I'm going to add a single div with
this custom class called linear progress and then I'm
going to add a bit of CSS to control how that renders. My CSS is going to look like this. I'm going to say it's
got a silver background, it's got a particular high, a particular width and that's all I'm saying
about that at the moment. Also, I want to render another
element next to it or inside it, which is going to be blue and
I'm going to set this to be 30 percent of the width of its parents and I've
got some other stuff to do with animation as well. That's not really going to show the load progress because
it's hard-coded to 30 percent but let's just
check how it displays. When I reload, you'll see I need to clear my cache again if we
want it to really be there. You'll see it's now showing
that 30 percent value. If we want it to show the
real loading progress, we can simply use a CSS variable, which is now built-in. It's called blazor load
percentage and blazor will automatically change
that dynamically to match the current
load percentage. If I go back and clear my site, enter one more time and
reload, then this time, you'll see that that progress bar is dynamically updating to show
the actual load progress. It's very slow because of what
I've done in the network tools, but it is actually working. That is the empty template
and loading progress. Now there's other WebAssembly
specific features too which you can find in other
talks in this conference. One of them is some enhancements
to how authentication works. New extensibility points that allow you to run some extra
logic before and after Auth so that you can pass some additional parameters to
your authentication provider. If you want to control
a little bit more about how the Earth works and then there's also some big improvements to the underlying runtime in
terms of its performance. We've made AOT quite a lot faster. I don't have specific numbers, but in some of my
experimental benchmarking, I've been getting apps that
have been almost twice as fast with.net7AOT as
they were with.net6AOT. Not promising it's always going
to be that much of a multiple, but I'm just saying it can
be quite a bit faster. We've also got now support
for vectorization or SIMD. Now that's a little bit advanced, that's generally used with
numerical algorithms and what it means is that even
on a single thread, your CPU can process multiple
streams of data simultaneously. You do have to change your
algorithm to make it use these new the SIMD APIs. But that is now supported on WebAssembly it's spotted
in regular.net for quite a few years but it's also now ready to go with
your WebAssembly code. Then finally, quite excitingly, we have got an
Alpha-level preview of real multi-threading
for blazor WebAssembly. This is not something that we expect you to
actually use in production. In fact, it can't even be used out of the box in
blazor WebAssembly, we're going to add that shortly but if you're using a.net
on WebAssembly, there is the opportunity
for you to try out.net8 multithreading now so you can
get a sense of what works, what doesn't give us some feedback. This absolutely isn't intended
for production use to share, but it gives you a sense
of where we're going. You can find out more
about blazor WebAssembly runtime features tomorrow in
a talk that is all about it. That is all we've got
time for in this session. If you want to learn some more, you can go to the URLs that
you see on your screen right now for an overview of all the ASP.Net Core features including
blazor ones and if you want this product manager sample
that I've shown you just now, then you can go to the URL there
and try that out yourself. There we are. That's
all I've got time for, and I will hand you back, and I hope you have a great
rest of the conference.