Building Modern Web Applications with ASP.NET Core Blazor: Learn how to use Blazor to create powerful, responsive, and engaging web applications (English Edition)
By Brian Ding
()
About this ebook
It begins by introducing WebAssembly, the technology that makes Blazor possible. It then discusses the different hosting models available for Blazor applications. Next, the book covers the basics of building Blazor applications, including how to create components, handle user input, and navigate between pages. The book then delves into more advanced topics, such as uploading and downloading files, using .NET and JavaScript interoperability, connecting to the world with HTTP, persisting data with EF Core, and protecting your application with identity. Finally, the book shows you how to deploy your Blazor application with Docker and Kubernetes.
By the end of the book, you will be able to build modern, interactive web applications using Blazor and .NET Core.
Related to Building Modern Web Applications with ASP.NET Core Blazor
Related ebooks
Building Modern Serverless Web APIs: Develop Microservices and Implement Serverless Applications with .NET Core 3.1 and AWS Lambda (English Edition) Rating: 0 out of 5 stars0 ratingsExploring Web Components: Build Reusable UI Web Components with Standard Technologies (English Edition) Rating: 0 out of 5 stars0 ratingsReact.js Design Patterns: Learn how to build scalable React apps with ease (English Edition) Rating: 0 out of 5 stars0 ratingsAdvanced Web Development with React: SSR and PWA with Next.js using React with advanced concepts Rating: 0 out of 5 stars0 ratingsEnterprise Applications with C# and .NET: Develop robust, secure, and scalable applications using .NET and C# (English Edition) Rating: 0 out of 5 stars0 ratingsBuilding a Web App with Blazor and ASP .Net Core: Create a Single Page App with Blazor Server and Entity Framework Core Rating: 0 out of 5 stars0 ratingsVue.js for Jobseekers: A complete guide to learning Vue.js, building projects, and getting hired (English Edition) Rating: 0 out of 5 stars0 ratingsReact and React Native Rating: 0 out of 5 stars0 ratingsBuilding Scalable Apps with Redis and Node.js Rating: 0 out of 5 stars0 ratingsObject Oriented Programming with Angular: Build and Deploy Your Web Application Using Angular with Ease ( English Edition) Rating: 0 out of 5 stars0 ratingsJavaScript for Modern Web Development: Building a Web Application Using HTML, CSS, and JavaScript Rating: 0 out of 5 stars0 ratingsReactJS for Jobseekers: The Only Guide You Need to Learn React and Crack Interviews (English Edition) Rating: 0 out of 5 stars0 ratingsSignalR on .NET 6 - the Complete Guide Rating: 0 out of 5 stars0 ratingsASP.NET Core for Jobseekers: Build Career in Designing Cross-Platform Web Applications Using Razor and Entity Framework Core Rating: 0 out of 5 stars0 ratingsWebSocket Essentials – Building Apps with HTML5 WebSockets Rating: 0 out of 5 stars0 ratingsReact Components Rating: 0 out of 5 stars0 ratingsImplementing C# 11 and .NET 7.0: Learn how to build cross-platform apps with .NET Core (English Edition) Rating: 0 out of 5 stars0 ratingsDesigning Microservices using Django: Structuring, Deploying and Managing the Microservices Architecture with Django Rating: 0 out of 5 stars0 ratingsLearning Docker Rating: 5 out of 5 stars5/5Learning ASP.NET Core MVC Programming Rating: 5 out of 5 stars5/5ASP.NET Core 3 and React: Hands-On full stack web development using ASP.NET Core, React, and TypeScript 3 Rating: 0 out of 5 stars0 ratingsASP.NET Web API Security Essentials Rating: 0 out of 5 stars0 ratingsNode.js High Performance Rating: 0 out of 5 stars0 ratingsWeb Development with MongoDB and Node.js Rating: 0 out of 5 stars0 ratingsThe basics that every web developer needs to know Rating: 5 out of 5 stars5/5Node Cookbook: Second Edition Rating: 3 out of 5 stars3/5React Projects: Build 12 real-world applications from scratch using React, React Native, and React 360 Rating: 0 out of 5 stars0 ratings
Internet & Web For You
The Gothic Novel Collection Rating: 5 out of 5 stars5/5No Place to Hide: Edward Snowden, the NSA, and the U.S. Surveillance State Rating: 4 out of 5 stars4/5How to Be Invisible: Protect Your Home, Your Children, Your Assets, and Your Life Rating: 4 out of 5 stars4/5The Hacker Crackdown: Law and Disorder on the Electronic Frontier Rating: 4 out of 5 stars4/5Coding For Dummies Rating: 5 out of 5 stars5/5How to Disappear and Live Off the Grid: A CIA Insider's Guide Rating: 0 out of 5 stars0 ratingsCoding All-in-One For Dummies Rating: 4 out of 5 stars4/5HTML in 30 Pages Rating: 5 out of 5 stars5/5Social Engineering: The Science of Human Hacking Rating: 3 out of 5 stars3/5How To Start A Profitable Authority Blog In Under One Hour Rating: 5 out of 5 stars5/5Remote/WebCam Notarization : Basic Understanding Rating: 3 out of 5 stars3/5Tor and the Dark Art of Anonymity Rating: 5 out of 5 stars5/5The Digital Marketing Handbook: A Step-By-Step Guide to Creating Websites That Sell Rating: 5 out of 5 stars5/5Podcasting For Dummies Rating: 4 out of 5 stars4/5How To Make Money Blogging: How I Replaced My Day-Job With My Blog and How You Can Start A Blog Today Rating: 4 out of 5 stars4/5Six Figure Blogging Blueprint Rating: 5 out of 5 stars5/5Everybody Lies: Big Data, New Data, and What the Internet Can Tell Us About Who We Really Are Rating: 4 out of 5 stars4/5Mike Meyers' CompTIA Security+ Certification Guide, Third Edition (Exam SY0-601) Rating: 5 out of 5 stars5/5Python QuickStart Guide: The Simplified Beginner's Guide to Python Programming Using Hands-On Projects and Real-World Applications Rating: 0 out of 5 stars0 ratingsThe Beginner's Affiliate Marketing Blueprint Rating: 4 out of 5 stars4/5Wireless Hacking 101 Rating: 5 out of 5 stars5/5An Ultimate Guide to Kali Linux for Beginners Rating: 3 out of 5 stars3/5Wordpress for Beginners: The Easy Step-by-Step Guide to Creating a Website with WordPress Rating: 5 out of 5 stars5/5Content Chemistry: The Illustrated Handbook for Content Marketing Rating: 5 out of 5 stars5/5The $1,000,000 Web Designer Guide: A Practical Guide for Wealth and Freedom as an Online Freelancer Rating: 5 out of 5 stars5/5WordPress For Dummies Rating: 0 out of 5 stars0 ratings
Reviews for Building Modern Web Applications with ASP.NET Core Blazor
0 ratings0 reviews
Book preview
Building Modern Web Applications with ASP.NET Core Blazor - Brian Ding
C
HAPTER
1
WebAssembly Introduction
Introduction
In this chapter, we will introduce the concept and roadmap of WebAssembly and how it enables web applications to be written in any programming language. We will also discuss a few popular WebAssembly languages and illustrate the benefits of building a web application with ASP.NET Core Blazor.
Structure
In this chapter, we will discuss the following topics:
What is WebAssembly
How to compile a WebAssembly module
What does a WebAssembly module look like
.NET Core with WebAssembly
Objectives
This chapter is intended to guide you briefly through the world of WebAssembly, get familiar with WebAssembly modules and how .NET Core is involved with WebAssembly. We will learn how to install Emscripten SDK and will also get familiar with emcc command. We will explore the world of WebAssembly binary format and understand how a module was constructed. Finally, we will introduce the new generation of .NET --- .NET Core with the WebAssembly framework, ASP.NET Core Blazor.
What is WebAssembly
WebAssembly (abbreviated as Wasm) is a target for modern languages for compilation of more than one language, designed to be highly efficient while maintaining a safe sandbox environment. The definition seems to be too official. But if we break it down to two words Web and Assembly, we might get a better understanding of WebAssembly. Web, of course, everyone from a three-year-old kid to the elders nowadays know that they are living in the world of it. We can buy goods from Amazon.com, watch videos on Youtube.com and check out how friends' life is on Facebook.com.
Assembly, on the other way around, might not be that obvious to those who do not work with computer science. From recent years, most developers write programs with advanced programming languages like Golang, C# or Java. But earlier, we did not have those advanced languages; programmers used to write code with Assembly, which is more specific to the hardware platform. For example, writing Assembly code for x86 CPU and ARM CPU will have different key words and syntax. As a language that is closer to the hardware level, Assembly language usually has higher runtime efficiency than advanced languages. Now, you might guess that WebAssembly is another assembly language running in the web
- browsers.
History of WebAssembly
Early in 1990s, the first web was created. At that time, the web was mainly used by the scientists to share information. The web was designed to be the media of static content. HTML defines the content. URL locates the resources in the world of webs. The client (browser) would then send a HTTP request to the server through URL and then render the HTML content returned by the server. In this process, all the information transported was static, and that means there was no way that a user could interact with the web.
In 1995, Branden Eich designed a new language called JavaScript within only ten days. It looks like Java, but is easier to use than Java, and even non-professional website workers can understand it. However, Branden himself seemed to not like JavaScript that much. He was of the belief that everything that is excellent is not original, and everything original is not excellent. With the Chrome from Google getting more and more popular, JavaScript soon took place everywhere on the website. Even on the server nowadays. Engine V8 from Google is enabling JavaScript to be used in a large and complex project.
Hello World with WebAssembly
JavaScript has been good enough, then why do we bother creating another Assembly Language
for the web? As far as we all know, JavaScript is a dynamic language, which means the type of a variable could be changed in runtime, unlike C# or Java. For programmers or developers, it is very convenient to write code, but it becomes cumbersome when it comes to the interpreter. The interpreter must judge of which type the variable is while running the code. Even armed with JIT compiler, compiling JavaScript into machine code ahead, sometimes, it must be rolled back to the original code under some circumstances. For this reason, many companies that build browsers are looking for a more performance enhanced solution.
In April 2015, WebAssembly Community Group was founded. Two years later, WebAssembly became one of the W3C standards. In 2019, WebAssembly became one of the standard web languages, along with HTML, CSS, and JavaScript. Through the years, most of the popular web browsers have supported WebAssembly.
Many languages, for example, C/C++, C#, Go can be compiled to WebAssembly now.
Let us take C/C++ as an example and write a simple C++ program that says Hello World. Save it as hello.cpp under my-hello-world-demo:
#include
int main() {
printf(Hello World!\n
);
}
Emscripten SDK is an open-source SDK that compiles C/C++ to WebAssembly, and auto-generates JavaScript code that can run the .wasm file. Install the SDK following the instructions here https://emscripten.org/docs/getting_started/downloads.html and compile the code with the following command:
emcc hello.cpp -o hello.html
Now, you will get three output files, hello.html, hello.js and hello.wasm, shown as follows:
my-hello-world-demo
├───hello.cpp
└───hello.html
└───hello.js
└───hello.wasm
hello.html is the default web page, and hello.js is the code logic running on it, designed by the Emscripten SDK.
Next, you will install Python from https://www.python.org. Now, open your command line or terminal and move to my-hello-world-demo and enter python -m http.server, python will start a server listening on port 8000. Open your browser and navigate to http://localhost:8000, it will show the files under my-hello-world-demo, then click hello.html, a default frontend page provided by emscripten will show. Refer to Figure 1.1:
Figure 1.1: Default Frontend Web Page
In the black box area, it shows Hello World! that we printed. A web that is actually running the C++ code. If we open the DevTools and switch to Console Tab, Hello World! is also printed there.
Call WebAssembly from JavaScript
Now, let us try something different, write a simple C++ function that can be called by the page using JavaScript. Create another file function.cpp and write the following code:
#include
extern C
{
EMSCRIPTEN_KEEPALIVE
int myAddFunc(int a, int b)
{
int c = a + b;
return c;
}
EMSCRIPTEN_KEEPALIVE
int myMinusFunc(int a, int b)
{
int c = a - b;
return c;
}
}
We have two functions here, myAddFunc will get the sum of two integers and myMinusFunc will get the subtraction. Similarly, compile with the command:
emcc function.cpp -o function.html
And the folder would look like:
my-hello-world-demo
├───function.cpp
└───function.html
└───function.js
└───function.wasm
└───hello.cpp
└───hello.html
└───hello.js
└───hello.wasm
We use python to start a server again and go to http://localhost:8000/function.html. Nothing was printed in the black box area this time and that's because we did not print anything in the function! But we can call the two math functions provided by WebAssembly this time. Open the DevTools, switch to the Console tab and write _myAddFunc(1,2) and you will get 3 as the result. In fact, when you are typing _myAddFunc the IntelliSense will tell you that the function does exist in the context of page function.html. Try _myMinusFunc and it will work as well. How exactly the web page loads the two math functions we wrote here? Let us take a look at the generate function.html and function.js:
var statusElement = document.getElementById('status');
var progressElement = document.getElementById('progress');
var spinnerElement = document.getElementById('spinner');
var Module = {
preRun: [],
postRun: [],
print: (function() {
var element = document.getElementById('output');
if (element) element.value = ''; // clear browser cache
return function(text) {
if (arguments.length > 1) text = Array.prototype.slice.call(arguments).join(' ');
console.log(text);
if (element) {
element.value += text + \n
;
element.scrollTop = element.scrollHeight; // focus on bottom
}
};
})(),
canvas: (function() {
// draw canvas
})(),
setStatus: function(text) {
// set status
},
totalDependencies: 0,
// some code here
};
Module.setStatus('Downloading...');
// some code here
In the HTML body, it defines the frontend layout and page logic. We will focus on the script section. It first initiated a Module object, which has a few properties, for example, print, canvas, setStatus. print shows Hello World! in the previous code example on the web page by changing the value of the element with ID output
and print it to the console as well with console.log(text);. setStatus is actually called when the page is first loaded and if you refresh the page a few times quickly, you will see a caption says Downloading…. And you might already guess it. It is downloading the WebAssembly file, function.wasm. Next, we will discuss how the function.wasm was loaded and how the function was called:
var asm = createWasm();
function createWasm() {
function receiveInstance(instance, module) {
var exports = instance.exports;
Module['asm'] = exports;
}
function receiveInstantiationResult(result) {
receiveInstance(result['instance']);
}
function instantiateArrayBuffer(receiver) {
return getBinaryPromise().then(function (binary) {
return WebAssembly.instantiate(binary, info);
}).then(function (instance) {
return instance;
});
}
function instantiateAsync() {
if (!wasmBinary && typeof WebAssembly.instantiateStreaming == 'function' &&
!isDataURI(wasmBinaryFile) && !isFileURI(wasmBinaryFile) && !ENVIRONMENT_IS_NODE &&
typeof fetch == 'function') {
return fetch(wasmBinaryFile, { credentials: 'same-origin' }).then(function (response) {
var result = WebAssembly.instantiateStreaming(response, info);
return result.then(
receiveInstantiationResult,
function (reason) {
return instantiateArrayBuffer(receiveInstantiationResult);
});
});
} else {
return instantiateArrayBuffer(receiveInstantiationResult);
}
}
if (Module['instantiateWasm']) {
var exports = Module['instantiateWasm'](info, receiveInstance);
return exports;
}
instantiateAsync();
return {};
}
function createExportWrapper(name, fixedasm) {
return function () {
var displayName = name;
var asm = fixedasm;
if (!fixedasm) {
asm = Module['asm'];
}
if (!asm[name]) {
assert(asm[name], 'exported native function `' + displayName + '` not found');
}
return asm[name].apply(null, arguments);
};
}
var _myAddFunc = Module[_myAddFunc
] = createExportWrapper(myAddFunc
);
var _myMinusFunc = Module[_myMinusFunc
] = createExportWrapper(myMinusFunc
);
Here is the key code of function.js, and it is fairly self-explained. A call to createWasm() starting the process. Inside this function, it goes to instantiateAsync() and we can guess from the function name that it will initiate the WebAssembly. And it does provide two ways to instantiate. If possible, it will fetch the wasm file through http protocol, in this case, function.wasm.
In this way, the wasm was loaded as a network stream, so WebAssembly.instantiateStreaming was used to process the http response, and if you open DevTools, switch to Network tab and refresh the page again, you will notice a request to http://localhost:8000/function.wasm and it returns 200. Refer to Figure 1.2:
Figure 1.2: fetch function.wasm
WebAssembly.instantiateStreaming() will be responsible for compiling and initiating the WebAssembly module, and it will be more efficient than load wasm code directly by WebAssembly.instantiate(). In practice, most of the WebAssembly frameworks will choose WebAssembly.instantiateStreaming() to load the WebAssembly and this explains that some websites built by WebAssembly will be take longer to load for the first time than a website built with purely JavaScript, since they will download the .wasm file through network.
Otherwise, it will fall back to WebAssembly.instantiate() inside instantiateArrayBuffer(), and the name of the function indicates that it is load the binary format of .wasm directly.
Once the WebAssembly module was loaded, receiveInstantiationResult() will be the callback to handle the instance of WebAssembly, and instance.exports will be assigned to Module['asm'] to save the exports from the WebAssembly. Finally, two lines of code generated by the Emscripten SDK call createExportWrapper(), and it will find the exported functions by name in Module['asm']. Function apply will be used to run the desired function with arguments.
We can prove it by opening DevTools, switch to Console tab and type: _myAddFunc(2,3) and hit enter. As expected, the result is 5. Or we could use Module['asm'] directly: Module['asm']['myAddFunc'](4,5) and it shows 9 correctly. Great! Now, we know how the WebAssembly runs in the web, but what exactly is in the function.wasm? Can we manually load it?
Introducing .WASM binary format
Let us try another example.
#include
extern C
{
EMSCRIPTEN_KEEPALIVE
int myMultiplyFunc(int a, int b)
{
int c = a * b;
return c;
}
}
This time, we will compile it to .wasm only, without generating html and js file.
In the Terminal, type:
emcc manual.cpp -O3 –no-entry -o manual.wasm
Notice that –no-entry is required since we do not have a main() function and we will build in STANDALONE_WASM mode. And the folder would look like:
my-hello-world-demo
├───function.cpp
└───function.html
└───function.js
└───function.wasm
└───hello.cpp
└───hello.html
└───hello.js
└───hello.wasm
└───manual.cpp
└───manual.wasm
Open manual.wasm with a binary viewer or VS Code with appropriate extensions.
00000000 00 61 73 6d 01 00 00 00 01 17 05 60 00 01 7f 60 .asm…...`..`
00000010 00 00 60 02 7f 7f 01 7f 60 01 7f 00 60 01 7f 01 ..`..`..`..
00000020 7f 03 07 06 01 02 00 03 04 00 04 05 01 70 01 02 ............p..
00000030 02 05 06 01 01 80 02 80 02 06 09 01 7f 01 41 90 .............A.
00000040 88 c0 02 0b 07 80 01 08 06 6d 65 6d 6f 72 79 02 .........memory.
00000050 00 0e 6d 79 4d 75 6c 74 69 70 6c 79 46 75 6e 63 ..myMultiplyFunc
00000060 00 01 19 5f 5f 69 6e 64 69 72 65 63 74 5f 66 75 ..__indirect_fu
00000070 6e 63 74 69 6f 6e 5f 74 61 62 6c 65 01 00 0b 5f nction_table..._
00000080 69 6e 69 74 69 61 6c 69 7a 65 00 00 10 5f 5f 65 initialize...__e
00000090 72 72 6e 6f 5f 6c 6f 63 61 74 69 6f 6e 00 05 09 rrno_location...
000000a0 73 74 61 63 6b 53 61 76 65 00 02 0c 73 74 61 63 stackSave...stac
000000b0 6b 52 65 73 74 6f 72 65 00 03 0a 73 74 61 63 6b kRestore...stack
000000c0 41 6c 6c 6f 63 00 04 09 07 01 00 41 01 0b 01 00 Alloc......A....
000000d0 0a 30 06 03 00 01 0b 07 00 20 00 20 01 6c 0b 04 .0....... . .l..
000000e0 00 23 00 0b 06 00 20 00 24 00 0b 10 00 23 00 20 .#.... .$....#.
000000f0 00 6b 41 70 71 22 00 24 00 20 00 0b 05 00 41 80 .kpq
.$. ....A.
00000100 08 0b ..2
Refer to the following code consisting of the magic number:
00000000 00 61 73 6d 01 00 00 00 01 17 05 60 00 01 7f 60
^^ ^^ ^^ ^^
The first four bytes are what we called the magic numbers, 0x00 0x61 0x73 0x6d representing \0asm if you convert by ASCII code. It means that this is a .wasm file.
00000000 00 61 73 6d 01 00 00 00 01 17 05 60 00 01 7f 60
^^ ^^ ^^ ^^
The next four bytes are the version number, and we have 0x01 0x00 0x00 0x00 (little endian), version 1 here:
00000000 00 61 73 6d 01 00 00 00 01 17 05 60 00 01 7f 60
^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
00000010 00 00 60 02 7f 7f 01 7f 60 01 7f 00 60 01 7f 01
^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^ ^^
00000020 7f 03 07 06 01 02 00 03 04 00 04 05 01 70 01 02
^^
The 9th byte is the start of a section, which composes binary format of WebAssembly. The starting byte of a section represents the section type, and the next byte would be the length of the section. You may refer to the following table for more possible values.
Table 1.1 : WebAssembly Module sections
Sections usually start with 01 – type section, in this section, .wasm defines signatures of functions, or type information. In the first line of the first code discussed in this chapter, 0x01 flags the start of the type section, and the following byte 0x17 indicates that this section has length 23 (excluding type byte and length byte) till byte 0x20. The next byte 0x05 tells us that there