100% found this document useful (1 vote)
23 views81 pages

73057164

The document provides information on various eBooks related to Microsoft Blazor, including titles by Peter Himschoot and others, focusing on building web applications using .NET technologies. It includes links to download these eBooks in multiple formats and highlights features such as instant access and compatibility with various devices. Additionally, it mentions the copyright details and the structure of the content within the eBooks, including chapters and topics covered.

Uploaded by

shyfulmiiros
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
23 views81 pages

73057164

The document provides information on various eBooks related to Microsoft Blazor, including titles by Peter Himschoot and others, focusing on building web applications using .NET technologies. It includes links to download these eBooks in multiple formats and highlights features such as instant access and compatibility with various devices. Additionally, it mentions the copyright details and the structure of the content within the eBooks, including chapters and topics covered.

Uploaded by

shyfulmiiros
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 81

Download the Full Ebook and Access More Features - ebooknice.

com

(Ebook) Microsoft Blazor: Building Web


Applications in .NET 6 and Beyond - Third Edition
by Peter Himschoot ISBN 9781484278444, 1484278445

https://ebooknice.com/product/microsoft-blazor-building-web-
applications-in-net-6-and-beyond-third-edition-36528582

OR CLICK HERE

DOWLOAD EBOOK

Download more ebook instantly today at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Microsoft Blazor: Building Web Applications in


.NET 6 and Beyond by Peter Himschoot ISBN 9781484278451,
9781484278444, 1484278445, 1484278453, B09N94DWXQ
https://ebooknice.com/product/microsoft-blazor-building-web-
applications-in-net-6-and-beyond-46394982

ebooknice.com

(Ebook) Microsoft Blazor: Building Web Applications in


.NET - Second Edition by Peter Himschoot ISBN
9781484259283, 1484259289
https://ebooknice.com/product/microsoft-blazor-building-web-
applications-in-net-second-edition-49857536

ebooknice.com

(Ebook) Blazor Revealed: Building Web Applications in .NET


by Peter Himschoot ISBN 9781484243428, 9781484243435,
1484243420, 1484243439
https://ebooknice.com/product/blazor-revealed-building-web-
applications-in-net-24014974

ebooknice.com

(Ebook) Microsoft Blazor, 2nd Edition by Peter Himschoot

https://ebooknice.com/product/microsoft-blazor-2nd-edition-50195208

ebooknice.com
(Ebook) Building Modern Web Applications with ASP.NET Core
Blazor: Learn how to use Blazor to create powerful,
responsive, and engaging web applications by Brian Ding
ISBN 9789355518798, 935551879X
https://ebooknice.com/product/building-modern-web-applications-with-
asp-net-core-blazor-learn-how-to-use-blazor-to-create-powerful-
responsive-and-engaging-web-applications-52198310
ebooknice.com

(Ebook) Building Single Page Applications in .NET Core 3:


Jumpstart Coding Using Blazor and C# by Michele Aponte
ISBN 9781484257463, 1484257464
https://ebooknice.com/product/building-single-page-applications-in-
net-core-3-jumpstart-coding-using-blazor-and-c-11115594

ebooknice.com

(Ebook) Web Development with Blazor : A practical guide to


start building interactive UIs with C# 12 and .NET 8 by
Jimmy
https://ebooknice.com/product/web-development-with-blazor-a-practical-
guide-to-start-building-interactive-uis-with-c-12-and-net-8-57360704

ebooknice.com

(Ebook) Beginning Azure Static Web Apps: Building and


Deploying Dynamic Web Applications with Blazor by Stacy
Cashmore ISBN 9781484281451, 1484281454
https://ebooknice.com/product/beginning-azure-static-web-apps-
building-and-deploying-dynamic-web-applications-with-blazor-46302574

ebooknice.com

(Ebook) Beginning Azure Static Web Apps: Building and


Deploying Dynamic Web Applications with Blazor by Stacy
Cashmore ISBN 9781484281468, 1484281462
https://ebooknice.com/product/beginning-azure-static-web-apps-
building-and-deploying-dynamic-web-applications-with-blazor-46364368

ebooknice.com
Microsof t
Blazor
Building Web Applications in .NET 6 and
Beyond

Third Edition

Peter Himschoot
Microsoft Blazor
Building Web Applications in
.NET 6 and Beyond
Third Edition

Peter Himschoot
Microsoft Blazor: Building Web Applications in .NET 6 and Beyond

Peter Himschoot
Melle, Belgium

ISBN-13 (pbk): 978-1-4842-7844-4 ISBN-13 (electronic): 978-1-4842-7845-1


https://doi.org/10.1007/978-1-4842-7845-1

Copyright © 2022 by Peter Himschoot


This work is subject to copyright. All rights are reserved by the Publisher, whether the whole or part of the
material is concerned, specifically the rights of translation, reprinting, reuse of illustrations, recitation,
broadcasting, reproduction on microfilms or in any other physical way, and transmission or information
storage and retrieval, electronic adaptation, computer software, or by similar or dissimilar methodology now
known or hereafter developed.
Trademarked names, logos, and images may appear in this book. Rather than use a trademark symbol with
every occurrence of a trademarked name, logo, or image we use the names, logos, and images only in an
editorial fashion and to the benefit of the trademark owner, with no intention of infringement of the
trademark.
The use in this publication of trade names, trademarks, service marks, and similar terms, even if they are not
identified as such, is not to be taken as an expression of opinion as to whether or not they are subject to
proprietary rights.
While the advice and information in this book are believed to be true and accurate at the date of publication,
neither the authors nor the editors nor the publisher can accept any legal responsibility for any errors or
omissions that may be made. The publisher makes no warranty, express or implied, with respect to the
material contained herein.
Managing Director, Apress Media LLC: Welmoed Spahr
Acquisitions Editor: Jonathan Gennick
Development Editor: Laura Berendson
Coordinating Editor: Jill Balzano
Cover designed by eStudioCalamar
Cover image designed by Freepik (www.freepik.com)
Distributed to the book trade worldwide by Springer Science+Business Media New York, 1 New York Plaza,
Suite 4600, New York, NY 10004-1562, USA. Phone 1-800-SPRINGER, fax (201) 348-4505, e-mail
[email protected], or visit www.springeronline.com. Apress Media, LLC is a California LLC and
the sole member (owner) is Springer Science + Business Media Finance Inc (SSBM Finance Inc). SSBM
Finance Inc is a Delaware corporation.
For information on translations, please e-mail [email protected]; for reprint,
paperback, or audio rights, please e-mail [email protected].
Apress titles may be purchased in bulk for academic, corporate, or promotional use. eBook versions and
licenses are also available for most titles. For more information, reference our Print and eBook Bulk Sales
web page at http://www.apress.com/bulk-sales.
Any source code or other supplementary material referenced by the author in this book is available to
readers on GitHub via the book’s product page, located at www.apress.com/978-1-4842-7844-4. For more
detailed information, please visit http://www.apress.com/source-­code.
Printed on acid-free paper
Table of Contents
About the Author���������������������������������������������������������������������������������������������������xvii

About the Technical Reviewer��������������������������������������������������������������������������������xix


Acknowledgments��������������������������������������������������������������������������������������������������xxi

Introduction����������������������������������������������������������������������������������������������������������xxiii

Chapter 1: Introduction to WebAssembly and Blazor����������������������������������������������� 1


A Tale of Two Wars������������������������������������������������������������������������������������������������������������������������ 1
The First Browser War������������������������������������������������������������������������������������������������������������� 2
The Second Browser War�������������������������������������������������������������������������������������������������������� 3
Introducing WebAssembly������������������������������������������������������������������������������������������������������������� 4
Which Browsers Support WebAssembly?�������������������������������������������������������������������������������� 6
WebAssembly and Mono��������������������������������������������������������������������������������������������������������� 7
Interacting with the Browser with Blazor������������������������������������������������������������������������������������� 8
How Does It Work?������������������������������������������������������������������������������������������������������������������ 8
Blazor Server������������������������������������������������������������������������������������������������������������������������� 10
Pros and Cons of the Blazor Server��������������������������������������������������������������������������������������� 11
Your First Blazor Project�������������������������������������������������������������������������������������������������������������� 12
Installing Blazor Prerequisites����������������������������������������������������������������������������������������������� 13
Using Visual Studio���������������������������������������������������������������������������������������������������������������� 13
Using Visual Studio Code������������������������������������������������������������������������������������������������������� 15
Understanding the Blazor Templates for VS/Code����������������������������������������������������������������� 16
Generating the Project with Dotnet CLI��������������������������������������������������������������������������������� 17
Generating Your Project with Visual Studio �������������������������������������������������������������������������� 18
Running Blazor with Visual Studio Code�������������������������������������������������������������������������������� 20
Running the Generated Project��������������������������������������������������������������������������������������������������� 20
Examining the Project’s Parts����������������������������������������������������������������������������������������������������� 23

iii
Table of Contents

The Server Project����������������������������������������������������������������������������������������������������������������� 24


Using a Shared Project���������������������������������������������������������������������������������������������������������� 27
Understanding the Client Blazor Project�������������������������������������������������������������������������������� 28
Layout Components��������������������������������������������������������������������������������������������������������������� 30
Debugging Client-Side Blazor����������������������������������������������������������������������������������������������������� 31
Debugging with Visual Studio������������������������������������������������������������������������������������������������ 32
Debugging with Visual Studio Code��������������������������������������������������������������������������������������� 34
Developing with Hot Reload�������������������������������������������������������������������������������������������������������� 36
Hot Reload with .NET CLI������������������������������������������������������������������������������������������������������� 36
Hot Reload with Visual Studio������������������������������������������������������������������������������������������������ 37
The Blazor WASM Bootstrap Process������������������������������������������������������������������������������������������ 37
The Blazor Server Bootstrap Process����������������������������������������������������������������������������������������� 41
Nullable Reference Types������������������������������������������������������������������������������������������������������������ 43
An Apology����������������������������������������������������������������������������������������������������������������������������� 43
Using Null in C#��������������������������������������������������������������������������������������������������������������������� 43
Using References������������������������������������������������������������������������������������������������������������������ 46
The Null-Forgiving Operator�������������������������������������������������������������������������������������������������� 47
Nullable Reference Types and .NET Libraries������������������������������������������������������������������������ 49
Summary������������������������������������������������������������������������������������������������������������������������������������ 49

Chapter 2: Data Binding������������������������������������������������������������������������������������������ 51


A Quick Look at Razor����������������������������������������������������������������������������������������������������������������� 51
One-Way Data Binding���������������������������������������������������������������������������������������������������������������� 53
One-Way Data Binding Syntax����������������������������������������������������������������������������������������������� 53
Attribute Binding������������������������������������������������������������������������������������������������������������������� 55
Conditional Attributes������������������������������������������������������������������������������������������������������������ 56
Event Handling and Data Binding������������������������������������������������������������������������������������������������ 57
Event Binding Syntax������������������������������������������������������������������������������������������������������������� 57
Event Arguments������������������������������������������������������������������������������������������������������������������� 57
Using C# Lambda Functions�������������������������������������������������������������������������������������������������� 58
Two-Way Data Binding���������������������������������������������������������������������������������������������������������������� 59

iv
Table of Contents

Two-Way Data Binding Syntax����������������������������������������������������������������������������������������������� 59


Binding to Other Events: @bind:{event}��������������������������������������������������������������������������������� 61
Preventing Default Actions���������������������������������������������������������������������������������������������������� 62
Stopping Event Propagation�������������������������������������������������������������������������������������������������� 63
Formatting Dates������������������������������������������������������������������������������������������������������������������� 66
Change Detection������������������������������������������������������������������������������������������������������������������������ 66
The PizzaPlace Single-Page Application������������������������������������������������������������������������������������� 69
Creating the PizzaPlace Project��������������������������������������������������������������������������������������������� 69
Adding Shared Classes to Represent the Data���������������������������������������������������������������������� 70
Building the UI to Show the Menu����������������������������������������������������������������������������������������� 75
Converting Values������������������������������������������������������������������������������������������������������������������ 78
Adding Pizzas to the Shopping Basket���������������������������������������������������������������������������������� 79
Displaying the Shopping Basket�������������������������������������������������������������������������������������������� 81
Entering the Customer Information��������������������������������������������������������������������������������������� 86
Debugging Tip������������������������������������������������������������������������������������������������������������������������ 88
Blazor Validation������������������������������������������������������������������������������������������������������������������������� 90
Letting Entities Validate Themselves������������������������������������������������������������������������������������� 90
Using FormField and InputText to Enable Validation�������������������������������������������������������������� 91
Showing Validation Errors����������������������������������������������������������������������������������������������������� 92
Customizing the Validation Feedback������������������������������������������������������������������������������������ 95
Summary������������������������������������������������������������������������������������������������������������������������������������ 97

Chapter 3: Components and Structure for Blazor Applications������������������������������ 99


What Is a Blazor Component?����������������������������������������������������������������������������������������������������� 99
Examining the SurveyPrompt Component��������������������������������������������������������������������������� 100
Building a Simple Alert Component with Razor������������������������������������������������������������������� 101
Separating View and View Model���������������������������������������������������������������������������������������������� 105
Creating a DismissibleAlert Component������������������������������������������������������������������������������ 105
Understanding Parent-Child Communication���������������������������������������������������������������������������� 107
Adding a Timer Component������������������������������������������������������������������������������������������������� 107
Using Two-Way Data Binding Between Components����������������������������������������������������������� 110
Using EventCallback<T>����������������������������������������������������������������������������������������������������� 114

v
Table of Contents

Referring to a Child Component������������������������������������������������������������������������������������������������ 117


Communicating with Cascading Parameters���������������������������������������������������������������������������� 119
Using the CascadingValue Component�������������������������������������������������������������������������������� 120
Resolving Ambiguities��������������������������������������������������������������������������������������������������������� 122
Component Life Cycle Hooks���������������������������������������������������������������������������������������������������� 123
Life Cycle Overview������������������������������������������������������������������������������������������������������������� 123
SetParametersAsync����������������������������������������������������������������������������������������������������������� 128
OnInitialized and OnInitializedAsync������������������������������������������������������������������������������������ 129
OnParametersSet and OnParametersSetAsync������������������������������������������������������������������� 130
ShouldRender���������������������������������������������������������������������������������������������������������������������� 131
OnAfterRender and OnAfterRenderAsync���������������������������������������������������������������������������� 132
IDisposable�������������������������������������������������������������������������������������������������������������������������� 133
A Word on Asynchronous Methods�������������������������������������������������������������������������������������� 133
Refactoring PizzaPlace into Components��������������������������������������������������������������������������������� 134
Creating a Component to Display a List of Pizzas��������������������������������������������������������������� 134
Showing the ShoppingBasket Component�������������������������������������������������������������������������� 138
Adding the CustomerEntry Component������������������������������������������������������������������������������� 142
Using Cascading Properties������������������������������������������������������������������������������������������������� 145
Disabling the Submit Button������������������������������������������������������������������������������������������������ 148
Summary���������������������������������������������������������������������������������������������������������������������������������� 151

Chapter 4: Advanced Components������������������������������������������������������������������������ 153


Using Templated Components��������������������������������������������������������������������������������������������������� 153
Creating the Grid Templated Component����������������������������������������������������������������������������� 153
Using the Grid Templated Component��������������������������������������������������������������������������������� 155
Specifying the Type Parameter’s Type Explicitly������������������������������������������������������������������ 159
Using Generic Type Constraints������������������������������������������������������������������������������������������� 159
Razor Templates������������������������������������������������������������������������������������������������������������������������ 160
Wig-Pig Syntax�������������������������������������������������������������������������������������������������������������������� 162
Using Blazor Error Boundaries�������������������������������������������������������������������������������������������������� 165
Building a Component Library��������������������������������������������������������������������������������������������������� 168

vi
Table of Contents

Creating the Component Library Project����������������������������������������������������������������������������� 168


Adding Components to the Library�������������������������������������������������������������������������������������� 169
Referring to the Library from Your Project��������������������������������������������������������������������������� 170
Using the Library Components�������������������������������������������������������������������������������������������� 170
Static Resources in a Component Library��������������������������������������������������������������������������������� 172
Virtualization����������������������������������������������������������������������������������������������������������������������������� 173
Displaying a Large Number of Rows����������������������������������������������������������������������������������� 173
Using the Virtualize Component������������������������������������������������������������������������������������������� 177
Adding Paging��������������������������������������������������������������������������������������������������������������������� 178
Dynamic Components��������������������������������������������������������������������������������������������������������������� 182
Component Reuse and PizzaPlace�������������������������������������������������������������������������������������������� 191
Summary���������������������������������������������������������������������������������������������������������������������������������� 194

Chapter 5: Services and Dependency Injection���������������������������������������������������� 197


What Is Dependency Inversion?������������������������������������������������������������������������������������������������ 197
Understanding Dependency Inversion��������������������������������������������������������������������������������� 198
Using the Dependency Inversion Principle�������������������������������������������������������������������������� 199
Adding Dependency Injection���������������������������������������������������������������������������������������������� 201
Using an Inversion-of-Control Container����������������������������������������������������������������������������������� 202
Constructor Dependency Injection�������������������������������������������������������������������������������������� 202
Property Dependency Injection�������������������������������������������������������������������������������������������� 203
Configuring Dependency Injection�������������������������������������������������������������������������������������������� 204
Singleton Dependencies������������������������������������������������������������������������������������������������������ 206
Transient Dependencies������������������������������������������������������������������������������������������������������ 207
Scoped Dependencies��������������������������������������������������������������������������������������������������������� 208
Understanding Blazor Dependency Lifetime����������������������������������������������������������������������������� 209
Blazor WebAssembly Experiment���������������������������������������������������������������������������������������� 211
Blazor Server Experiment���������������������������������������������������������������������������������������������������� 213
Using OwningComponentBase�������������������������������������������������������������������������������������������� 215
The Result of the Experiment���������������������������������������������������������������������������������������������� 217

vii
Table of Contents

Building Pizza Services������������������������������������������������������������������������������������������������������������� 218


Adding the MenuService and IMenuService Abstraction����������������������������������������������������� 219
Ordering Pizzas with a Service�������������������������������������������������������������������������������������������� 223
Summary���������������������������������������������������������������������������������������������������������������������������������� 225

Chapter 6: Data Storage and Microservices��������������������������������������������������������� 227


What Is REST?��������������������������������������������������������������������������������������������������������������������������� 227
Understanding HTTP������������������������������������������������������������������������������������������������������������ 227
Universal Resource Identifiers and Methods����������������������������������������������������������������������� 228
HTTP Status Codes�������������������������������������������������������������������������������������������������������������� 229
Invoking Server Functionality Using REST�������������������������������������������������������������������������������� 229
HTTP Headers���������������������������������������������������������������������������������������������������������������������� 230
JavaScript Object Notation�������������������������������������������������������������������������������������������������� 230
Some Examples of REST Calls��������������������������������������������������������������������������������������������� 231
Building a Simple Microservice Using ASP.NET Core���������������������������������������������������������������� 233
Services and Single Responsibility������������������������������������������������������������������������������������� 233
The Pizza Service���������������������������������������������������������������������������������������������������������������� 234
What Is Entity Framework Core?����������������������������������������������������������������������������������������������� 238
Using the Code-First Approach�������������������������������������������������������������������������������������������� 239
Preparing Your Project for Code-First Migrations���������������������������������������������������������������� 242
Finding Your Database Server’s Connection String������������������������������������������������������������� 244
Creating Your First Code-First Migration����������������������������������������������������������������������������� 246
Generating the Database����������������������������������������������������������������������������������������������������� 250
Enhancing the Pizza Microservice�������������������������������������������������������������������������������������������� 253
Testing Your Microservice Using Postman��������������������������������������������������������������������������� 256
Summary���������������������������������������������������������������������������������������������������������������������������������� 260

Chapter 7: Communication with Microservices��������������������������������������������������� 261


Using the HttpClient Class��������������������������������������������������������������������������������������������������������� 261
Examining the Server Project���������������������������������������������������������������������������������������������� 261
Using a Shared Project. Why?��������������������������������������������������������������������������������������������� 263
Looking at the Client Project����������������������������������������������������������������������������������������������� 264
Emulating a Slow Network in Chrome��������������������������������������������������������������������������������� 266
viii
Table of Contents

Understanding the HttpClient Class������������������������������������������������������������������������������������������ 269


The HttpClientJsonExtensions Methods������������������������������������������������������������������������������ 270
Customizing Serialization with JsonSerializerOptions�������������������������������������������������������� 273
Retrieving Data from the Server����������������������������������������������������������������������������������������������� 273
Implementing the MenuService������������������������������������������������������������������������������������������ 275
Showing a Loading UI���������������������������������������������������������������������������������������������������������� 278
Storing Changes������������������������������������������������������������������������������������������������������������������������ 280
Updating the Database with Orders������������������������������������������������������������������������������������� 280
Building the Order Microservice������������������������������������������������������������������������������������������ 284
Talking to the Order Microservice��������������������������������������������������������������������������������������� 286
Summary���������������������������������������������������������������������������������������������������������������������������������� 288

Chapter 8: Unit Testing����������������������������������������������������������������������������������������� 289


Where Can We Find Bugs?�������������������������������������������������������������������������������������������������������� 289
Requirements���������������������������������������������������������������������������������������������������������������������� 290
Coding��������������������������������������������������������������������������������������������������������������������������������� 290
Integration��������������������������������������������������������������������������������������������������������������������������� 291
Beta Testing������������������������������������������������������������������������������������������������������������������������� 291
Post-release������������������������������������������������������������������������������������������������������������������������ 292
Why Should We Use Unit Tests?������������������������������������������������������������������������������������������������ 292
What Makes a Good Unit Test?�������������������������������������������������������������������������������������������� 292
Unit Testing Blazor Components����������������������������������������������������������������������������������������������� 293
Adding a Unit Test Project���������������������������������������������������������������������������������������������������� 293
Adding bUnit to the Test Project������������������������������������������������������������������������������������������ 294
Write Your First Unit Test����������������������������������������������������������������������������������������������������������� 295
Writing Good Unit Test Methods������������������������������������������������������������������������������������������ 295
Running Your Tests�������������������������������������������������������������������������������������������������������������� 296
Making Your Test Pass��������������������������������������������������������������������������������������������������������� 299
Using Facts and Theories���������������������������������������������������������������������������������������������������� 300
Checking Your Sanity����������������������������������������������������������������������������������������������������������� 301

ix
Table of Contents

Write a bUnit Tests with C#������������������������������������������������������������������������������������������������������� 303


Understanding bUnit?���������������������������������������������������������������������������������������������������������� 303
Testing Component Interaction�������������������������������������������������������������������������������������������� 308
Passing Parameters to Our Component������������������������������������������������������������������������������� 311
Testing Two-Way Data Binding and Events�������������������������������������������������������������������������� 315
Testing Components that Use RenderFragment������������������������������������������������������������������ 317
Using Cascading Parameters���������������������������������������������������������������������������������������������� 325
Using MOQ to Create Fake Implementations���������������������������������������������������������������������������� 327
Injecting Dependencies with bUnit�������������������������������������������������������������������������������������� 328
Replacing Dependencies with Fake Objects����������������������������������������������������������������������� 330
Using Stubs������������������������������������������������������������������������������������������������������������������������� 331
Using Mocks������������������������������������������������������������������������������������������������������������������������ 333
Implementing Stubs and Mocks with MOQ������������������������������������������������������������������������� 336
Writing bUnit Tests in Razor������������������������������������������������������������������������������������������������������ 339
The First Razor Test������������������������������������������������������������������������������������������������������������� 339
Handling Asynchronous Re-renders������������������������������������������������������������������������������������������ 343
Configuring Semantic Comparison������������������������������������������������������������������������������������������� 345
Why Do We Need Semantic Comparison?��������������������������������������������������������������������������� 346
Customizing Semantic Comparison������������������������������������������������������������������������������������� 346
Summary���������������������������������������������������������������������������������������������������������������������������������� 349

Chapter 9: Single-Page Applications and Routing������������������������������������������������ 351


What Is a Single-Page Application?������������������������������������������������������������������������������������������ 351
Single-Page Applications����������������������������������������������������������������������������������������������������� 352
Layout Components������������������������������������������������������������������������������������������������������������������ 352
Using Blazor Layout Components���������������������������������������������������������������������������������������� 352
Configuring the Default Layout Component������������������������������������������������������������������������� 355
Selecting a Layout Component�������������������������������������������������������������������������������������������� 357
Nesting Layouts������������������������������������������������������������������������������������������������������������������� 359
Blazor Routing��������������������������������������������������������������������������������������������������������������������������� 360
Installing the Router������������������������������������������������������������������������������������������������������������ 360
The NavMenu Component��������������������������������������������������������������������������������������������������� 361

x
Table of Contents

Setting the Route Template������������������������������������������������������������������������������������������������� 364


Redirecting to Other Pages�������������������������������������������������������������������������������������������������� 366
Understanding the Base Tag������������������������������������������������������������������������������������������������ 368
Lazy Loading with Routing�������������������������������������������������������������������������������������������������������� 369
Lazy Loading Component Libraries������������������������������������������������������������������������������������� 369
Marking an Assembly for Lazy Loading������������������������������������������������������������������������������� 371
Dynamically Loading an Assembly�������������������������������������������������������������������������������������� 372
Lazy Loading and Dependencies����������������������������������������������������������������������������������������� 374
Adding Another Page to PizzaPlace������������������������������������������������������������������������������������������ 377
Summary���������������������������������������������������������������������������������������������������������������������������������� 386

Chapter 10: JavaScript Interoperability��������������������������������������������������������������� 389


Calling JavaScript from C#�������������������������������������������������������������������������������������������������������� 389
Providing a Glue Function���������������������������������������������������������������������������������������������������� 389
Using IJSRuntime to Call the Glue Function������������������������������������������������������������������������ 390
Storing Data in the Browser with Interop���������������������������������������������������������������������������� 390
Passing a Reference to JavaScript�������������������������������������������������������������������������������������� 393
Calling .NET Methods from JavaScript�������������������������������������������������������������������������������������� 395
Adding a Glue Function Taking a .NET Instance������������������������������������������������������������������ 396
Using Services for Interop��������������������������������������������������������������������������������������������������������� 398
Building the LocalStorage Service�������������������������������������������������������������������������������������� 398
Dynamically Loading JavaScript with Modules������������������������������������������������������������������������ 403
Using JavaScript Modules��������������������������������������������������������������������������������������������������� 403
Loading the Module into a Blazor Service��������������������������������������������������������������������������� 404
Adding a Map to PizzaPlace������������������������������������������������������������������������������������������������������ 406
Choosing the Map JavaScript Library���������������������������������������������������������������������������������� 406
Adding the Leaflet Library��������������������������������������������������������������������������������������������������� 407
Building the Leaflet Map Razor Library������������������������������������������������������������������������������� 408
Registering with the Map Provider�������������������������������������������������������������������������������������� 409
Creating the Map Component���������������������������������������������������������������������������������������������� 409
Consuming the Map Component����������������������������������������������������������������������������������������� 411
Adding Markers to the Map������������������������������������������������������������������������������������������������� 413
Summary���������������������������������������������������������������������������������������������������������������������������������� 419
xi
Table of Contents

Chapter 11: Blazor State Management����������������������������������������������������������������� 421


Examining Component State����������������������������������������������������������������������������������������������������� 421
What Not to Store���������������������������������������������������������������������������������������������������������������� 422
Local Storage����������������������������������������������������������������������������������������������������������������������� 422
The Server��������������������������������������������������������������������������������������������������������������������������� 426
URL�������������������������������������������������������������������������������������������������������������������������������������� 432
Using Protected Browser Storage��������������������������������������������������������������������������������������������� 433
The Redux Pattern�������������������������������������������������������������������������������������������������������������������� 434
The Big Picture�������������������������������������������������������������������������������������������������������������������� 434
The Application Store���������������������������������������������������������������������������������������������������������� 435
Actions��������������������������������������������������������������������������������������������������������������������������������� 435
Reducers����������������������������������������������������������������������������������������������������������������������������� 436
Views����������������������������������������������������������������������������������������������������������������������������������� 436
Using Fluxor������������������������������������������������������������������������������������������������������������������������������ 436
Creating the Store��������������������������������������������������������������������������������������������������������������� 437
Using the Store in Our Blazor Application���������������������������������������������������������������������������� 438
Adding an Action����������������������������������������������������������������������������������������������������������������� 441
Implementing the Reducer�������������������������������������������������������������������������������������������������� 441
Redux Effects���������������������������������������������������������������������������������������������������������������������������� 443
Adding the First Action�������������������������������������������������������������������������������������������������������� 444
Adding the Second Action and Effect���������������������������������������������������������������������������������� 446
Summary���������������������������������������������������������������������������������������������������������������������������������� 448

Chapter 12: Building Real-Time Applications with Blazor and SignalR��������������� 449
What Is SignalR?����������������������������������������������������������������������������������������������������������������������� 449
How Does SignalR Work?���������������������������������������������������������������������������������������������������� 449
Building a WhiteBoard Application�������������������������������������������������������������������������������������������� 450
Creating the WhiteBoard Solution���������������������������������������������������������������������������������������� 450
Implementing the Mouse Handling Logic���������������������������������������������������������������������������� 453
Painting the Segments on the Board����������������������������������������������������������������������������������� 455
Adding a SignalR Hub on the Server����������������������������������������������������������������������������������������� 458
Implementing the BoardHub Class�������������������������������������������������������������������������������������� 458

xii
Table of Contents

Configuring the Server�������������������������������������������������������������������������������������������������������� 459


Implementing the SignalR Client����������������������������������������������������������������������������������������������� 461
Making the SignalR Hub Connection����������������������������������������������������������������������������������� 461
Notifying the Hub from the Client���������������������������������������������������������������������������������������� 462
Cleaning Up the Hub Connection����������������������������������������������������������������������������������������� 463
Summary���������������������������������������������������������������������������������������������������������������������������������� 464

Chapter 13: Efficient Communication with gRPC������������������������������������������������� 465


What Is gRPC?��������������������������������������������������������������������������������������������������������������������������� 465
Pros and Cons of RPC���������������������������������������������������������������������������������������������������������� 465
Understanding gRPC������������������������������������������������������������������������������������������������������������ 466
Protocol Buffers������������������������������������������������������������������������������������������������������������������� 466
Describing Your Network Interchange with Proto Files������������������������������������������������������������� 467
Installing the gRPC Tooling�������������������������������������������������������������������������������������������������� 467
Adding the Service Contract������������������������������������������������������������������������������������������������ 469
Implementing gRPC on the Server�������������������������������������������������������������������������������������������� 471
Implementing the Service��������������������������������������������������������������������������������������������������� 472
Adding gRPC������������������������������������������������������������������������������������������������������������������������ 473
Building a gRPC Client in Blazor����������������������������������������������������������������������������������������������� 475
Creating the ForecastGrpcService��������������������������������������������������������������������������������������� 475
Enabling gRPC on the Client������������������������������������������������������������������������������������������������ 477
Updating the FetchData Component������������������������������������������������������������������������������������ 478
Comparing REST with gRPC������������������������������������������������������������������������������������������������������ 479
Summary���������������������������������������������������������������������������������������������������������������������������������� 482

Chapter 14: Supporting Multiple Languages in Your Blazor Application�������������� 483


Understanding Internationalization, Globalization, and Localization����������������������������������������� 483
Representing the User’s Locale������������������������������������������������������������������������������������������������ 484
CurrentCulture vs. CurrentUICulture������������������������������������������������������������������������������������ 486
Enabling Multiple Languages���������������������������������������������������������������������������������������������������� 486
Using Request Localization������������������������������������������������������������������������������������������������� 486
Internationalizing Your App������������������������������������������������������������������������������������������������������� 492

xiii
Table of Contents

Localizing Your App������������������������������������������������������������������������������������������������������������������� 494


Adding Your First Resource File������������������������������������������������������������������������������������������� 494
Localizing SurveyPrompt����������������������������������������������������������������������������������������������������� 496
Understanding Resource Lookup����������������������������������������������������������������������������������������� 498
Adding a Language Picker in Blazor Server������������������������������������������������������������������������������ 499
Making PizzaPlace International����������������������������������������������������������������������������������������������� 506
Enabling Globalization Data������������������������������������������������������������������������������������������������� 506
Globalizing Your Components���������������������������������������������������������������������������������������������� 507
Adding a Language Picker in Blazor WebAssembly������������������������������������������������������������� 512
Using Global Resources������������������������������������������������������������������������������������������������������������ 518
Summary���������������������������������������������������������������������������������������������������������������������������������� 519

Chapter 15: Deploying Your Blazor Application���������������������������������������������������� 521


Deploying Standalone Blazor WebAssembly����������������������������������������������������������������������������� 521
Hosting on GitHub���������������������������������������������������������������������������������������������������������������� 521
Creating a Simple Website�������������������������������������������������������������������������������������������������� 523
Deploying a Simple Site in GitHub��������������������������������������������������������������������������������������� 524
Deploying a Blazor WASM Project��������������������������������������������������������������������������������������� 525
Fix the Base Tag������������������������������������������������������������������������������������������������������������������ 531
Disabling Jekyll������������������������������������������������������������������������������������������������������������������� 533
Fixing GitHub 404s�������������������������������������������������������������������������������������������������������������� 534
Alternatives for GitHub�������������������������������������������������������������������������������������������������������� 535
Deploying Your Site As WebAssembly��������������������������������������������������������������������������������������� 535
Deploying Hosted Applications�������������������������������������������������������������������������������������������������� 536
Understanding the Deployment Models������������������������������������������������������������������������������ 536
Deploying to Microsoft Azure����������������������������������������������������������������������������������������������� 537
Creating the Publishing Profile�������������������������������������������������������������������������������������������� 537
Selecting Publishing Options����������������������������������������������������������������������������������������������� 543
Publishing the Application��������������������������������������������������������������������������������������������������� 545
Summary���������������������������������������������������������������������������������������������������������������������������������� 546

xiv
Table of Contents

Chapter 16: Security with OpenId Connect����������������������������������������������������������� 547


Representing the User�������������������������������������������������������������������������������������������������������������� 547
Using Claims-Based Security���������������������������������������������������������������������������������������������� 547
Understanding Token Serialization�������������������������������������������������������������������������������������� 549
Representing Claims in .NET����������������������������������������������������������������������������������������������� 550
OpenId Connect������������������������������������������������������������������������������������������������������������������������� 551
Understanding OpenId Connect Hybrid Flow����������������������������������������������������������������������� 551
Identity Providers���������������������������������������������������������������������������������������������������������������������� 553
Implementing the Identity Provider with IdentityServer4���������������������������������������������������� 553
Adding the Login UI to Our Identity Provider����������������������������������������������������������������������� 558
Understanding User Consent���������������������������������������������������������������������������������������������������� 561
Protecting a Blazor Server Application with Hybrid Flow���������������������������������������������������������� 562
Adding OpenId Connect to Blazor Server���������������������������������������������������������������������������� 563
Implementing Authorization in Blazor Server���������������������������������������������������������������������� 564
Using AuthorizeView������������������������������������������������������������������������������������������������������������ 572
Adding and Removing Claims���������������������������������������������������������������������������������������������� 577
Enabling Role-Based Security��������������������������������������������������������������������������������������������� 580
Accessing a Secured API����������������������������������������������������������������������������������������������������������� 583
Using an Access Token�������������������������������������������������������������������������������������������������������� 584
Registering the API Project with the Identity Provider��������������������������������������������������������� 587
Adding JWT Bearer Token Middleware�������������������������������������������������������������������������������� 589
Enabling the Bearer Token in the Client������������������������������������������������������������������������������� 591
Using Policy-Based Access Control������������������������������������������������������������������������������������� 595
Summary���������������������������������������������������������������������������������������������������������������������������������� 603

Chapter 17: Securing Blazor WebAssembly��������������������������������������������������������� 605


Authorization Code Flow with PKCE������������������������������������������������������������������������������������������ 605
Understanding PKCE������������������������������������������������������������������������������������������������������������ 606
Registering the WASM Client Application���������������������������������������������������������������������������������� 607
Creating and Examining the Application������������������������������������������������������������������������������ 607
Registering the Client Application��������������������������������������������������������������������������������������� 610

xv
Table of Contents

Implementing Authentication���������������������������������������������������������������������������������������������� 611


Customizing the Login Experience�������������������������������������������������������������������������������������� 614
Accessing a Protected API�������������������������������������������������������������������������������������������������������� 615
Fetching Data from the WeatherService API������������������������������������������������������������������������ 615
Using the AuthorizationMessageHandler����������������������������������������������������������������������������� 618
Adding Client-Side Authorization����������������������������������������������������������������������������������������� 620
Using Role-Based Security������������������������������������������������������������������������������������������������������� 621
Creating the Claims Component������������������������������������������������������������������������������������������ 621
Enabling RBAC��������������������������������������������������������������������������������������������������������������������� 624
Promoting the Role Claim���������������������������������������������������������������������������������������������������� 626
Using Policy-Based Access Control������������������������������������������������������������������������������������������� 628
Updating Scopes����������������������������������������������������������������������������������������������������������������� 628
Adding Policies�������������������������������������������������������������������������������������������������������������������� 629
Summary���������������������������������������������������������������������������������������������������������������������������������� 631

Index��������������������������������������������������������������������������������������������������������������������� 633

xvi
About the Author
Peter Himschoot works as a lead trainer, architect,
and strategist at U2U. He has a wide interest in software
development that includes applications for the Web,
Windows, and mobile devices. He has trained thousands of
developers, is a regular speaker at international conferences,
and has been involved in many web and mobile
development projects as a software architect. He has been
a Microsoft Regional Director (from 2003 to 2019) and co-
founded the Belgian Visual Studio User Group (VISUG) in
2006, which is a group of trusted advisors to developer and
IT professional audiences and to Microsoft.

xvii
About the Technical Reviewer
Gerald Versluis (@jfversluis) is a software engineer at
Microsoft from the Netherlands. With years of experience
working with Azure, ASP.NET, Xamarin (now .NET MAUI),
and other .NET technologies, he has been involved in
numerous projects and has been building several real-world
apps and solutions.
Not only does he like to code, but he is also passionate
about spreading his knowledge – as well as gaining some in
the bargain. Gerald involves himself in speaking, providing
training sessions, writing blogs or articles, recording videos for his YouTube channel,
and contributing to open source projects in his spare time.
Twitter: @jfversluis
Website: https://jfversluis.dev

xix
Acknowledgments
When Jonathan Gennick from Apress asked me if I would be interested in writing a book
on Blazor, I felt honored and of course I agreed that Blazor deserves a book. Writing a
book is a group effort, so I thank Jonathan Gennick and Jill Balzano for giving me tips
on styling and writing this book, and I thank Gerald Versluis for doing the technical
review and pointing out sections that needed a bit more explaining. I also thank Magda
Thielman and Lieven Iliano from U2U, my employer, for encouraging me to write
this book.
I thoroughly enjoyed writing this book, and I hope you will enjoy reading and
learning from it.

Second Edition
As the first edition of Blazor Revealed was published (using pre-release software), the
Blazor team had made a bunch of changes to the razor syntax, stopping my examples
in the first edition of Blazor Revealed from working. Now that Blazor has been released
and is completely official (YEAH!!!!), the time has come to publish an updated version of
Blazor Revealed, now renamed as Microsoft Blazor.
Should you get stuck with an example, I invite you to consult the accompanying code
samples for comparison purposes.

Third Edition
I wrote the third edition of Microsoft Blazor using the previews of .NET 6 to get this book
in your hands right after the official release of .NET 6. This of course means that the
last-minute changes made in October 2021 could not make it to this book. However,
I have set up a repository in GitHub where you can find last-minute additions and errata
at https://github.com/PeterHimschoot/microsoft-­blazor-­book-­3, including every
sample and exercise using the latest version of .NET.

xxi
Introduction
Full Stack Web Development with C#
Building modern Single-Page Application websites today typically means writing
JavaScript on the client and C# on the server when you are using the Microsoft
development stack. But with Blazor, you can build everything using C# and reuse the
knowledge and experience you gained with .NET. Porting existing C# applications like
WinForms to the Web does not involve translating some of your logic to JavaScript; you
can again reuse most of this code, resulting in less testing and bugs.

Is This Book for You?


This book assumes you know C#, and you have some experience writing applications
with it. Since this is also about web development, basic knowledge about HTML, CSS,
and JavaScript is also required. Completing this book will allow you to build professional
applications with Blazor, including mastery of some harder topics like authentication.
You will see learning Blazor is fun!

Practical Development
I wrote this book with practice in mind, so sit down next to your computer and follow
along with the examples; the best way to learn is to just do things with Blazor. I did my
best to make the code samples easy to read, but this means breaking lines of code to fit
nicely on the page. When in doubt, you can always consult the included code, which
you can download from the book's product page, located at www.apress.com/{{ISBN}}.
You can find last-minute additions and errata at https://github.com/PeterHimschoot/
microsoft-­blazor-­book-­3, including every sample and exercise using the latest version
of .NET.

xxiii
CHAPTER 1

Introduction
to WebAssembly
and Blazor
I was attending the Microsoft Most Valued Professional and Regional Directors summit
2018 where we were introduced to Blazor for the first time by Steve Sanderson and
Daniel Roth. And I must admit I was super excited about Blazor! Blazor is a framework
that allows you to build Single-Page Applications (SPAs) using C# and allows you to run
any standard .NET library in the browser. Before Blazor, your options for building a SPA
were Angular, React, Vue.js (and others) using JavaScript, or one of the other higher-­
level languages like TypeScript (which gets compiled into JavaScript anyway). In this
introduction, we will look at how browsers are now capable of running .NET assemblies
in the browser using WebAssembly and Blazor.

A Tale of Two Wars


Think about it. The browser is one of the primary applications on your computer. You
use it every day. Companies that build browsers know that very well and are bidding for
you to use their browser. At the beginning of mainstream Internet, everyone was using
Netscape, and Microsoft wanted a share of the market, so in 1995, they built Internet
Explorer 1.0, released as part of Windows 95 Plus! pack.

1
© Peter Himschoot 2022
P. Himschoot, Microsoft Blazor, https://doi.org/10.1007/978-1-4842-7845-1_1
Chapter 1 Introduction to WebAssembly and Blazor

The First Browser War


Newer versions were released rapidly, and browsers started to add new features such as
<blink> and <marquee> elements. This was the beginning of the first browser war, giving
people (especially designers) headaches because some developers were building pages
with blinking marquee controls 😊. But developers were also getting sore heads because
of incompatibilities between browsers. The first browser war was about having more
HTML capabilities than the competition.
But all of this is now behind us with the introduction of HTML5 and modern
browsers like Google Chrome, Microsoft Edge, Firefox, Safari, and Opera. HTML5 not
only defines a series of standard HTML elements but also rules on how these should
render, making it a lot easier to build a website that looks the same in all modern
browsers. Then, in 1995, Brendan Eich wrote a little programming language known
as ECMAScript (initially called LiveScript) in ten days (What!?). It was quickly dubbed
JavaScript because its syntax was very similar to Java. I will be using the name JavaScript
here because that is what most people call it.
JavaScript and Java are not related. Java and JavaScript have as much in common as
ham and hamster (I don’t know who formulated this first, but I love this phrasing).
Little did Mr. Eich know how this language would impact the modern Web and
even desktop application development. In 1995, Jesse James Garrett wrote a white
paper called Ajax (Asynchronous JavaScript and XML), describing a set of technologies
where JavaScript is used to load data from the server and that data is used to update
the browser’s HTML. This avoids full page reloads and allows for client-side web
applications, which are applications written in JavaScript that run completely in the
browser. One of the first companies to apply Ajax was Microsoft when they built Outlook
Web Access (OWA). OWA is a web application almost identical to the Outlook desktop
application proving the power of Ajax. Soon other Ajax applications started to appear,
with Google Maps stuck in my memory as one of the other keystone applications. Google
Maps would download maps asynchronously and with some simple mouse interactions
allowed you to zoom and pan the map. Before Google Maps, the server would do the
map rendering and a browser displayed the map like any other image by downloading a
bitmap from a server.
Building an Ajax website was a major undertaking that only big companies like
Microsoft and Google could afford. This soon changed with the introduction of
JavaScript libraries like jQuery and knockout.js (knockout was also written by Steve
Sanderson, the author of Blazor!). Today, we build rich web apps with Angular, React,

2
Chapter 1 Introduction to WebAssembly and Blazor

and Vue.js. All of them are using JavaScript or higher-level languages like TypeScript
which gets transpiled into JavaScript.
Transpiling will take one language and convert it into another language. This is very
popular with TypeScript which gives you a modern high-level typed language. You need
JavaScript to run it in a browser, so TypeScript gets “transpiled” into JavaScript.

The Second Browser War


This brings us back to JavaScript and the second browser war. JavaScript performance
is paramount in modern browsers. Chrome, Edge, Firefox, Safari, and Opera are all
competing with one another, trying to convince users that their browser is the fastest
with cool-sounding names for their JavaScript engine like V8 and Chakra. These engines
use the latest optimization tricks like Just-In-Time (JIT) compilation where JavaScript
gets converted into native code as illustrated in Figure 1-1.

Figure 1-1. The JavaScript Execution Process

This process takes a lot of effort because JavaScript needs to be downloaded into
the browser, where it gets parsed, then compiled into bytecode, and then Just-In-Time
converted into native code. So how can we make this process even faster?
The second browser war is all about JavaScript performance.

3
Chapter 1 Introduction to WebAssembly and Blazor

Introducing WebAssembly
WebAssembly allows you to take the parsing and compiling to the server, before your
users even open up their browser. With WebAssembly, you compile your code in a
format called WASM (an abbreviation of WebASseMbly), which gets downloaded by the
browser where it gets Just-In-Time compiled into native code as in Figure 1-2.

Figure 1-2. The WebAssembly Execution Process

Open your browser and open https://earth.google.com. This should take you to
the Google Earth app written in WebAssembly as shown in Figure 1-3. Play around with
this a little bit and you will see that this application has excellent performance, but the
initial load takes a fair amount of time because it needs to download the whole WASM
application’s code.

4
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-3. Google Earth in WebAssembly

What is WebAssembly? From the official site webassembly.org:


WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based
virtual machine. Wasm is designed as a portable target for compilation of high-level
languages like C/C++/Rust, enabling deployment on the web for client and server
applications.
So WebAssembly as a new binary format optimized for browser execution, it is
NOT JavaScript. It uses a stack-based virtual machine, just like .NET does. There are
compilers for languages like C++ and Rust which compile to WASM. Some people
have compiled C++ applications to WASM, allowing to run them in the browser.
There is even a Windows 2000 operating system (https://bellard.org/jslinux/
vm.html?url=https://bellard.org/jslinux/win2k.cfg&mem=192&graphic=1&w=1024
&h=768) compiled to WASM so you can play minesweeper as shown in Figure 1-4!

5
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-4. Windows 2000 Running in the Browser

Which Browsers Support WebAssembly?


WebAssembly is supported by all major browsers: Chrome, Edge, Safari, Opera, and
Firefox, including their mobile versions. You can verify support yourself by visiting
https://caniuse.com/?search=WASM as shown in Figure 1-5.

6
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-5. WebAssembly Support

As WebAssembly will become more and more important, we will see other browsers
follow suit, but don’t expect Internet Explorer to support WASM.

WebAssembly and Mono


Mono is an open source implementation of the .NET CLI specification, meaning that
Mono is a platform for running .NET assemblies. Mono is used in Xamarin (now called
Multi-platform App UI, or MAUI for short) for building mobile applications that run on
the Windows, Android, and iOS mobile operating systems. You can also use it to build
applications for macOS, Linux, Tizen, and others. Mono also allows you to run .NET on
Linux (its original purpose) and is written in C++. This last part is important because
we saw that you can compile C++ to WebAssembly. So, what happened is that the Mono
team decided to try to compile Mono to WebAssembly, which they did successfully.
There are two approaches. One is where you take your .NET code and you compile it
together with the Mono runtime into one big WASM application. However, this approach
takes a lot of time because you need to take several steps to compile everything into
WASM, not so practical for day-to-day development. The other approach takes the Mono
runtime and compiles it into WASM, and this runs in the browser where it will execute
.NET Intermediate Language just like normal .NET does. The big advantage is that you
can simply run .NET assemblies without having to compile them first into WASM.

7
Chapter 1 Introduction to WebAssembly and Blazor

This is the approach currently taken by Blazor. In the beginning, Blazor used the
Mono runtime, but they have now built their own .NET Core runtime for WebAssembly.
But Blazor is not the only one taking this approach. For example, there is the Ooui
project which allows you to run Xamarin.Forms applications in the browser. The
disadvantage of this is that it needs to download a lot of .NET assemblies. This can be
solved by using tree shaking algorithms which remove all unused code from assemblies.
We will look at this in Chapter 15.

Interacting with the Browser with Blazor


WebAssembly with the .NET runtime allows you to run .NET code in the browser. Steve
Sanderson used this to build Blazor. Blazor uses the popular ASP.NET MVC approach
for building applications that run in the browser. MVC uses the razor syntax to generate
HTML on the server. With Blazor, you build razor files (Blazor = Browser + Razor) which
execute inside to browser to dynamically build a web page. With Blazor, you don’t need
JavaScript to build a web app, which is good news for thousands of .NET developers
who want to continue using C# (or F#). To use some browser features, you will still need
JavaScript, and we will discuss this in Chapter 10.

How Does It Work?


Let’s start with a simple razor file in Listing 1-1 which you can find when you create
a new Blazor project (which we will do further on in this chapter, no need to type
anything yet).

Note Each code sample has been formatted for readability, sometimes splitting
lines where this is not necessary and using less indentation. I leave it to you how
you decide to format your code.

8
Chapter 1 Introduction to WebAssembly and Blazor

Listing 1-1. The Counter Razor File

@page "/counter"

<h1>Counter</h1>

<p role="status">Current count: @currentCount</p>

<button class="btn btn-primary"


        @onclick="IncrementCount">
  Click me
</button>

@code {
  private int currentCount = 0;

  private void IncrementCount()


  {
    currentCount++;
  }
}

This file gets compiled into a .NET class (you’ll find out how later in this book)
which is then executed by the Blazor engine. The result of this execution is a tree-
like structure called the render tree. The render tree is then sent to JavaScript which
updates the DOM to reflect the render tree (creating, updating, and removing HTML
elements and attributes). Listing 1-1 will result in h1, p (with the contents set to the
value of currentCount), and button HTML elements. When you interact with the
page, for example, when you click the button, this will trigger the button’s click event
which will invoke the IncrementCount method from Listing 1-1. The render tree is
then regenerated, and any changes are sent again to JavaScript which will update the
DOM. This process is illustrated in Figure 1-6.

9
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-6. The Blazor WebAssembly DOM Generation Process

This model is very flexible. It allows you to build Progressive Web Apps, and your
app can be embedded in Electron desktop applications of which Visual Studio Code is a
prime example.

Blazor Server
At the August 7, 2018, ASP.NET community standup (www.youtube.com/watch?v=7Eh_
l7jEcCo), Daniel Roth introduced a new execution model for Blazor now called Blazor
Server. In this model, your Blazor site is running on the server resulting in a way smaller
download for the browser.
We just saw that Blazor WebAssembly builds a render tree using the .NET runtime
running in the browser which then gets sent to JavaScript to update the DOM. With
Blazor Server, the render tree is built on the server using regular .NET and then gets
serialized to the browser using SignalR (we will look at SignalR in a later chapter).
JavaScript in the browser then deserializes the render tree to update the DOM. Pretty
similar to the Blazor WebAssembly model. When you interact with the site, events get
serialized back to the server which then executes the .NET code, updating the render
tree, and the changes get serialized back to the browser. I’ve illustrated this process in
Figure 1-7. The big difference is that there is no need to send the .NET runtime and your
Blazor assemblies to the browser. And the programming model stays the same! You can
switch Blazor Server-side and Blazor WebAssembly with just a couple of small changes
to your code.

10
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-7. Blazor Server Runtime Model

Pros and Cons of the Blazor Server


The Blazor Server model has a couple of benefits but also some drawbacks. Let’s discuss
these here so you can decide which model fits your application’s needs.

• Smaller downloads: With Blazor Server, your application does not


need to download dotnet.wasm (the .NET runtime) nor all your .NET
assemblies. The browser downloads a small JavaScript library which
sets up the SignalR connection to the server. This means that the
application will start a lot faster, especially on slower connections,
but at the price that we continuously need a connection to the server
to exchange small messages.

• Development process: Blazor WebAssembly does not support all


modern debugging capabilities, resulting in added logging. Because
your .NET code is running on the server, you can use the regular
.NET debugger with all of its advanced features. You could start
building your Blazor application using the server-side model, and
when it is finished, switch to the client-side model by switching the
hosting model.

11
Chapter 1 Introduction to WebAssembly and Blazor

• .NET APIs: Because you are running your .NET code on the server,
you can use all the .NET APIs you would use with regular ASP.NET
Core MVC applications, for example, accessing the database directly.
Do note that doing this will stop you from quickly converting it into
a client-side application. You can limit this by writing service classes
and using dependency injection to inject different implementations
depending on the environment your components are hosted in.

• Online only: Running the Blazor application on the server does


mean that your users will always need access to the server. This will
prevent the application from running in Electron, nor will you be
able to run it as a Progressive Web Application (PWA). And if the
connection drops between the browser and server, your user could
lose some work because the application will stop functioning. Blazor
will try to reconnect to the server without losing any data, so most of
the time, users will not lose any work done.

• Server scalability: All your .NET code runs on the server, so if you have
thousands of clients, your server(s) will have to handle all the work. Not
only that, Blazor uses a stateful model which will require you to keep track
of every user’s state on the server. So your server will need more resources
than with Blazor WebAssembly which can use a stateless model.

Your First Blazor Project


Getting hands-on is the best way to learn. You will first install the prerequisites to
developing with Blazor. Then you will create your first Blazor project, run the project
to see it work, and finally inspect the different aspects of the project to get a “lay of the
land” view for how Blazor applications are developed.

Note I learned an important lesson from the first edition of this book: never
underestimate the speed at which Microsoft innovates! All code samples in the
first edition of Blazor Revealed became invalid quite rapidly. I do not expect this
to happen again with this edition since it is based on the Release To Manufacture
(RTM) version of Blazor. If something does not work, simply consult the sources
that come with this book. I will keep these up to date. Promise!

12
Chapter 1 Introduction to WebAssembly and Blazor

The source code for this book is available on GitHub via the book’s product page,
located at www.apress.com/ISBN.

Installing Blazor Prerequisites


Working with Blazor requires you to install some prerequisites, so in this section, you will
install what is needed to get going.
Blazor runs on top of .NET, optionally providing the web server for your project
which will serve the client files that run in the browser and run any server-side APIs that
your Blazor project needs. .NET (previously known as .NET Core) is Microsoft’s cross-­
platform solution for working with .NET on Windows, Linux, and OSX.
You can find the installation files at www.microsoft.com/net/download. Look for the
latest version of the .NET SDK (you’ll need at least version 6.0). Follow the installation
instructions and install it on your machine, using Windows, OSX, or Linux.
Verify the installation when the installer is done by opening a new command prompt
and typing the following command:

dotnet --version

Output should indicate that you installed the correct version. The version number
should be at least 6.0.
Should the command’s output show an older version, you will need to download
and install a more recent version of .NET SDK. These can run side by side so you will not
break other .NET projects doing this.

Using Visual Studio


For people using Windows, Visual Studio (from now on, I will refer to Visual Studio as
VS) is one of the integrated development environments (IDE) we will use throughout
this book. If you are using OSX or Linux, you can use Visual Studio Code, and OSX users
might prefer Visual Studio for Mac. With any one, you can edit your code, compile it, and
run it all from the same application. And the code samples are also the same.
If you want to use Visual Studio, download the latest version of Visual Studio from
www.visualstudio.com/downloads/. The Community Edition is free and should allow
you to do everything done in this book.

13
Chapter 1 Introduction to WebAssembly and Blazor

Run the installer and make sure that you install the ASP.NET and web development
role as shown in Figure 1-8.

Figure 1-8. The Visual Studio Installer Workloads Selection

After installation, run Visual Studio from the Start menu. Then open the Help menu
and select About Microsoft Visual Studio. The About Microsoft Visual Studio dialog
window should specify at least version 17.0.0 as illustrated in Figure 1-9.

Figure 1-9. About Microsoft Visual Studio


14
Chapter 1 Introduction to WebAssembly and Blazor

Using Visual Studio Code


Visual Studio Code (VSC) is a free, modern, cross-platform development environment
with an integrated editor, git source control, and debugger. The environment has a huge
range of extensions available allowing you to use all kinds of languages and tools directly
from VSC. So, if you don’t have access to (because you’re running a non-Windows
operating system or you don’t want to use) Visual Studio, use VSC.
Install VSC from www.visualstudio.com/. Install using the defaults.
After installation, you should install a couple of extensions for Code, especially
the C# extension. Start Code, and at the left side, select the extensions tab as shown in
Figure 1-10.

Figure 1-10. Visual Studio Code Extensions Tab

You can search for extensions, so start with C# which is the first extension from
Figure 1-11. This extension will give you IntelliSense and debugging for the C#
programming language and .NET assemblies. You will probably get a newer version
listed, so take the latest.
Click Install.

Figure 1-11. C# for Visual Studio Code

15
Chapter 1 Introduction to WebAssembly and Blazor

Understanding the Blazor Templates for VS/Code


Throughout this book, we will create several different Blazor projects. With .NET Core,
we can use the command-line interface (CLI) to create all kinds of projects, including
Blazor WebAssembly and Blazor Server.
Let us begin by looking at the installed templates; you can list all installed templates
using the following CLI command. You can execute this from a command prompt or
from the VSC Terminal.

dotnet new --list

You will see four columns. The first shows the template’s description, the second
column displays the name, the third lists the languages for which the template is
available, and the last shows the tags, a kind of group name for the template. Among
those listed are the following of interest:

Template Name                                 Short Name


--------------------------------------------  -------------------
Blazor Server App                             blazorserver
Blazor WebAssembly App                        blazorwasm
Class Library                                 classlib
Razor Class Library                           razorclasslib
Razor Component                               razorcomponent
xUnit Test Project                            xunit

With Blazor projects, you have a couple of choices. You can create a standalone
Blazor project (using the blazorwasm template) that does not need server-side code. This
kind of project known as Blazor WebAssembly has the advantage that you can simply
deploy it to any web server which will function as a file server, allowing browsers to
download your site just like any other site. We will look at deployment in a later chapter.
Or you can create a hosted project (adding the --hosted option) with client, server,
and shared code. This kind of Blazor WebAssembly project will require you to host it
where there is .NET Core support because you will execute code on the server as well, for
example, to retrieve data from a database.
The third option is to run all Blazor code on the server (using the blazorserver
template). In this case, the browser will use a SignalR connection to receive UI updates
from the server and to send user interaction back to the server for processing.

16
Chapter 1 Introduction to WebAssembly and Blazor

In this book, we will use the second option (Blazor WebAssembly hosted on ASP.NET
MVC Core) most of the time, but the concepts you will learn in this book are the same
for all three options. You can even develop for Blazor WebAssembly and Blazor Server
at the same time! Why? Because debugging support for Blazor WebAssembly is limited,
so you develop with Blazor Server using all debugger features you know and love. But
you can test everything with Blazor WebAssembly ensuring you can run everything in
the browser later. This is the way I like to work. However, to pull this off, you need some
experience with Blazor first, so keep reading.

Generating the Project with Dotnet CLI


To generate the project with dotnet CLI, which works on any machine, start by opening
a command line, and change the current directory to wherever you want to create the
project. Now execute the following command to create a new Blazor WebAssembly
project. The dotnet is the command line, taking the new instruction, with the template
being blazorwasm. The --hosted option will generate the server project as well. Finally,
we tell it to generate everything in the MyFirstBlazor directory.

dotnet new blazorwasm --hosted -o MyFirstBlazor

This command will take a little while because it will download a bunch of
NuGet packages from the Internet. When the command is ready, you can build your
project using

cd MyFirstBlazor
dotnet build

This should build without any errors.


Now we can run the project from the command line using

cd MyFirstBlazor/Server
dotnet run

This will show you some output, including the URL of the Blazor application:

Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: https://localhost:5001
info: Microsoft.Hosting.Lifetime[14]

17
Chapter 1 Introduction to WebAssembly and Blazor

      Now listening on: http://localhost:5000


info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: C:\Code\GitHub\Microsoft.Blazor.3rd\Ch01\MyFirstBlazor

Open your browser on this address (here https://localhost:5001), and you are
ready to play!

Generating Your Project with Visual Studio


Start Visual Studio and select Create a new project.
Type Blazor in the search box, and select the Blazor WebAssembly App project
template as illustrated in Figure 1-12.

Figure 1-12. Visual Studio New Project Dialog


18
Chapter 1 Introduction to WebAssembly and Blazor

Click Next.
Name your project MyFirstBlazor, choose the location where the project should be
generated, and click Next.
On the next screen, you can select the framework to use. Choose the latest version
(at the time of writing, that is .NET 6.0), leave Authentication type set to None, check the
ASP.NET Core hosted checkbox, and click Create. An example is shown in Figure 1-13.

Figure 1-13. New ASP.NET Core Web Application

Wait for Visual Studio to complete. Then build and run your solution by pressing F5.
After a little while, the browser will open and display the Blazor application.

19
Chapter 1 Introduction to WebAssembly and Blazor

Running Blazor with Visual Studio Code


After creating the project as we did with the CLI, open your solution’s folder (where the
MyFirstBlazor.sln file sits) with VSC. You can do this from the command prompt

code .

Or you can open VSC and then select File ➤ Open Folder….
When Code has loaded everything (be patient), it will pop a question as in
Figure 1-14. Answer Yes. This will add a folder called .vscode with configuration files
adding support for building and running the project from Code. If you already have a
.vscode folder (because you copied an existing project, for example), you will not get this
question.

Figure 1-14. Code Asking to Add Build and Debug Assets

Thanks to this integration with Visual Studio Code, you can simply press F5 to build
and run your project.

Note VSC now uses Workspace Trust which might pop up a dialog asking if you
trust the authors of a project. When opening the provided code download, you will
probably encounter this.

Running the Generated Project


Press F5 or Ctrl-F5 (no debugger) to run (this should work for both VS and VSC). Your
(default) browser should open and display the home page as shown in Figure 1-15.

20
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-15. Your First Application – Home Screen

This generated Single-Page Application (SPA) has on the left side a navigation
menu allowing you to jump between different pages. On the right side, you will see the
selected component; in Figure 1-15, it is showing the Index component. And in the top
right corner, there is an About link to https://blazor.net/ which is the official Blazor
documentation website.
The Index component shows the mandatory “Hello, world!” demo, and it also
contains a survey component you can click to fill out a survey (this is a real survey, so
please let Microsoft know you like Blazor!). The SurveyPrompt is the first example of a
custom Blazor component. We will discuss building components like SurveyPrompt in
Chapters 3 and 4.

21
Chapter 1 Introduction to WebAssembly and Blazor

In the navigation menu, click the Counter link. Doing so opens a simple screen with
a number and a button as illustrated in Figure 1-16. Clicking the button will increment
the counter. Try it!

Figure 1-16. Your First Application – Counter Screen

In the navigation menu, click the Fetch data link. Here, you can watch a (random and
fake) weather forecast as shown in Figure 1-17. This forecast is generated on the server
when asked by the client. This is very important because the client (which is running
in the browser) cannot access data from a database directly, so many times, you need a
server that can access databases and other data storage. Of course, if this was a Blazor
Server application, you can access the database directly because you are running on
the server.

22
Chapter 1 Introduction to WebAssembly and Blazor

Figure 1-17. Your First Application – Fetch data Screen

Examining the Project’s Parts


Now being able to play with these pages is all nice, but let us have a look at how all this
works. We will look starting with the server project which hosts our Blazor website. Then
we will look at the shared project which contains classes used by both server and client.
Finally, we will examine the client project which is the actual Blazor implementation.
Visual Studio, Visual Studio Code, and Visual Studio for Mac use solution files to
group projects that will form an application. So, a typical Blazor WebAssembly project
consists of a server, a client, and a shared project grouped into a single solution. This
simplifies building everything since the solution allows tools to figure out in which order
23
Chapter 1 Introduction to WebAssembly and Blazor

to compile everything. Hey, you could even switch between Visual Studio, VS for Mac,
and VSC because they all use the same project and solution files!

The Server Project


Web applications are a bunch of files that get downloaded by the browser from a server.
It is the server’s job to provide the files to the browser upon request. There is a whole
range of existing servers to choose from, for example, IIS on Windows or Apache on
Linux. ASP.NET Core has a built-in server known as Kestrel that you generated with
the --hosted option, which you can then run on Windows, Linux, or OSX. This is the
preferred option to use during development.
The topic of this book is Blazor, so we’re not going to discuss all the details of the
server project that got generated (Microsoft has very good documentation on .NET Core
at https://docs.microsoft.com/aspnet/core), but I do want to show you an important
thing. In the server project (MyFirstBlazor.Server), look for Program.cs. Open this file
and scroll down to the Configure section (look for the comment) shown in Listing 1-2.

Listing 1-2. The Server Project’s Program Class

// Configure the HTTP request pipeline.


if (app.Environment.IsDevelopment())
{
  app.UseDeveloperExceptionPage();
  app.UseWebAssemblyDebugging();
}
else
{
  app.UseExceptionHandler("/Error");
  app.UseHsts();
}

app.UseHttpsRedirection();

app.UseBlazorFrameworkFiles();
app.UseStaticFiles();

app.UseRouting();

24
Another Random Scribd Document
with Unrelated Content
már nem keltheti fel: csak áltatjátok magatokat és felültetitek
egymást. A lényegben van itt a veszedelem, és nem a tréfás
garnirungban. Képtelen vagyok megérteni a Lisnevszkátokat. Nem
abban látja a nagyobb bajt, hogy a szegény emberek egy szobában
alusznak a gyermekeikkel, hanem abban, hogy a szegény emberek
nem magyarázzák el a gyermekeiknek – idejekorán és alaposan – a
mit az egyetlen szobában gyanítaniok kell, de a mit még nem
tudnak. Mintha mégis jobb volna emezeknek, ha nem kellene
gyanítaniok semmit és nem volna szükségük szüleik sürgős
magyarázatára.
– Hiszen akkor te nem vagy feminista!
– De az volnék, vagy mi, és szeretném, ha propagandát tudnék
csinálni annak a hitemnek, hogy a nőknek, igenis, minden téren
joguk van a munkához. De éppen azért szeretném, ha egyszer már
abbahagynátok a felvilágosítás kérdésének a bolygatását. Mért nem
álltok már egyszer valami egyébbel a nyilvánosság elé? Azt hiszem,
tanultunk már annyit, hogy érdeklődhetünk más valami iránt is. Mért
adtok fegyvert az ellenségeink kezébe? Vagy talán ezeknek van
igazuk, és a legkényesebb téma folytonos feszegetése: a gyermekek
felvilágosítása volna az az egyetlen női munka, a mely benneteket
igazán és komolyan érdekel?!…
RÉGI ISMERŐSÖK.

A gyorsvonat egyik elsőosztályu fülkéjében két utas foglalt


helyet: egy magánosan utazó, még egészen csinos hölgy és egy sok
podgyászszal megáldott, már kopaszodni kezdő úriember. A hölgy
harmincz-harminczkét évesnek látszott, tehát nem lehetett több
harmincznyolcznál; az öltözködése csorbátlan izlésre, és ha nem is
éppen vagyonra, mindenesetre elsőosztályu jómódra vallott. A
sokpodgyászos úr ötven esztendős lehetett; de bátran hazudhatta
volna magát negyvenötnek is. Meglátszott rajta, hogy mindig
gondosan ápolta a személyét, és hogy eléggé jól gazdálkodott az
életerejével. Már aligha szokott versenyezni a huszárhadnagyokkal,
de azokon a fürdőhelyeken, a hol sokkal több az asszony, mint a
férfi, a számottevő udvarlók közé sorozták volna.
Alig hogy elhelyezkedtek, a póttartalékos gavallér nyomban
beletemetkezett először is a hölgy, aztán a hölgy minden
hozzátartozóságának részletes méltatásába. A keleten élő emberek
tökéletesen nyilt tekintetével nézelődött, de azért érdeklődése nem
volt sértően tolakodó; a szemejárásából is ki lehetett olvasni, hogy
világotjárt és élnitudó ember.
Miután szakértő pillantása gyorsan megbecsülte a hölgy holmiját,
figyelme visszatért érdeklődése főtárgyához, a holmik gazdájához, a
ki vele szemben, a fülke másik sarkában huzódott meg.
– Meleg fényü szem, szép száj – szólt magában – gyönyörü nyak
és váll, ritka jó derék, se kurta, se hosszu, általában szinte junói
alak, mely azonban nem sír a soványító kúra után, arányosan kicsiny
és formás láb, kitünő suszter, egészen az én zsánerem!
Aztán egy pár pillanatig rajta volt, hogy kövesse Ariosto tanácsát
és abból, a mit láthatott, kitalálja mindazt, a mit már nem kötöttek
az orrára.
Ennek a talány-fejtegetésnek egész tudománya van, a melynek
Brantôme mester, a hindu bölcsek, és egy kitünő arab író, az »Illatos
kert« szerzője, a legtudósabb tanárai. E kitünő vezetők nyomán a
póttartalékos gavallér elvégezte, hogy minél többet tud kitalálni,
maga a találgatás annál kevésbbé elégítheti ki.
Budapesttől Kőbányáig azt tanulmányozta, hogy a
megismerkedés és a bizalmasabb közeledés »lehetséges-e?«
Kőbányától Rákosig meggyőződött róla, hogy érdeklődése a
legkevésbbé se alkalmatlan a szép asszonynak, sőt, hogy
érdeklődése pár percz óta viszonzásra talál. Rákoson túl a
beszélgetésnek már csak valami jobb ürügyét keresgélte – mert nem
kezdheti akármilyen ostobasággal, mint egy fiatalember… az
öregedésnek is megvan a maga szemérme – a mikor egyszerre csak
a hölgy váratlanul megszólalt:
– Ugyan, mondja kérem, nem Szombathy Pál urhoz van
szerencsém?
A gavallér az első pillanatban elámult, aztán majd kinézte a
szemét. Szerette volna megsarkantyuzni az emlékezetét, de hiába
bámészkodott útitársára, ő, a ki olyan sokat tudott kitalálni, azt már
nem találta ki, hogy ki lehet ez a hölgy, a ki őt ismeri és nevén
szólítja.
– Nem ismer meg?! – csodálkozott a hölgy. És jóizüen nevetett.
– Nagyságos asszonyom – hebegte a gavallér – az igazat
megvallva… pedig nagyságos asszonyom az első pillanattól fogva
olyan ismerősnek tünt fel előttem!… de már nagyon régóta nem
voltam Magyarországon… nagyságos asszonyom akkor még nyolcz-
tiz éves leányka lehetett…
– Ez persze hizelgés akar lenni – szólt a hölgy, a kit a gavallér
elképpedése láthatóan mulattatott. – Sohase erőlködjék! Ez a rossz
emlékezet egy cseppet se hizelgő rám nézve. Igaz ugyan, hogy rég
nem láttuk egymást, és azóta nagyon megváltozhattam… De
érdekes, csakugyan nem ismer meg!
Majdnem kaczagott.
A nevetés hangja végre régesrég eltemetett emlékeket
bizseregtetett meg a gavallérban.
– Ida! – kiáltott fel. Majd más formában ismételte ezt a nevet,
halkabb és gyöngédebb hangon:
– Dusika!
És mintha egy parányi megindulás is rezgett volna a szavában.
– Ilyenek maguk férfiak! – szólt a junói alaku Dusika. – Igaz,
hogy majdnem húsz év múlt el azóta!… de akkor az élete
boldogságának nevezett!… és tessék, most egy negyedóráig néz…
talán órákig nézhetett volna, s eszébe se jut, hogy valaha ismert…
nem ismer meg még akkor se, a mikor megszólítom!… Azt, a ki egy
évig, nem… tizenhét hónapig a felesége volt! Hát olyan nagyon
megváltoztam?! Annyira megvénültem?!
– Jól tudja, hogy ez nem igaz. Csak más lett. Viruló szép
asszony… Mig akkor… akkor… sápadt, vézna, beteges, törékeny kis
síróbaba volt… Ó, nagyon bájos kis penészvirág volt, de csak egy kis
penészvirág!… Maga már nem emlékszik, hogy milyen volt akkor…
de én emlékszem, hogy milyen volt az a csúnya baba, a ki sohase
akart tudni rólam… és a ki, miután vagy három esztendeig hiába
törtem magamat egy gyöngédebb pillantásáért, végre is a faképnél
hagyott! Emlékszik még! Másfél esztendeig nem akart a feleségem
lenni; aztán, mikor a szülei mégis csak rábeszélték, hogy a
feleségem legyen, még tizenöt hónapig imádtatta magát hiába!…
pedig eléggé dédelgettem!
– Talán éppen az volt a hiba, hogy tulságosan dédelgetett. De
hagyja ezt! Úgyis eléggé megbántam, hogy nem maradtam meg
maga mellett!…
– Hogyan? Hát…
– Ó, nem is képzeli, mennyi szemrehányást tettem magamnak
azért, hogy akkor olyan ostoba voltam!…
– No lássa!
– De ne beszéljünk rólam. Beszéljünk magáról. Az én kedves
jóbarátomról. Arról az egyetlen férfiról, a ki mindig csak jó volt
hozzám. Mondja, hol járt, mit csinált azóta? Úgy eltünt akkor, mintha
a föld nyelte volna el. Hírt se hallatott magáról; azt se tudtuk, él-e
még, vagy meghalt.
– Sokat törődött velem!
– Ne higyje, hogy valaha elfelejtettem a hozzám való jóságát! És
nemsokára nagyon is sokat gondoltam magára. De ne beszéljünk
rólam. Mondja el, mit csinált az alatt a roppant hosszú idő alatt? Hol
élt? Van-e családja? Vannak-e kis babái, vagy már nagyocska
babái?… mert már nagy gyermekei lehetnek.
– Nincsenek. Nem házasodtam meg másodszor.
– Kár. Nagy hiba, ha az olyan ember, mint maga, nem szaporítja
el a fajtáját. Nagyon kellenének az ilyenfajta emberek, egy kicsit
ellensúlyozni a többieket. Hát beszélje el, hová ment, a mikor
egyszerre csak eltünt? Merre járt és mivel foglalkozott azóta?
Beszéljen el mindent. Nagyon érdekel, milyen volt az életesora.
– Az én történetem nagyon rövid. Mikor maga, egy nem éppen
szép napon, megvallotta nekem, hogy sohase szeretett, hogy nem
tud szeretni, hogy csak a szülei kényszerítették hozzám, hogy mást
szeretett, hogy a szerelmese nélkül tovább nem élhet, hogy el akar
tőlem válni, hogy ahhoz akar férjhez menni, a kit szeret, hogy ez
mindig el akarta venni, és most már el is veheti, – nagyon
elszégyeltem és elbusultam magamat. Nem akartam itthon maradni,
a hol minden magára és a házassági balesetemre emlékeztetett.
Éppen ezekben a szomorú napokban kaptam ajánlatot egy külföldi
czégtől; hirtelen elhatároztam magamat és kimentem Kis-Ázsiába
vasutat építeni. Ez eltartott egy pár esztendeig. A pusztaságban, a
hol dolgoztam, nem volt alkalmam pénzt költeni; mikor befejeztük a
munkát, nagyobb összegü keresmény jutott a kezembe. Ezzel a
pénzzel megszállott a vagyonszerzés láza. Meg akartam gazdagodni,
és felcsaptam kereskedőnek. Tönkre mentem és megint elülről
kezdtem. Aztán da capo. Négyszer vágódtam földhöz és négyszer
keltem fel ujra; végül mégis csak megszereztem azt a vagyont, a
melyre áhítoztam. Most aztán hazajöttem pihenni. Mindössze ennyi
történt velem.
– Akkor hát gratulálhatok magamnak. Mert nekem köszönheti, ha
meggazdagodott.
– Bocsánat, magam is igyekeztem.
– De ha én akkor véletlenül úgy gondolkozom, hogy a legjobb
lesz belenyugodnom a sorsomba, hogy a nő tűrésre, megadásra,
szenvedésre született – a mi engemet illet, most már nagyon
sajnálom, hogy nem így gondolkoztam – akkor most talán volna
vagy nyolcz gyermekünk, és talán nagyon szegények volnánk.
– Vagy talán volna tizenkét gyermekünk és nem volnánk
szegények. Mit tudjuk azt, hogy mi volna?! De hát beszéljünk most
már magáról. Van sok kis babája? Már nagyocskák lehetnek.
– Nincsenek gyermekeim.
– Ugyan! És Bodor Béla úr, szerencsés vetélytársam?
– Az igazat megvallva, nem tudom, hogy hol van.
– Ne mondja! Csak nem vált el attól is?
– De bizony elváltam.
– Attól, a kit szeretett? Hát ebbe a házasságába se vitt egy kis
türelmességet? Akkor már mégis csak magában volt a hiba.
– Mit akar?! Ha egy erőltetett házasság nem sikerül, az csak
tűrhetetlen; fel kell bontani és pont. De ha egy szerelmi házasság
nem sikerül, az maga a pokol. Mit mondjak magának?! Lássa,
magára mindig hálával és barátsággal gondoltam; ezt az embert
pedig úgy meggyűlöltem, mint még soha senkit. De hagyjuk ezt!
Szomorú történet ez, a mely magát csak untatná és engem még ma
is idegessé tesz. Rágondolni se szeretek.
– És régi történet?
– De milyen régi! Három évig se éltünk együtt.
– Szóval, ha tovább epedek, mint a hű szerelmesek, és egy kicsit
vártam volna…
– Ne is mondja, mert ríva fakadok!
– Visszajött volna hozzám?
– Akár mezitláb, ha úgy kivánja! És meglehet, hogy most a
legboldogabban élnénk.
– Ki tudja?! Hátha mégis csak jobb így?! Higyje el nekem, hogy a
volná-t sohase lehet kiszámítani. Se előbb, se utóbb.
– Akármilyen udvariatlan, sőt szivtelen, én bizonyosan tudom,
hogy nekem jobb volna.
– Miért? Mi történt azután?
– Képzelje, harmadszor is férjhez mentem!
– Nagyszerü! Úgy látszik, ha hamar elveszíti a türelmét, a
bátorságát nem veszíti el olyan hamar, mint én. De, remélem, a
harmadik férjétől már nem vált el?
– Nem, még rosszabb az eset. Harmadszor, okulva a szerelmi
regényem tanulságain, már komoly, rendes embert kerestem; nem
olyan könnyelmü betyárt, mint Bodor, hanem olyanformát, mint
maga. No, és megint megjártam. A harmadik férjem nem volt rossz
ember, de neki is jobb lett volna, szegénynek, ha agglegény marad.
Eleinte csak a dolgának élt, később csak a betegségének. Mogorva,
már nem fiatal, beteges, zsémbes ember volt. Rajta voltam, hogy
mégis megbecsüljem, mert már megtört a sors. De istenem, olyan
kevéssé voltam a felesége! No, és aztán meghalt.
– Úgy, hogy most egészen özvegy, miután előbb is özvegy volt
egy kicsit.
– Nem. Ne nevessen ki: negyedszer is férjhez mentem.
– De édes Dusika, hiszen maga egy női Kékszakál!
– Mit tehetek róla, hogy igazi asszony akartam lenni, és mert
becsületes teremtés vagyok, sokáig nem akartam szakítani a
hagyományos formákkal, az erkölcs, a tisztesség, az illendőség, vagy
mit mondjak, minek a követelményeivel?! Akkor még nem tudtam, a
mit azóta megtanultam, hogy a házasság a nőt okvetetlenül
áldozattá teszi, és hogy ez a formaság a legnagyobb gazság mind a
közül a sok dolog közül, a mit a férfiönzés és a számító emberi
gonoszság az asszonyok rovására valaha kitalált.
– Szent isten, csak nem vált el a negyedik férjétől is? Ámbár,
minthogy az özvegysége némi változatosságot vitt a sorsába, most
már minden nagyobb feltünés nélkül újra kezdhette az elválást.
– Bár elváltam volna tőle!
– Ez idő szerint tehát ismét férjes asszony.
– Most már igazán magam se tudom, mi vagyok. Se kint, se
bent.
– A negyedik házassága is boldogtalan volt?
– Ez volt a legboldogtalanabb valamennyi közül. Talán azért, mert
ebben a házasságban, okulva a harmadik házasságom tanulságain,
éppen csak a férjet kerestem. Nem is mondhatnám, hogy a
gazembernek nem voltak szeretetreméltó tulajdonságai. De mégis ez
a választásom volt a legrosszabb. Képzelje! A gazember elharácsolta,
a mit a vagyonomból, lopva, pénzzé tehetett, aztán sikkasztott, csalt,
lopott, váltót hamisított, s egy pár nappal előbb, hogy mindez
kiderült, elszökött Amerikába.
– Dusika, bocsásson meg, de a házassági szerencsétlenségeknek
ez a ritka sorozata már nem annyira szomoru, mint inkább
mulatságos.
– Hiszen láthatja, hogy most már én is nevetek rajta! De várjon
csak! Még nem vagyok szomoru történetemnek a végén, és ha
érdekli a sorsom…
– Dusika, elő ne álljon egy ötödik házassággal, mert
elszörnyedek!
– Nem, ez egyszer már éppen torkig voltam a házassággal. Azért,
bár jogczimem bőven lett volna hozzá, nem indítottam meg a
válópert, és a törvény előtt még ma is felesége vagyok ennek a
bitangnak, a kiről azt se tudom, hogy hol van…
– Teringettét, három férje volt, a kikről nem tudta, hogy hol
vannak!…
– Csak nevessen! Higyje el, ez nem csak éppen mulatságos. Egy
kicsit bosszantó is, különösen az olyan asszonyra nézve, a ki
becsületes teremtés, és a ki még elég fiatal ahhoz, hogy…
– Igazi asszony maradjon! De hát, Dusika, akkor én éppen a
legjobbkor érkeztem haza Kis-Ázsiából! Ha maga megbánta, hogy
elhagyott, ha már régebben is visszajött volna hozzám, ha mindig
barátsággal gondolt rám… ez engem a legédesebb reménységgel
tölt el… és ha csakugyan érzi, hogy sok-sok szeretettel maradt
adósom…
– Nem várta meg a végét. Ha már mindent elmondtam, el kell
mondanom azt is, hogy én most szabad házasságban élek. Egy
főhadnagygyal.
– Tyű, be hamar leforrázza a reménységeimet!… De hát a szabad
házasságban, ha nem csalódom, a legnevezetesebb az, hogy még
csak nem is házasság… És ha csakugyan én vagyok az egyetlen férfi,
a kit valaha becsült, végre is… maga szabad, mint a madár!…
– A szabad házasság éppen olyan rabszolgaság, mint a másik, a
régi divatu. Az ősi formáju házasságnak minden rossz tulajdonsága
megvan benne, azzal a különbséggel, hogy egygyel több rossz
tulajdonsága van, mint amannak, mert azt az asszonyt, a ki a szokás
és az előitéletek ellenére is vállalja ezt a kötést, az emberek többé
nem tisztelik… itt a férfi még a köztiszteletet is elszedi az asszonytól.
És a helyett, hogy ezért kárpótlást igyekeznék nyujtani, ő maga az
első, a ki az asszonyt nem tiszteli többé. Mondhatom, az igazi
férjeim még csak megbecsültek valamennyire, ha másért nem, azért,
mert a világ előtt a tulajdon nevük viselőjét süvegelték bennem: mig
a szabad férjem!… ez rovásomra írja azt az áldozatot, a melyet neki
hoztam… és annyival többet követel tőlem, mert helyre kell hoznom
azt is, a mit a mások erkölcsi felfogása ellen vétek. Persze, ezt még
nem tudtam akkor, a mikor a házasságnak ebben az uj formájában a
jövő zenéjét üdvözöltem; de azóta megtanultam, hogy találjanak ki
akármit, a szerelmi összeköttetésben, legyen ez akár holtigtartó,
akár hosszabb vagy rövidebb időre tervezett frigy, a nő mindig
áldozata lesz a férfinak… mindaddig, mig az egész világon az nem
lesz a szokás, hogy a férfi és a nő csak egyszer találkoznak s aztán
sohase látják többé egymást.
– Hogyan, Dusika, maga úgy akarná megjavítani a világot, hogy
a szerelmi összeköttetésnek sohase legyen másnapja? De hátha
megkedvelték egymást és örülnének az uj találkozásnak?!
– Én sehogy se akarom megjavítani a világot. A maguk dolga
valami okosabbat kitalálni. Én csak azt tudom, hogy így nincs jól.
Sehogy sincs jól.
– De lássa, Dusika, a mig senki se talál ki valami okosabbat, egy
kis rendnek, legalább egy kis nyilvántartásnak mégis csak kell lennie!
Ne felejtse el, hogy a szerelmi összeköttetésből sokszor gyermek is
származik, és a mig ebben a társadalmi rendben élünk, a mig a
gyermekről a szülőknek kell gondoskodniok, mert az állam, a
társadalom nem gondoskodik, vagy olyan kevéssé gondoskodik,
hogy ez szóra se érdemes…
– Én nem mondom, hogy ne legyen semmiféle nyilvántartás, de
gondoskodni kellene arról is, hogy a nő ne legyen a férfi rabszolgája.
Igazivá kellene tenni a nő szabadságát…
– Például hogyan képzeli ezt?
– Úgy, hogy a szerelmi összeköttetés és az elválás olyan szabad
legyen, mint a költözködés. Például mindenkinek joga volna
bejelentő vagy kijelentő czédulát küldeni egy hivatalba…
– Jaj, Dusika, ahhoz éppen ezernyolczszázmillió tisztviselő
kellene, hogy ezt a temérdek bejelentő és kijelentő czédulát mind
nyilvántarthassa! Mindenki ennek a hivatalnak a tisztviselője volna,
és még így se győznék a munkát! Hanem, tudja mit? Kezdjük el a
reformot, s küldje el a kijelentő czédulát a főhadnagyának!
– Nem tehetem, mert most még szeret, már a maga módja
szerint, és félek, hogy agyonver.
– Az már baj. Erről ugyan nem tehet a társadalom, csak a
főhadnagy; azért mégis baj. Hanem lássuk csak! Ha igazán olyan
kedves marad, mint a milyen kedves az előbb volt, a mikor azt
mondta, hogy… Mondja, igazán jóérzéssel van irántam? Igazán én
vagyok az egyetlen ember, a ki meg tudta magát becsülni, és a kit az
ex-férjei közül még a leginkább szível? Igazán belátja, hogy rosszul
cselekedett, a mikor semmire se méltatta az én makacs
ragaszkodásomat?
– Igazán. A legkomolyabban mondtam. Ha akarja, meg is
esküszöm rá.
– Csak ne esküdjék! Egyszer már megesküdött és az nem
sikerült. Mondja csak így egyszerüen; elhiszem, mert szeretem
elhinni. Akkor hát van egy mód, hogy kárpótolja azt, a kivel szemben
régente nem volt igazságos. Az ősi mód.
– Mit akar ezzel mondani?
– A szabad házasságnak van egy jó tulajdonsága is: az, hogy,
mint minden házasságot, ezt is meg lehet törni. Ha csakugyan
megbánta, hogy nem maradt meg mellettem: szálljunk ki az első
állomáson, a hol ez a vonat megáll, és – a meddig mást nem gondol
– felejtsük el azt a sok esztendőt, a mig nem láttuk egymást.
Pokolba a főhadnagygyal. Végre is én már régebben kiérdemeltem,
hogy jóságos legyen hozzám, mint ez az ember, a ki a többieknél is
kevésbbé tudja magát megbecsülni!
– A főhadnagy megérdemelné. És… és…
– Köszönöm az »és«-t…
– De nem lehet.
– Miért nem?
– Mert a főhadnagy vár a vasútnál.
– A szabad házasságnak van egy másik jótulajdonsága is. Nagy
enyhítője a hazugság.
– Agyonverne.
– Tehát másodszor sincs szerencsém. De én negyedszer se
szoktam megadni magamat a sorsnak… Mit nevet?
– Illetlen dolog, de magának megmondom. Hiszen régente elég
jó viszonyban voltunk. Hát éppen ez az… Arra gondoltam, milyen
furcsa volna, ha véletlenül engednék a maga csábítgatásának, ha
véletlenül csakugyan megszöknénk a vonatról, és az után, hogy
négyszer voltam férjnél, legelőször is magánál, sőt ötödször is… már
akár számítja ezt is, akár nem számítja… most, a mikor a negyedik
asszonyi név után már megint a leánynevemet viselem… Ej, mégse
mondom!
– Milyen furcsa volna, ugy-e, ha az után, hogy négy vagy öt
házassága… már akár számítjuk az ötödiket, akár nem számítjuk…
szóval, négy-öt házassága gyermektelen maradt, a jövő esztendőben
egyszerre csak egy kis szabad fiú állítana be a világra!
A SÖTÉT UDVAR.

Az előkelő negyed közepén százesztendős, rozoga, ütött-kopott,


földszintes házikó éktelenkedik. Mintha szégyenkeznék az úri paloták
és a hatalmas bérházak között. Pedig daczol velük. Csak azért se
akar elpusztulni a közelükből. Csak azért se akar átalakulni divatos
külsejü, hatalmas, uj épületté. Megmarad a régi dísztelenségében,
hogy csúffá tegye amazokat, hogy folytonosan bosszanthassa a
paloták urait.
Tulajdonosa furcsa gondolkozásu, és furcsa életet élő agglegény,
a ki már régesrég a külföldön tartózkodik, a honnan soha, látogatóba
se jön haza. Valamikor régen, senki se emlékszik már rá, micsoda
csekélység miatt, összezördült a főváros tanácsával. A
viszálykodásból per lett; a pert elvesztette. Azóta látni se akarja a
szülővárosát. Csak a pereskedést folytatja ellene. Az első pert vagy
háromszor ujitotta meg, minden elképzelhető czimen. Ha a biróság
elutasította, feljebbezett; és ez az ősrégi bonyodalmas »anya-per«
még ma is folyik; szívósabb életü minden pernél, a melyet a
budapesti biróságok ismernek. Szívósabb életü és termékenyebb is.
Mert az anya-per sok kis apró pert fiadzott, a melyek nőnek, nőnek,
és szépen erősödnek. A furcsa úr ingatlanai révén, minduntalan
beleköthet régi haragosába, a magyar fővárosba, és a kinálkozó
alkalmat soha se mulasztja el. Követeléseket támaszt; megtagadja
háziúri kötelességeinek a teljesítését és bár a pörök sorsát előre
tudja, csak pörösködik tovább. Talán ez a per az egyetlen
szenvedélye.
A házait pedig semmi áron nem akarja eladni. Ha eladná az
ingatlanait, bedugulna a forrás, a mely a pörösködő szenvedélyét
táplálja. De lebontatni se akarja ezeket a viskókat, hogy palotákat
vagy bérkaszárnyákat építtetne a helyükön. Csak hadd bosszantsák a
várost és a város lakóit. Viskói a város legbelső részén alkotnak itt is,
amott is, foltot. Mindegyiknek roppant telke van; tágas udvara és
messze elhúzódó kertje. Időközben ezeknek a telkeknek az értéke a
százszorosára emelkedett annak az árnak, a melyen az ingatlanait
hajdan összevásárolta. Ha a viskókat lebontatná és bérházakat
építtetne a telkein, uj kincsesbányákat szerezne. Csak azért se.
Ezt is, azt is megpróbálták, hogyan lehetne rábirni arra, hogy
megválthassák tőle a tulajdonjogot, akármilyen árt szab. A kisajátítás
czimén egyik-másik kalyibájának a tulajdonjogából ki is forgatták. De
valamennyi alkalommal minden követ megmozgatott, hogy a
kisajátítás ne történhessék meg. És a legtöbbször ki is módolta, hogy
a kisajátítás elmaradt.
Rengeteg pénzt költött el erre a czélra. Rengeteg pénzt veszít a
konok daczával. De viskóinak nagy része ma is megőrizte régesrégi
éktelenségét, és ő csak ezt akarja.
Teheti, hogy fejedelmi árt fizet a rosszakaratu szeszélyéért. A
milliói megszámlálhatatlanok. Egypár millióval több, vagy kevesebb,
a furcsa életü külföldi úrnak mindegy. Jut is, marad is. Telkeinek az
értéke például nő magától.
És ha így nem juthat hozzá a jómóduak forintjaihoz, a szegények
garasait mégis csak megkapja. Ügyvédje a rozzant épületek apró
lakásait ágrólszakadt szegény ördögöknek adja ki, egy kevés piszkos
bankóért. S a kis piszkos bankók sietnek az apjukhoz. Kis halak, jó
halak.
Az előkelő utczát beszennyező földszintes házban is csupa pária
lakik. Nyolcz lakás van benne, nem számítva a házmesterét, a ki a
lakók nagy részének bizalmas jóbarátja. Ha a szegény ember
véletlenül rábukkant e lakások valamelyikére, nem szivesen költözik
ki belőle, a mig egyáltalán meg tudja fizetni a házbért. A szobák
szűkek, de a ház levegős. A tágas udvar – milyen szerencse a
gyermekeknek! A kertbe, ha az ember jóbarátságot tart a
házmesterrel, le szabad menni; és ha nem szabad: a kert felől
balzsamos szellő árad, s már ez is valami.
Aztán este, későn, a mikor a tágas udvar teljesen elsötétedik,
künn ülni a tornáczon, csupa mulatság.
Az udvarban már mély csend ül, és ebben a mély csendben olyan
jól esik elnézni a kert fáinak szemnyugtató feketeségét… és olyan
szórakoztató, erről a feketeségről jobbra, vagy balra pillantva,
elnézni azokat a fénycsikokat, a melyek a két szomszédos
bérpalotából sugárzanak ki, eltünődve azon, micsoda élete lehet
azoknak, a kik itt laknak, az egyik vagy másik palota
oldalszárnyában, a kivilágított ablakok mögött, az első, és a második
emeleten, a honnan minduntalan zongoraszó és víg lárma
hallatszik?!… Milyen kár, hogy nem lehet belátni a kivilágított ablakok
mögé!
Este tiz órától tizenegyig az utazó felesége ki is élvezi ezt a
csöndes mulatságot.
Ráér. Neki nincs semmi dolga. Cselédet tart. Ő a ház legelőkelőbb
lakója.
Nagyon ráér, mert az utazó csak ritkán van otthon.
Néha egy másik asszony csatlakozik hozzá. A szedőné. Annak az
ura csak négy óra után jön haza. Ha ugyan már akkor hazajön. Mert
szeret politizálni, és sokszor megesik, hogy munka után még betér
valahová az elvtársakkal tanácskozni, néha talán poharazni is.
Akárhányszor csak a reggel veti haza.
Tiz órakor a szedőné már régen letektette az apró gyerekeit. És
ha nem tartja vissza valami házi munka, a mi már a körmére égett,
vagy ha nem tulságosan fáradt és álmos, kimegy a tornáczra és leül
a szomszédasszony mellé.
Néha éjfélig is el tudnak beszélgetni, így, kettesben…
A szedőné majdnem annyira érdekli az utazó feleségét, mint azok
az ismeretlenek, a kik a kivilágított ablakok mögött laknak. Nem győz
eleget csodálkozni rajta; nem tudja megérteni. Hiszen ha ő ilyen
szép volna!…
Az alakja ugyan olyan törékenynek látszik, mint a milyen egy
sápkóros úri kisasszonyé lehet. Nyilván a sok gyerek ártott meg neki.
Aztán nem valami nagy bőségben élhetnek a sok kicsi gyermekükkel.
Minden esztendőben gyerek!… Hallatlan! És az apró lények úgy
ődöngenek körülötte, mint a kis kacsák egy nagyobb kacsa körül.
Négy gyerek egy fiatal asszonynak, egy gyerekasszonynak, a ki csak
egy-két esztendővel van túl a húszon, a ki még maga is olyan
gyerekes, hogy bátran párisi babával játszhatnék!… elgondolni is
borzasztó!
De az arcza! Az a tejfehér, minden finomságnál finomabb arczbőr,
meg az a bámulatos haj! A szépen ívelt, sűrű, koromfekete
szemöldök, meg a nagyon is piros, nagyon is formás, kissé húsos
száj elárulják, hogy nem kereszténynek született, – mert most már
az, – de ilyenek lehettek a bibliai leányok. A szeme olyan, mint a
virág; mint azok a csodálatosan kék virágok, a melyek csak a
délszaki földeken teremnek, s a melyek kékebbek, melegebben
kékek, mint a mieink; olyan, mint a virág, mert a szine a virágok
szinének finomságára és lágyságára emlékeztet; annyira puha szin,
hogy a világítás szerint más és más, de ha hosszasan nézed, úgy
tünik fel előtted, hogy a másik pillanatban már nem olyan, mint az
imént, mintha belülről más-más fényt és szint kapna a lélektől, a mi
minden hő- és fénysugárzó közül a legtökéletesebb és a
legbőségesebb. És ezt az érzékien szép szemet, a melyet nemcsak a
kifejezés, a mosoly, a lélek tesz széppé, hanem szép már alkatánál
fogva is, éjfeketeségü és éjsűrűségü, hosszú szempilla árnyékolja be,
szebb ernyő, mint a világ összes csipkeernyői.
Hát nem kár, hogy ez a virág egy embernek, egy durva, kiabáló
embernek virágozzék, és hamarosan elvirágozzék a virágoknak kellő
éltető talaj, levegő és meleg hijján a nyomorúságtól?!…
***
– Már én ezzel az emberrel nem tudnék meglenni – szól az utazó
felesége. – Azon kezdem, hogy a szegény embernek nem volna
szabad megházasodnia. Az én uram is szegény ember, de nem
munkás, hanem vállalkozó, és a milyen igyekvő, bizonyos, hogy
nemsokára vagyonos ember lesz. Ha ez nem volna kétszer kettő, egy
perczig se maradnék meg mellette. De, hogy egy ember, a ki éppen
csak a betevő falatot tudja megkeresni, a ki világéletében mindig
szegény ember lesz, még ráadásul rosszul is bánjék a feleségével!…
– De ha mondom, hogy nem bánik velem rosszul!… – vág közbe
a szedőné.
– Nekem beszélhet, lelkem! Hallok én mindent; és ha nem volna
elég jó fülem, az ura elég nagyokat kiált. Ma reggel is… vagy csak
álmodtam?!… Hét óra után jött haza, és alig hogy hazaért, már úgy
bömbölt, mint egy Behemóth. Megint megverte, mi?
– Soha se ver meg.
– Ej, a multkor maga is elismerte…
– Igen, az első esztendőben. De akkor meg is érdemeltem, mert
még nagyon ostoba voltam.
– És ma?… Mi volt ma?… Mert valami csak történt?…
A szedőné nem akart vallani.
– Az én uram jó ember – felelt. – Arról, hogy szegények vagyunk,
arról nem tehetünk.
– Az ember lehet szegény, de azért még nem kell részegeskedni.
Ha az én uram, csak egyszer is, részegen jönne haza, mindjárt itt
hagynám. Pedig úgy bánik velem, mint a hímes tojással.
– Az én uram se részegeskedik. Hogy egy-egy pohár bort
megiszik?! Uram isten, férfiember a bort megissza.
– De nem vetődik haza fényes nappal, és nem harsog, a mikor
aludnia kellene.
– Nem járhat haza este, a mikor hajnalig dolgoznia kell. Aztán a
férfiember nem lehet el minden társaság nélkül.
– Igen, össze kell bujni az elvtársakkal; nagyokat kell inni és még
nagyobbakat ordítani. Ilyenkor aztán se isten, se király, se haza, se
semmi; a római pápa se parancsol neki. De bezzeg, ha a
nagyméltóságu munkás-tanács egyszerre csak ráparancsolja a
sztrájkot! Akkor a kiabáló elvtárs mindjárt ilyen kicsi lesz, ni! A mikor
reszketve gondol a holnapra, de azért még se mer még csak
megmukkanni se, mert nem zúdíthatja magára a hatalmas elvtárs
urak haragját. Akkor aztán szűköl, és olyan csendesen beszél, hogy
nem lehet megérteni, a mit mond. Ismerem a férjeurát, lelkem.
Láttam, most harmadéve, hogy milyen jámbor ember tud lenni. De
ha nincs semmi baj, és megkeresi azt az egypár garast, bezzeg
kiereszti a hangját, és ugyancsak hatalmaskodik a feleségével! A
munkásvezető urakkal tetszenék neki hatalmaskodni, ne egy gyönge
asszonynyal, a ki olyan vékonyka, hogy be lehetne fűzni a tűbe!…
No, mondja el már, mi történt ma reggel?!… Hiszen régen ismerjük
már egymást, nem vagyunk idegenek! És én még a legféltettebb
titkaimat is elmondom magának.
A szedőné emlékezett még arra az időre, a mikor olyan szűkön
voltak, és a mikor az utazó felesége apró kölcsönöket adogatott neki,
de hogy ezt ne ingyen tegye, elmondotta a bámuló
szomszédasszonykának minden boldog szerelmét, összes
kedveseinek a történetét, a bölcsőtől a sírig.
Ez az emlékezés nem tette közlékenyebbé. Sehogysem akarta
kielégíteni a szomszédasszony kiváncsiságát. Látszott rajta, hogy
szégyelli a dolgot.
Megint kitérően felelt:
– Bizony isten, egy ujjal se bántott.
De az utazó felesége nem hagyott neki békét. Addig faggatta, a
mig végre a szedőné kivallotta a ma reggeli dolgot.
– Lássa, most is neki volt igaza! Olyan ostobaságot követtem el,
hogy csak egy kis hijja volt, és magamra gyujthattam volna a házat.
De nem tehettem másképpen.
Az utazó felesége égett a kiváncsiságtól. (Egészen másféle
történetet várt.)
– De hát mi történt, hogyan történt?! Mondja el már!
– Hát… hiszen mondottam is a szomszédasszonynak a multkor…
tegnap volt az édesanyám halálának az évfordulója. És tudni kell,
hogy minálunk a vallás azt kivánja, hogy a halál évfordulóján világot
gyujtsunk a kedveseink emlékezetére. Az ember egy mécsest éget
huszonnégy óráig; ezt már így kivánja a vallás. De talán azt is
elmondottam már, hogy a szegény uramnak a vallás olyan, mint a
bikának a vörös posztó. Nagyon jó ember különben, de ez az egy
hibája megvan. Hát nem akartam, hogy a mikor majd haza jön,
meglássa a mécsest. Azért a mikor lefeküdtem, eldugtam a mécsest
a szekrény tetejére, a szekrény párkánya mögé. Reggel aztán
hazajött az uram, nem is volt valami jó kedvében, és azt mondja,
hogy nagy égésszagot érez. Akkor ébredtem föl az álmomból,
hamarjában nem találtam ki, hogy mi az… azt hittem, hogy ő dobott
el gyufát vagy szivarvéget… és a mig tanakodunk, a mig keresgéljük,
hogy mi éghet, egyszerre csak lánggal kezd égni a szekrény
párkánya. Az történt, hogy… a szekrény párkánya, bizony már el van
töredezve… és a töredezett fának egy kiálló darabja nagyon közel
talált érni a mécseshez. Előbb, a mig aludtam, csak pörkölődött, de
aztán még közelebb juthatott a lánghoz, mert mialatt javában
vitatkoztunk, hogy én nem érzek semmit, a vékony, kiálló fadarabka
tüzet fogott, és ez a tűz, a mint növekedett, végre fölgyujtotta az
egész párkányt. Bizony, szerencse, hogy ez nem akkor történt, a
mialatt aludtam, és hogy az uram mindjárt megérezte az égésszagot.
Mert különben könnyen nagy szerencsétlenség történhetett volna.
Ha például az uram ittasan került volna haza… de ebből is láthatja,
hogy az uram nem szokott inni. Persze, a mikor megtudta, hogy az
én ostobaságom okozta a bajt, egy kicsit pattogott… de egy kis
pattogás még nem a világ… és nincsen vasfazék zörgés nélkül.
Az utazó feleségét meglepte az eset.
– De hiszen, lelkem, én azt hittem, hogy maga most már –
keresztény?!… És azért nem értem, hogy…
– Igen, én most már keresztény vagyok, és meg is tartom a
keresztény vallást, már a mennyire egy asszony megtarthatja. A
nagy böjtöket mind megtartom, pedig az uram nagyon haragszik e
miatt, és neki ilyenkor is húsételt kell adnom. És nincs az a
nagyünnep, hogy titokban el ne menjek a templomba, pedig az
uramtól egyszer nagyon kikaptam e miatt… elmondott akkor
vízfejünek, tyúkeszünek, mindennek, és úgy szidta a papokat, hogy
azt hallani is borzasztó volt. De hát nekem két vallást adott az isten:
az uramét meg a magamét, és azért, hogy az urammal elvállaltam az
ő vallását is, és kijelentettem magamat nálunk, azért a régi
vallásomat sem hagytam el. Megtartom én a magam vallását is:
mindent, a mit a vallás parancsol. De ne mondja meg az uramnak!…
Mert még csak az kellene, hogy ezt megtudja!… el se tudom
gondolni, hogy haragjában mit csinálna. De hát én már mégse
tehetek másképpen. Nem vétek ezzel senkinek… és az nem is lehet
vétek, ha én mind a két vallásomnak eleget teszek, mert így kétszer
engedelmeskedem az istennek, nem igaz?
AZ ERŐS ASSZONY.

I.

Kedves Aranka,
szeretnék röviden felelni a kérdésedre és a kérdésedben foglalt
hallgatag szemrehányásra. Csakhogy ez nem olyan könnyű dolog. Az
eset bonyolultabb, mint képzeled. Hosszasan kell szólnom, hogy
megmagyarázhassam azt a lépést, a mely téged annyira meglepett.
Nem unod? Neked, az egyetlennek a világon, elmondhatok mindent.
Mindent, a mi a fejemben jár.
Ismered-e a Lady Hamilton élettörténetét? Aligha. Kevés asszony
van, a kit ez a példa gondolkozóba ejtett. Én könyv nélkül tudom
ennek a nőnek egész életrajzát, a mint sokan vannak, a kik könyv
nélkül tudják a nagy Napoleon kalandokban gazdag történetét.
Lady Hamilton mint peszra kezdte; aztán szobaleány lett egy
fogadóban. Elcsábították, és az aszfaltra került… azaz, hogy akkor
még nem volt aszfalt, de mindegy… Szóval, London utczáin kóborolt,
és a barátságos mosolygást szórta, a mikor többek között egy
droguistával akadt össze. A droguista lepingáltatta a szép leányt a
plakátjaira, igéretül, hogy: ilyen lesz az, a ki az ő kozmetikus szereit
használja! A plakát feltünt egy divatos festőnek; felkutatta a kép
eredetijét, és Lady Hamilton, a kit akkor még Harte Emmának
hivtak, elszegődött a hires festőhöz modellnek. A műteremben
megismerkedett egy gazdag fiatalemberrel. Ez ráköltötte az egész
vagyonát, s mikor mindenből kifogyott, temérdek adósságot csinált a
szép Emma kedvéért.
Ekkor uj alak jelenik meg a szinen: a fiatalember nagybátyja,
Lord Hamilton, Anglia nápolyi követe, a ki állomáshelyéről egyenesen
azért jött Londonba, hogy rendet csináljon és öcscsét elválaszsza a
sziréntől. Csakhogy a nagykövet még jobban meghabarodik, mint a
tékozló ifju; a haladottabb kornak szép kiváltsága, hogy az
őrültségben nem tart mértéket, mert azt tartja, hogy: ha lud, hát
legyen kövér! Lord Hamilton tehát kifizeti öcscsének az adósságait; a
fiatalember ennek fejében lemond kedveséről a nagybácsi javára; a
nagybácsi habozás nélkül feleségül veszi az egykori peszrát,
szobaleányt, stb… felpakolja, és elviszi Nápolyba.
Itt már rohamosan halad előre Emma. Meghódítja egész Nápolyt,
meghódítja Mária Karolina királynét, és végül meghódítja Nelson
admirálist, a későbbi abukiri győztest és trafalgari hőst. Nelson épp
olyan akarattalan sakkfigurává válik Emmának a kezeben, mint az
öreg nagykövet, s ettől fogva Lady Hamilton olyan befolyással van a
politikára, a milyen befolyással mostanában már a királynők közül is
csak kevesen dicsekedhetnek. Ha nem ismered történelmi
szereplésének a részleteit se, s olvasni akarsz egyetmást arról, hogy
milyen diplomácziai cselszövések teltek ki tőle – ezt megtalálhatod
akármelyik jobb lexikonban.
De szereplésének ez a része már nem tartozik a dologra.
»Előélet«-ének kevésbbé ismert részleteit is csak azért írtam le ilyen
hosszan, hogy megmutassam neked: »Látod, ez az asszony nagyobb
utat tett meg, mint a nagy Napoleon!«
És mi volt a segítségére, hogy megtudta tenni ezt a nagy utat?
Csak a szépsége, meg az esze.
Előttem van az arczképe. Mása annak a képnek, a melyet
Romney festett róla, akkor, a mikor az utczáról felszedte. És előttem
vannak a levelei. Hidd el, becsületszóra, hogy nem volt szebb, és
nem volt eszesebb, mint én.
Nápolyban szépen kiművelődött, de hozzám képest mindig csupa
tudatlanság maradt. Ismerd el, hogy még nem is hallottál olyan
nőről, a ki többet tudna, mint én. Megtanultam mindent, a mit az a
fiatalember tud, a ki kitünően végzi az egyetemet. Mulatságot
találtam száraz jogi ismereteknek a megszerzésében; érdekelt és
folyton foglalkoztat a társadalomtudomány; úgy olvasom a
közgazdasági könyveket, mint te a regényeket. Mintha csak
politikusnak készültem volna, a ki a képviselőséget ambicziója
kielégítésére akarja felhasználni. Mindezt puszta unalomból. Mert
valóságos remeteségben kellett felnőnöm, s mert az eszem mindig
szomjazta a komoly szellemi munkát, a folytonos traininget. És
játékból olyan műveltséget, annyi tudást szereztem, hogy ennek
szoknyában aligha találod meg a párját.
De nem csak ennyiből áll a felsőbbségem Harte Emmával
szemben.
Sohase voltam se peszra, se szobalány; előkelő származásu
vagyok. Nincs »előéletem«, multam, a melyet fegyverül lehetne
használni ellenem – a mely gáncsot vethetne elém, akárhová,
akármilyen magasra törekszem. Többet mondhatok. Én vagyok a
kifogástalanság. Én vagyok az ideál. Egy tiszta leány, a ki mindent
tud!
Nekem nem kell olyan nagy utat tennem, mint Harte Emmának.
Miért ne juthatnék el éppen olyan magasra, vagy még magasabbra?!
Igen – ne nézz olyan nagyot! – én a hatalomra szomjazom! A
komoly dolgokkal való folytonos játékom feltüzelte bennem – az
ambicziót. Az ambicziót, mely ott szunnyad a női lélekben is, bár
bizonyos, hogy az ambicziónak ez a legkevésbbé egészséges
lakóhely… De nem voltak-e nők minden időben, a kik akarták és el
tudták érni a hatalmat?! A régi királynők szenvedélye támadt fel
bennem, azoké, a kik igazi királynők akartak lenni, és csakugyan
igazi királynők lettek!
Bámulsz? Egy huszonhárom esztendős leány, a ki nem a
szerelemről, hanem a hatalomról álmodik!
Hát én alighanem férfias lélek vagyok. A fiziológusok irataiból
tudom, hogy ez lányban, asszonyban nem éppen a legnagyobb
ritkaság. A lelke legmélyén minden ember megőriz egyetmást abból
az ősállapotból, a melyben még nem volt két különböző nem.
Bizonyos vagyok benne például, hogy a szerelemnek nem lehet
akkora hatalma rajtam, mint a legtöbb asszonyszemélyen. Hidegebb
vagyok, mint más.
Igaz, úgy is fordulhatott volna életemnek a sora, hogy az
ambiczió talán sohase támad fel bennem, és örökre beérem azzal, a
mi egy közönséges asszonynak az osztályrésze, jó vagy rossz sorsa.
Sokszor gondolok rá: milyen furcsa az élet! Ha az a Featherston
nevü ember, a ki Harte Emmát elcsábította s aztán kilökte az utczára,
véletlenül másféle alak, s magánál tartja, sőt feleségül veszi Harte
Emmát… ki tudja?!… Harte Emmából talán a legjobb feleség lett
volna, a ki harisnyát foltoz, krumplit hámoz, közben sok gyermekkel
örvendezteti meg a férjét, s nem is álmodik arról, hogy diplomácziai
cselszövések és Lady Hamilton-féle női alakok is vannak a világon!
Nekem is az utamba akadt egy ilyen Featherston. Ez ugyan
engem nem csábított el… ó, a legkevésbbé se!… De egy kis ideig
mégis tőle függött a sorsom.
Ha ez az ember véletlenül az, a kinek képzeltem, ha véletlenül
csakugyan olyan, a milyennek egy pár hónapig, vagy inkább csak
egy pár perczig hittem: akkor ez az ember, ez az egy, ez a
képzeletbeli, talán fel tudta volna kelteni bennem a szerelmet. Ha ez
az ember nem több, csak éppen igazán kedvem szerint való, és meg
tud győzni arról, hogy én vagyok neki az egész világ: akkor talán
lemondtam volna az ábrándjaimról és be tudtam volna érni a
szerelemmel. »Ülj mellém a kandallóhoz; fel van szítva melege«… és
ezután már csak holtan hordoztam volna magamban a Lady
Hamiltont.
Csakhogy ez a Featherston is olyannak bizonyult, mint a többi.
Mint mindegyik férfi, a kitől egy-egy nőnek a sorsa függ, olykor egy
pár perczig.
Miképpen leplezte le magát előttem? – minthogy nem
csábíthatott el, a mi különben eszeágában se volt, tehát nem is
lökhetett ki az utczára?
Csak így:
Ez a szegény ember azt hitte, hogy én éppen olyan gazdag
vagyok, mint te. Valami pokoli véletlenből nem is sejtette, hogy te
meg én csak féltestvérek vagyunk; nem tudta, hogy te az
édesanyádtól örökölted a vagyonodat, hogy én az én anyámtól nem
örököltem semmit, és hogy az apánknak sohase volt semmije. Azt
képzelte, a jámbor, hogy ha a testvérem olyan imádásraméltóan
gazdag, én is csak az lehetek. Még az eljegyzésünk után is azt
képzelte.
Mikor megtudta a kegyetlen igazságot, hősiesen viselte
elhamarkodott lépésének a következéseit. Sápadtan, de hősiesen.
Nem lépett vissza; ha minden elveszett, a becsületet nem akarta
elveszíteni.
Csakhogy nagyon folyt az orra vére; nem lehetett nézni, hogy
mennyire folyik az orra vére!…
C’était plus fort, que lui.
És mikor elbocsátottam, örökre, mintha lidércznyomástól
szabadult volna meg. Visszanyerte a szinét, a hangját, az életkedvét.
Hát alighanem jobb is így, mind a kettőnknek.
Mert hátha a kandalló melege se tudta volna megaszalni –
néhány perczig már halálra kárhoztatott – ábrándjaimat?!
Hátha a tűzhely mellett is kitört volna belőlem az ambiczió, és
eget kér, mialatt körülöttem a tűzhely tücske czirpel és a fazékban a
leves bugyborékol?!… Mily tragédia!
Szóval, most már szabadon élhetek a hatalomra való
vágyódásomnak.
Meglehet, hogy kineveted teljes gőzzel szabadjára bocsátott
szenvedélyemet, és lehetetlennek tartod, a mire törekszem.
Megvallom, engem is gondolkodóba ejtett néha, hogy a politikai
befolyásra, a hatalomra, a koronátlan királynői szereplésre majdnem
mindig csak az Aszpáziák és a Harte Emmák tettek szert.
Sohase, vagy csak kivételképpen az erős leányok és azok az erős
asszonyok, a kik a tisztességüket, vagy mondjuk: a társadalmi
kifogástalanságuk apró előnyeit se akarták elveszíteni.
A statisztika mindenesetre azt bizonygatja, hogy a hatalomhoz
vezető úton rendesen csak azok a nők nem törnek le, a kik – a
társadalmon kivül kezdik.
Könnyebben haladnak, mert már nincs veszíteni valójuk? A
veszíteni való itt csak túlsúly, teher?
Vagy olyan eszközeik is vannak, a melyeket a magunkfajta nő
nem ismer, s éppen ezek az előttünk ismeretlen eszközök teszik
lehetővé mind előbbre, mind magasabbra haladásukat?
Meglehet. Ha sok tekintetben különb vagyok, mint Lady Hamilton
– ez talán ereje volt neki, s nekem csak akadályom.
De nem hiszem azt, hogy ha egy nő fel akar jutni a legnagyobb
társadalmi magaslatra, ehhez okvetetlenül egy nagy vargabetüt kell
tennie a társadalmon kivül.
És egyebet is mondok.
Minden áron akarom a hatalmat. Bármi áron.
Nem hiszem, hogy erre szükség lesz… akármennyire megvetem a
világot, ennél mégis különbnek tartom… de ha valaha abba a
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

ebooknice.com

You might also like