Yes, Syncfusion Blazor components are indeed mobile-friendly. They have been developed with a mobile-first approach, ensuring that they are responsive and adaptive across various devices. This means that whether users access applications built with Syncfusion Blazor components on desktops, tablets, or smartphones, they will experience consistent usability and functionality.
Comprehensive Component Library: The Syncfusion Blazor UI library includes unique components: Diagram, Smith Chart, Bullet Chart, Kanban Chart, Rating, Word Processor, Image Editor, Mention, AppBar, Speed Dial, Message, Toast, In-place Editor, Query Builder, and PowerPoint library.
Theming and Customization: Customize your Blazor application with our Fluent, Material 3, Bootstrap 5, high contrast, or dark mode themes. Additionally, our Theme Studio tool allows rich customization of these themes according to your preferences.
Performance Optimization: Syncfusion provides a CRG (custom resource group) to optimize loading performance by selectively loading specific component scripts and CSS styles as needed.
Adaptive and Touch-Friendly Design: All Syncfusion Blazor components are touch-friendly and adaptively render based on device, ensuring an optimal user experience across phones, tablets, and desktops.
Data and UI Virtualization: For large-scale applications, applicable components support data and UI virtualization, enhancing performance and scalability. This feature is available in components like DataGrid, Scheduler, and Gantt Chart.
Seamless Data Binding: Syncfusion Blazor components support seamless data binding for data-bound controls such as DataGrid, Pivot Table, Gantt Chart, and Scheduler. It includes two-way data binding for applicable component properties, enabling efficient data management.
Extensive Documentation and Demos: Access over 1,000 interactive demos, comprehensive user guide documentation, and class references to facilitate a smoother learning curve and implementation process.
Instead of using the DataAnnotationValidator in Blazor, you can use FluentValidation to implement form validation. FluentValidation is a common validation library for.NET Core that offers a few advantages over the built-in DataAnnotations validation library, such as a larger set of rules, simpler setup, and extensibility.
Install the “FluentValidation” package using the NuGet package manager.
Create a new folder named FluentValidation in the main application and add the following *.cs files – Employee, EmployeeValidator, FluentValidationValidator to it as shown below.
Add a model Employee class name in the Employee.cs file.
To write a model validator, you must create a EmployeeValidator class that is inherited from the AbstractValidator<Employee> and then add all the validation rules for the respective model to the constructor.
using FluentValidation;
namespace {AppName}.FluentValidation { publicclassEmployeeValidator : AbstractValidator<Employee> { publicEmployeeValidator() { RuleFor(p => p.Name).NotEmpty().WithMessage("You must enter a valid name."); RuleFor(p => p.Name).MaximumLength(20).WithMessage("The name cannot be more than 20 characters long."); RuleFor(p => p.Organization).NotEmpty().WithMessage("You must enter a valid organization name."); } } }
In FluentValidationValidator.cs, create a new validator component named FluentValidationValidator to replace DataAnnonationsValidator, and add the code below to it.
The FluentValidationValidator receives an EditContext as a cascading parameter and hooks into the EditContext’sOnFieldChanged and OnValidationRequested events to know when something is happening in the UI. It can add or remove validation messages from a ValidationMessageStore at any time.
using System; using FluentValidation; using Microsoft.AspNetCore.Components; using Microsoft.AspNetCore.Components.Forms;
protectedoverridevoidOnInitialized() { validator = new TValidator(); var messages = new ValidationMessageStore(EditContext);
/* Re-validate when any field changes or when the entire form requests validation.*/ EditContext.OnFieldChanged += (sender, eventArgs) => ValidateModel((EditContext)sender, messages);
while (true) { var nextTokenEnd = propertyPath.IndexOfAny(separators); if (nextTokenEnd < 0) { returnnew FieldIdentifier(obj, propertyPath); }
var nextToken = propertyPath.Substring(0, nextTokenEnd); propertyPath = propertyPath.Substring(nextTokenEnd + 1);
object newObj; if (nextToken.EndsWith("]")) { nextToken = nextToken.Substring(0, nextToken.Length - 1); var prop = obj.GetType().GetProperty("Item"); var indexerType = prop.GetIndexParameters()[0].ParameterType; var indexerValue = Convert.ChangeType(nextToken, indexerType); newObj = prop.GetValue(obj, newobject[] { indexerValue }); } else { var prop = obj.GetType().GetProperty(nextToken); if (prop == null) { thrownew InvalidOperationException($"Could not find property named {nextToken} in object of type {obj.GetType().FullName}."); } newObj = prop.GetValue(obj); }
if (newObj == null) { returnnew FieldIdentifier(obj, nextToken); }
obj = newObj; } } } }
Add the following code to the Index.razor page to perform fluent validation using the FluentValidationValidator component and its model validator (EmployeeValidator) in the EditForm component.
The DisplayName property, which is set for
built-in form components, help maintain an alternate name. When the component’s
input value is incorrect due to form validation, this alternate name is
displayed in the error message.
The DisplayName property is supported
by the following built-in components.
InputCheckbox
InputDate
InputNumber
InputRadioGroup
InputSelect
InputText
InputTextArea
Please refer to the code example below.
[Index.razor]
@page "/"
@using System.ComponentModel.DataAnnotations;
<EditFormModel="@details"><DataAnnotationsValidator /><div><strong>Name:</strong><InputText @bind-Value="details.Name" /><ValidationMessageFor="@(() => details.Name)" /></div><br /><div><strong>Age:</strong><InputNumber @bind-Value="details.Age"DisplayName="Details: Age"></InputNumber><ValidationMessageFor="@(() => details.Age)" /></div><br /><div><strong>Birth Date:</strong><InputDate @bind-Value="details.BirthDate"DisplayName="Details: Birthday" /><ValidationMessageFor="@(() => details.BirthDate)" /></div><br /><div><strong>Address:</strong><InputTextArea @bind-Value="details.Address" /><ValidationMessageFor="@(() => details.Address)" /></div><br /><div><strong>Classification:</strong><InputSelect @bind-Value="details.Classification"><optionvalue="">Select classification...</option><optionvalue="Sedan">Sedan</option><optionvalue="SUV">SUV</option><optionvalue="MUV">MUV</option></InputSelect><ValidationMessageFor="@(() => details.Classification)" /></div><br /><div><strong>Vehicle Name: @details.VehicleName</strong><InputRadioGroup @bind-Value="details.VehicleName">
@foreach (var option in VehicleNames)
{
<br /><InputRadioValue="option" /> @option
}
</InputRadioGroup><ValidationMessageFor="@(() => details.VehicleName)" /></div><br /><div><strong>Loan Required:</strong><InputCheckbox @bind-Value="details.IsLoanRequired" /><ValidationMessageFor="@(() => details.IsLoanRequired)" /></div><br /><buttontype="submit">Submit</button></EditForm>
@code{
public Details details = new Details();
public List<string> VehicleNames = new List<string> { "Ciaz", "Vitara Brezza", "Ertiga" };
public class Details
{
[Required, Display(Name = "Details: Name")]
public string Name { get; set; }
[Required]
public int Age { get; set; }
[Required]
public DateTime BirthDate { get; set; }
[Required, Display(Name = "Details: Address")]
public string Address { get; set; }
[Required, Display(Name = "Details: Classification")]
public string Classification { get; set; }
[Required, Display(Name = "Details: Vehicle Name")]
public string VehicleName { get; set; }
[Required, Display(Name = "Details: Loan Required")]
public bool IsLoanRequired { get; set; }
}
}
By default, the System.ComponentModel.Annotations library provides different validation attributes. However, to add a new or custom validation, users can create a custom validation attribute and apply it to their model class. To create an attribute:
Install the System.ComponentModel.Annotations NuGet package to perform custom validation in Created project.
Create a new folder named Models in the main application and add the following *.cs files –EmployeeDetails, OrganizationValidationAttribute to it as shown below.
Add a model EmployeeDetails class name in the EmployeeDetails.csfile.
Create a new OrganizationValidationAttribute.cs file and then the OrganizationValidationAttribute class, which is derived from ValidationAttribute. The ValidationAttribute from System.ComponentModel.Annotations acts as the base class for validation.
The ValidOrganizationName property can be set from the model EmployeeDetails class. Following that, override the IsValid method, which takes two parameters, value and validationContext. The value parameter contains the value that the user entered in the Organization field. The validationContext parameter is used to explain the context in which validation is performed. If the value is equal to the ValidOrganizationName, no errors will be thrown; otherwise, an error message returns.
Add the following custom validation attribute to the Organization property.
using System.ComponentModel.DataAnnotations; namespaceBlazorServerApp.Models { publicclassEmployeeDetails { [Required] publicstring? Name { get; set; } //Here OrganizationValidation is a Customvalidation Attribute [Required] [OrganizationValidation(ErrorMessage = "Invalid customer log-in.", ValidOrganizationName = "Syncfusion")] public string? Organization { get; set; } } }
Moving back to the Blazor Server application, add the following code to the Index.razor page to render a form with validation settings.
The built-in DataAnnotationsValidator allows you to validate form input using data annotations, but it only validates top-level properties bound to the form and not child or complex type properties. To validate the nested complex model, replace the DataAnnotationsValidator with the ObjectGraphDataAnnotationsValidator, which validates the entire object, including child and complex type properties in the form.
Install the following package via Package Manager Console in order to use the ObjectGraphDataAnnotationsValidator.
Create a new Folder named StudentDetails in the main application and add the class named Student.cs to the StudentDetails folder. In Student.cs file, create two model classes -Student and PersonalDetails. Here, add ValidateComplexType belonging to the ObjectGraphDataAnnotationsValidator above the complex type declaration.
using System.ComponentModel.DataAnnotations; namespaceValidating_Complex_Model_in_Blazor.StudentDetails { publicclassStudent { publicStudent () { Details = new PersonalDetails(); }
[Required] publicstring Name { get; set; } [Required] publicstring Department { get; set; } [ValidateComplexType] public PersonalDetails Details { get; set; } }
publicclassPersonalDetails { [Required] publicint Age { get; set; }
Create an Index.razor page with the EditForm and Input components shown in the code sample below. Set the Model property of the EditForm component to the Student class instance. Additionally, the ObjectGraphDataAnnotationsValidator and ValidationSummary tags are used for validation and the display of validation summary, respectively.
The EditContext of the form stores information about the editing process, such as which fields have been changed and which validation messages are currently displayed. To manually pass the EditContext to the EditForm, follow the steps below.
Create a new Customer.cs file and model Customer class.
publicclassCustomer { [Required] publicstring Name { get; set; }
[Required] [StringLength(4, ErrorMessage = "The organization code must be less than 5 characters in length.")] publicstring OrganizationCode { get; set; } }
Insert an EditForm component into the Index.razor page. Then, make instances of the Customer class and the EditContext, and assign the Customer class instance to the EditContext instance. Finally, bind the EditContext instance to the EditContext property in the EditForm component.
As the EditContext stores all the form information, it can be used to validate the form components. Add the Razor code as given below with input texts and a button. When a form is submitted, the Validate() method is invoked to perform validation.
[Required] [StringLength(4, ErrorMessage = "The organization code must be less than 5 characters in length.")] publicstring OrganizationCode { get; set; } } }
Create a new CustomFieldCssClassProvider.cs and then the CustomFieldCssClassProvider class.Inherit the CustomFieldCssClassProvider class from FieldCssClassProvider and override the GetFieldCssClass method, which helps to check for validation messages with the EditContext and returns the “validField” or “invalidField” class name to the appropriate field.
using Microsoft.AspNetCore.Components.Forms; using System.Linq;
namespaceFormBootstrapCSS.Data { publicclassCustomFieldCssClassProvider : FieldCssClassProvider { publicoverridestringGetFieldCssClass(EditContext editContext, in FieldIdentifier fieldIdentifier) { var isValid = !editContext.GetValidationMessages(fieldIdentifier).Any();
Add the form design code as well as the code for input components validation to the Index.razor page. Here, the SetFieldCssClassProvider method in the EditContext class is used to set the custom CSS name to the appropriate field based on the validation result returned by the CustomFieldCssClassProvider class, whose instance is passed into the method.
To use .npm packages in a Blazor WebAssembly application, follow these steps:
Create a Blazor WebAssembly application in Visual Studio 2019 using this link.
Right-click on the application and create a new folder named npm_packages.
Open the npm_packages folder directory via command prompt and run the following command to initialize NPM in the application.
npm init -y
Once the command is executed, it will create a new package.json file in the npm_packages directory.
Continue in the command prompt by executing the following command to install a JavaScript bundler named webpack and its CLI as development dependencies.
npm install webpack webpack-cli –save-dev
Finally, install the required .npm package. In this demo, we installed Syncfusion Maps by running the following command.
npm install @syncfusion/ej2-maps
Within the npm_packages folder, create a new folder called src, and then a JavaScript file called index.js.
Include the build script for the package.json file, as shown in the following, which uses webpack to bundle the JavaScript file. This script tells webpack to use the index.js file in the src folder as the source file. The output directory of the bundled file is then set to be created under the js folder in the wwwroot folder directory as index.bundle.js.
Navigate to the Index.razor page and insert a div tag with the id set as element to display the Syncfusion Maps component. [Index.razor]
@page "/"
<h1>NPM Packages Demo</h1>
<divid="element"></div>
In the index.js file, import and declare the Syncfusion Maps component. Finally, the component is appended to the div tag with the id set as element in the Index.razor page. [index.js]
Modify the index.html file with the following code to help Blazor inject a script after it starts. Note: This step is primarily for including the Syncfusion Maps component; if you’re using something else, you can skip it.
CORS stands for cross-origin resource sharing, and it is an HTTP header-based mechanism that allows the server to tell the browser whether to accept a request from a domain, port, or scheme other than its own. It is based on a process in which the browser sends a “preflight” request to the server, and the server responds with response headers indicating whether the request can proceed or not. The browser will either succeed or fail the request based on what these headers say. The browser sends headers that indicate the HTTP method and headers that will be used in the actual request in the preflight request.
To enable CORS in your Blazor Server application, follow these steps:
After creating the application, open the Program.cs file. In this file, you will find the code where the AddCors method is called on the builder.Services object to register the CORS service. Within the AddCors method, a named CORS policy called “NewPolicy” is defined using the options.AddPolicy method. If necessary, you can further configure the CORS policy by providing additional options through the builder parameter in the AddPolicy method. [Program.cs]
Bundling is the process of combining multiple files into a single file. Minifying is the process of removing unnecessary data such as comments and extra spaces, as well as converting a large variable name into a smaller name without affecting its functionalities.
To bundle and minify the CSS and JS files in a Blazor application, follow these steps:
Install the BuildBundlerMinifier NuGet package and reference it in the .csproj file, as shown.
After you build your application, the bundled and minified files are generated as shown in the following image. You can reference these files in your application based on the requirement.
The AddDefaultPolicy method allows you to add a new policy to the CORS configuration and make it the application’s default. In the Program.cs file, you can call the AddCors method to add the cross-origin resource sharing services to the service collection. To add a default policy to the configuration, you can call the AddDefaultPolicy within the AddCors method. Since you are using the default policy, there is no need to include the policy name in the UseCors method, as shown.
The AddPolicy method allows you to add a custom policy to the CORS configuration and give it a name for identification. In the Program.cs file, to add a user-defined (custom) policy to the configuration, you can call AddPolicy within the AddCors method.
SEO is an abbreviation for search-engine optimization,
and it refers to the process of optimizing a website for search engines. In
simpler words, it refers to the process of improving your website in order to
increase its visibility when people use Google, Bing, and other search engines
to find what they’re looking for.
The best way to make your Blazor WebAssembly application SEO-friendly is to work on the title, meta description, and H1 tag in the index.html common page or in individual pages based on your requirements and development activities. If you include keywords in the title, meta description, and H1 tag of your Blazor WebAssembly application, the app will appear near the top of search engine results when people search for general information using those keywords.
Title: The title must be text-only and appears in the browser’s title bar or in the page’s tab.
H1 tag: The H1 tag will be displayed as the application’s top-level heading.
Meta description: The meta description will be displayed as compressed content just below the search-related link.
Meta keywords: If anyone searches for a keyword mentioned in your Blazor application, it will appear at the top of the search engine results. However, Googlebot no longer considers meta keywords to be SEO-friendly.
Note: Make sure that your
title, H1 tag, and meta description are unique. If the description or title is
too long, Google will limit the content to a specific range. Follow these guidelines to avoid unwanted
content loss:
Title: should be
between 20 and 70 characters long.
Meta description:
should be between 100 and 160 characters long.
SEO is an abbreviation for search-engine optimization,
and it refers to the process of optimizing a website for search engines. In
simpler words, it refers to the process of improving your website in order to
increase its visibility when people use Google, Bing, and other search engines
to find what they’re looking for.
The best way to make your Blazor Server application SEO-friendly is to work on the title, meta description, and H1 tag in the _Host.cshtml common page or in individual pages based on your requirements and development activities. If you include keywords in the title, meta description, and H1 tag of your Blazor Server application, the app will appear near the top of search engine results when people search for general information using those keywords.
Title: The title must be text-only and appears in the browser’s title bar or in the page’s tab.
H1 tag: The H1 tag will be displayed as the application’s top-level heading.
Meta description: The meta description will be displayed as compressed content just below the search-related link.
Meta keywords: If anyone searches for a keyword mentioned in your Blazor application, the app will appear at the top of the search engine results. However, Googlebot no longer considers meta keywords to be SEO-friendly.
Note: Make sure that your
title, H1 tag, and meta description are unique. If the description or title is
too long, Google will limit the content to a specific range. Follow these guidelines to avoid unwanted
content loss:
Title: should be
between 20 and 70 characters long.
Meta description:
should be between 100 and 160 characters long.
In a Blazor application, you can call JavaScript functions from C# (.NET) methods and vice versa. This is referred to as “JavaScript interoperability” or “JS interop.” The JS interop allows you to integrate JavaScript libraries into your Blazor application, and its primary function is to handle DOM manipulation and browser API calls.
Please refer to this link to
learn more about JS interop in Blazor.
Please refer to this link for
calling and implementing JS interop in Blazor.
You can change
the CSS value in the Blazor application by using the following options.
Internal CSS
Inline CSS
Declare and assign a variable to the
respective DOM element.
NOTE: In CSS, the “!important” rule is used to give a property more weightage, that is, it will override all the previous styling rules applied to that element for that specific property.
[Index.razor]
@page "/"<style>
.divStyle {
font-family: 'Courier New';
color: red !important;
}
</style><divclass="divStyle"> This is internal CSS styling. </div><divstyle="font-family: 'Times New Roman'; color: green !important;"> This is inline CSS styling. </div><divstyle="@styleInfo"> This CSS styling is applied by declaring a variable. </div>
@code {
public string styleInfo = "font-family: 'Calibri'; color:blue !important;";
}
Stored procedures are pieces of reusable code that you can save in a database data dictionary. They help you extract, edit, and remove data from a database without writing the code to do so again and again. It also saves your time, lessens your workload, and increases your productivity. Follow these steps to use stored procedures in a Blazor application:
Connect the SQL Server database to the Blazor application by choosing (View –> Server Explorer). Right-click the Data Connections and choose Add connection in Visual Studio. Add your server name and DB name to connect the database to the Blazor application. The database is now connected to the Blazor application.
Add the connection string configurations to the appsetting.json file. [appsetting.json]
The Dispose method is used to avoid memory leaks and allows proper garbage collection. Implement the IDisposable interface in the component and call the Dispose method. If the framework calls the Dispose method, the component is removed from the UI and unmanaged resources can be released.
The following example demonstrates the disposal of Timer in the counter page.
A progressive web application (PWA) is usually a single-page application (SPA) used to create a Blazor WebAssembly application to work offline. It runs in its own app window and independent of network speed.
Follow these steps to create a Blazor WebAssembly PWA application to work offline.
Create a Blazor WebAssembly application with a progressive web application configuration.
Press Ctrl + F5 to run the application. Users have the option of installing the app.
Once the app is installed, the app appears in its own window without an address bar.
To achieve two-way binding with the Select component in Blazor, you can use the @bind directive. Here’s an example of how you can implement two-way binding with the Select component:
Using the StateHasChanged() method, you can force a re-render of your Blazor component. The StateHasChanged() method notifies that the state has been changed and requires a re-render of the component.
To apply custom CSS style to a Blazor component, create a custom CSS file in your Razor page with the name of razorpage.css (i.e. Index.razor.css) and add your styles.
Now, create a new custom validation class in the Pages folder and restrict the user to enter only “admin” in the password field. [CustomValidatorAttribute.cs]
Use the created custom validator attribute in the Razor component. Provide the error message and valid username properties for validation. [Index.razor]
Using C# conditional preprocessor directives and predefined constants, you can check the Blazor target framework version. For example, if the framework targets .NET 6.0, or latest version the code is compiled only in that specified condition. Follow these steps to check the Blazor target framework version.
[Index.razor]
@page "/"
<h1>@blazorVersion</h1>
@code {
privatestring? blazorVersion { get; set; }
protectedoverridevoidOnInitialized ()
{
#if NET6_0
blazorVersion = "Blazor App version is .NET6.0";
#elif NET5_0
blazorVersion = "Blazor App version is .NET5.0";
#elif NETCOREAPP3_1
blazorVersion = "Blazor App version is netcoreapp3.1";
#endif
}
}
By calling the StateHasChanged() method in Blazor, you can receive notifications about state changes and trigger component re-rendering to push the changes to the browser using SignalR. An example that illustrates this functionality is the Counter component. In this example, the component automatically pushes incremented count data using the Timer function and updates the UI in the browser by invoking the StateHasChanged() method within the InvokeAsync action.
[Counter.razor]
@page "/counter"
@using System.Timers
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
privateint currentCount = 0;
private Timer time;
privatevoidIncrementCount()
{
currentCount++;
}
protectedoverridevoidOnAfterRender(bool firstRender)
{
if (firstRender)
{
time = new Timer();
//Set the time interval.
time.Interval = 1000;
time.Elapsed += OnTimeInterval;
time.AutoReset = true;
// Start the timer.
time.Enabled = true;
}
base.OnAfterRender(firstRender);
}
Private asyncvoidOnTimeInterval(object sender, ElapsedEventArgs e)
{
IncrementCount();
await InvokeAsync(() => StateHasChanged());
}
publicvoidDispose()
{
// While navigating to other components, Dispose method will be called and clean up the Timer function.
time?.Dispose();
}
}
Use HttpContext through the IHttpContextAccessor interface to get the user agent details in a Blazor Server application. The following example demonstrates how to use HttpContext to get the user agent and IP address details by default. Extend the AddHttpContextAccessor() method in the Program.cs file.
In a Blazor Server app, the default RenderMode is Server Prerendered. When the component is rendering with the ServerPrerendered render mode, the component is initially rendering statically as part of the page.
On executing the first time, it is rendered as an MVC component directly when the page is requested and handled by “_Host” which is specified in “_Host.cshtml”.
Then the resources are loaded with the blazor.server.js script and start rendering a second time. Then the Razor pages are loaded as a Blazor component. Note: If you are changing the RenderMode to Server, the lifecycle method executes only once.
Use the System.Timers.Timer class to wait until the user has finished typing in the text field. The onkeyup event triggers for each key press and resets the timer until the last timer raises the OnUserFinish event.
By utilizing browser storage in Blazor, you can effectively save and load data within a component. In the following example, you can see how the counter value is updated with a button click and the count value is stored in the local storage of the browser. When you refresh the page, the saved data will be loaded from the browser’s local storage.
[Index.razor]
@page "/"
@using Microsoft.AspNetCore.Components.Server.ProtectedBrowserStorage
@inject ProtectedLocalStorage LocalStorage
@if (isCount)
{
<p>Current count: <strong>@currentCount</strong></p>
<button class="btn btn-primary" @onclick="IncrementCount">Increment</button>
}
else
{
<p>Loading...</p>
}
@code {
privateint currentCount;
privatebool isCount;
protectedoverrideasync Task OnAfterRenderAsync(bool firstRender)
{
if (firstRender)
{
isCount = true;
// Get the count value into browser local storage.var countValue = await LocalStorage.GetAsync<int>("countValue");
// Loaded the browser local storage value to currentCount.
currentCount = countValue.Success ? countValue.Value : 0;
StateHasChanged();
}
}
privateasync Task IncrementCount()
{
currentCount++;
// Set the count value in browser local storage.await LocalStorage.SetAsync("countValue", currentCount);
}
}
IndexedDB is used for the client-side storage of data and files. Follow these steps to use IndexedDB in Blazor WebAssembly:
Create a Blazor WebAssembly app and install the IndexedDB.Blazor NuGet package using the NuGet package manager.
Set up the IIndexedDbFactory configuration service in your Program.cs file and set it as scoped. [Program.cs]
using IndexedDB.Blazor; builder.Services.AddScoped();
Now add the properties inside the class to store and process data in the Data folder. [IndexDb.cs]
using IndexedDB.Blazor; using Microsoft.JSInterop; using System.ComponentModel.DataAnnotations; namespaceBlazor_WebAssembly_App.Data { publicclassIndexDb : IndexedDb { publicIndexDb ( IJSRuntime jSRuntime, string name, int version ) : base(jSRuntime, name, version) { } // These are like tables. Declare as many of them as you want. public IndexedSet employee { get; set; } } public class Employee { [Key] public int Id { get; set; } [Required] public string? FirstName { get; set; } [Required] public string? LastName { get; set; } } }
Add the namespace for the IndexedDB in _Import.razor file. [_Import.razor]
Install the Microsoft.AspNetCore.Components.WebAssembly.Server NuGet package in the ASP.NET Core application and add the Blazor WebAssembly application project reference to the ASP.NET Core application. [AspNetCoreApp.csproj]
Add the following configurations the Program.cs file in the ASP.NET Core app to include Blazor WebAssembly. [Program.cs]
.... if (!app.Environment.IsDevelopment()) { app.UseWebAssemblyDebugging(); app.UseExceptionHandler("/Error"); // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts. app.UseHsts(); } app.UseBlazorFrameworkFiles(); app.MapFallbackToFile("index.html"); //app.MapRazorPages(); // Remove this line. app.Run();
To avoid conflicts during publishing between WebAssembly and ASP.NET Core applications, it is necessary to delete the favicon.ico file. By default, both projects create a favicon.ico file, which can lead to conflicts. To resolve this, remove one of the favicon.ico files from the project.
Blazor authentication is implemented to determine who a particular user is. Blazor follows the existing ASP.NET Core authentication mechanisms to show a user’s identity. Follow these steps to implement authentication within Blazor WebAssembly:
Create a Blazor WebAssembly app with individual user account authentication in Visual Studio 2019.
In wwwroot/appsettings.json file, replace the Authority and Client ID placeholders with the proper values taken from the Auth0 dashboard. Note: Use Auth0; it will let you integrate authentication for configuring your application. Refer to this link for how to configure the application. [wwwroot/appsetting.json]
Add CascadingAuthenticationState and AuthorizeRouteView to display the page matching the specified route only if the user is authorized. Otherwise, it redirects to the Login page. [App.razor]
<CascadingAuthenticationState>
<RouterAppAssembly="@typeof(Program).Assembly"> <FoundContext="routeData"> <AuthorizeRouteViewRouteData="@routeData" DefaultLayout="@typeof(MainLayout)"> <Authorizing> <p>Loading...</p> </Authorizing> <NotAuthorized> <p>You're not authorized to reach this page. You need to log in.</p> </NotAuthorized> </AuthorizeRouteView> </Found> <NotFound> <p>Sorry, there's nothing at this address.</p> </NotFound> </Router> </CascadingAuthenticationState>
Create a Razor component to allow the user to log in to be authenticated in the Shared folder. [Shared/LoginControl.razor]
<RemoteAuthenticatorViewAction="@Action"> <LogOut> @{ var authority = (string)Config["Auth0:Authority"]; var clientId = (string)Config["Auth0:ClientId"]; UriHelper.NavigateTo($"{authority}/v2/logout?client_id={clientId}"); } </LogOut> </RemoteAuthenticatorView> @code{ [Parameter] public string Action { get; set; } }
Now display the authorized content when the app is authorized. If the app is not authorized, display the “Not Authorized” message to the user. [Index.razor]
@page "/" <AuthorizeView> <Authorized> <h1>Hello, @context.User.Identity.Name !</h1> <p>Welcome to your new app.</p> </Authorized> <NotAuthorized> <p>Not Authorized</p> </NotAuthorized> </AuthorizeView>
Press Ctrl + F5 to run the application and click Log in in the header to authenticate the user.
Blazor authentication is implemented to determine who a particular user is. Blazor follows the existing ASP.NET Core authentication mechanisms to show a user’s identity. Follow these steps to implement authentication with OpenID Connect in Blazor:
Create Blazor application
Create a Blazor Server app and install a NuGet package named “Microsoft.AspNetCore.Authentication.OpenIdConnect” using the NuGet package manager.
Add OIDC and authentication configuration
Add OpenID Connect and cookie authentication service configuration to the Blazor Server app in the Startup.cs file. [Startup.cs]
using Microsoft.AspNetCore.Authentication.Cookies; using Microsoft.AspNetCore.Authentication.OpenIdConnect; using Microsoft.IdentityModel.Tokens;
Create Razor pages for login (Login.cshtml.cs) and logout (Logout.cshtml.cs) redirection requests to IdentityServer for authorization under the Pages folder. [Login.cshtml.cs]
Following is the code to display the authorized content when the app is authorized. If the app is not authorized, it displays the “Not Authorized” message to the user. [Index.razor]
@page "/" <AuthorizeView> <Authorized> <h1>Hello, @context.User.Identity.Name !</h1> <p>Welcome to your new app.</p> </Authorized> <NotAuthorized> <p>Not Authorized</p> </NotAuthorized> </AuthorizeView>
Run the application
Press Ctrl + F5 to run the application and click Log in in the header to authenticate the user.
Cookies are created by the application and passed to the user’s web browser when the user submits the request. The web browser passes the cookie back to the application to indicate that the user is authenticated. When the user logs out, the cookie is removed. Follow these steps to set a cookie and read that cookie with authentication in Blazor.
Configure the cookie authentication services in the Startup.cs file. [Startup.cs]
Now, add a controller page to set the cookie to the browser and redirect the URL. [CookieController.cs]
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using System.Collections.Generic; using System.Security.Claims; using System.Threading.Tasks;
To use the authorized view, configure the CascadingAuthenticationState component in the App.razor file. This will let you check the authentication state inside the Blazor application. [ App.razor ]
Run the application and submit the form request. You will find an authentication cookie with the scheme “Cookies,” which was specified in the ConfigureServices() method of the Startup class.
Refer to this blog post for more details and download the sample on GitHub.
Blazor Server is a stateful application framework that maintains a connection to the server. Its state will occur in the server memory known as circuit. We can preserve the state in Blazor server-side three ways:
Server-side storage
URL
Browser storage
The following example demonstrates how to preserve the state
in Blazor server-side using browser storage.
Install the Blazored.SessionStorage NuGet package in the NuGet package manager to store the session data in Blazor. Add the Blazored SessionStorage configuration to the Blazor Server app.
The background long-running tasks are cancelled by using the CancellationToken object in Blazor. If an application downloads the data to render in view and then you navigate to another page, the CancellationToken cancels the download by using the Cancel() method. Call the Cancel() method by using the Dispose() method to cancel the background running task.
In the following example, the background running task in the FetchData.razor component is cancelled when a user navigates to other pages in Blazor. [FetchData.razor]
Blazor CSS isolation is a process that occurs at build time. By utilizing CSS isolation, you can restrict the scope of CSS files or styles to specific components within your app, preventing them from affecting other components globally. The CSS selectors are rewritten by Blazor to match markup rendered by the component. These rewritten CSS files are loaded as static assets in the {{Your_App_Name}}.styles.css. The static file name is referenced inside the tag of the _Host.cshtml file. [_Host.cshtml] / [index.html]
To enable CSS isolation, create a razor.css file matching the .razor file for the component in the same folder. For example, if your component is named “Isolate.razor,” create a file alongside the component named “Isolate.razor.css.” The Isolate.razor.css file is placed in the same folder as the Isolate.razor component. [Pages/Isolate.razor]
@page "/isolate" <h1>Hello, World</h1> <p>Welcome to your new app</p>
The LocationChanged event handler is triggered when there is a change in the navigation location. In the example below, a JavaScript interop function is used to display an alert to the user whenever the navigation location changes:
@inject NavigationManager UriHelper
@inject IJSRuntime JSRuntime
<p> When navigating to another page, an alert box will be displayed to indicate the navigation. </p>
@code {
protectedoverridevoidOnInitialized ()
{
UriHelper.LocationChanged += DetectNavigation;
}
privatevoidDetectNavigation (object sender, LocationChangedEventArgs e )
{
JSRuntime.InvokeVoidAsync("alert", "Navigation event is triggered");
}
}
To redirect users to your login page when their session has expired, create a RedirectLogin Razor component and implement the AuthenticationState to check whether sessions are expired or valid. Follow these steps to redirect to a login page when sessions time out in Blazor:
Create a RedirectLogin component to redirect users to a login page when their session has expired.
[RedirectLogin.razor]
@inject NavigationManager UriHelper
@code {
[CascadingParameter]
public Task<AuthenticationState> StateAuthenticate { get; set; }
protectedoverrideasync Task OnInitializedAsync()
{
var authenticationState = await StateAuthenticate;
if (authenticationState?.User?.Identity isnull || !authenticationState.User.Identity.IsAuthenticated)
{
var returnUri = UriHelper.ToBaseRelativePath(UriHelper.Uri);
if (string.IsNullOrWhiteSpace(returnUri))
{
UriHelper.NavigateTo("YourLoginPath", true);
}
else
{
UriHelper.NavigateTo($"YourLoginPath?returnUrl={returnUri}", true);
}
}
}
}
Now, initialize the RedirectLogin component in App.razor to identify whether a session is expired or valid.
To convert the date and time to a client’s or user’s time zone in Blazor Server, use the JavaScript function to get the current offset time difference from UTC in minutes using the GetLocalDateTime() method in Blazor using JavaScript Interop. Display the local time by the current offset time difference.
Follow these steps to convert the server time zone to the user’s time zone.
To define the TimeZoneService class and the GetLocalDateTime() method, create a new file named TimeZoneService.cs in your project. Inside the TimeZoneService.cs file, define the TimeZoneService class and implement the GetLocalDateTime() method.
using Microsoft.JSInterop; namespace BlazorServerApp { public class TimeZoneService { private readonly IJSRuntime _jsRuntime; private TimeSpan? _userOffset; public TimeZoneService ( IJSRuntime jsRuntime ) { _jsRuntime = jsRuntime; } public async ValueTask GetLocalDateTime ( DateTimeOffset dateTime ) { if (_userOffset == null) { int offsetInMinutes = await _jsRuntime.InvokeAsync("blazorGetTimezoneOffset"); _userOffset = TimeSpan.FromMinutes(-offsetInMinutes); } return dateTime.ToOffset(_userOffset.Value); } } }
To register the time zone service, add the following code snippet to the Program.cs file. [Program.cs]
builder.Services.AddScoped();
Create a JavaScript file named BlazorInterop.js within the wwwroot directory and include the provided code snippet in it. [BlazorInterop.js]
function blazorGetTimezoneOffset() { return new Date().getTimezoneOffset(); }
To add a reference to the JavaScript file, open the Pages/_Layout.cshtml or _Host.cshtml file, and include the following line of code: [_Layout.cshtml/_Host.cshtml]
<scriptsrc="~/BlazorInterop.js">
Finally, you can utilize the service to display a date and time in your application. [Index.razor]
To get the current data and time from client, use
the date object (new Date()) in JavaScript
using JavaScript Interop. It will return the browser’s date
and time. Following is the code to get the current date and time from the
client in Blazor WebAssembly.
<body>
. . .
. . .
<script>functionGetDateTime() {
// Date object will return browser's date and time by default in JavaScript. document.getElementById("date-time").innerHTML = newDate();
}
</script></body >
Google reCaptcha is a process that helps to protect websites form spam and abuse. To implement Google reCaptcha in Blazor, refer to the Google reCaptcha script link the WebAssembly app and render the reCaptcha by calling the JavaScript function. Follow these steps to implement Google reCaptcha in Blazor WebAssembly.
Add the Google reCaptcha renderer function in a separate JavaScript file under the wwwroot folder. [googlereCaptcha.js]
Now call the rendering reCaptcha function in JavaScript from the Razor page using JavaScript Interop and show the reCaptcha response on button click. Note: To start using reCaptcha, you need to generate the API site key for your site. Refer to this link to generate the site key. [Index.razor]
To call a JavaScript method with parameters in Blazor WebAssembly, you can follow the code snippet provided below:
[Index.razor]
@page "/" @inject IJSRuntime JsRuntime <p>Here's an example of how to call a JavaScript method with parameters in Blazor WebAssembly.</p>@code {
protected override async void OnInitialized ()
{
string content = "JavaScript function called with parameter";
await JsRuntime.InvokeVoidAsync("jsFunction", content);
}
}
[index.html]
<body>
. . .
. . .
<script>functionjsFunction(value) {
// Parameter value has been passed here.console.log(value);
};
</script></body >
Close a browser window from a page in Blazor WebAssembly using
JavaScript Interop with the window.close() method. The window.close() method closes the currently opened window.
In the following example, open a new browser window and
close it using the window.close() method with a button onclick event.
To read a JSON file in Blazor WebAssembly, you can utilize the HttpClient class along with the GetFromJsonAsync() method.
Follow these steps to achieve that:
To proceed, create or load a JSON file in the wwwroot folder. As an example, I have created a basic employee.json file and will read its values within a Razor component.
[wwwroot/employee.json]
[{"id": "emp1"}, {"id": "emp2"}, {"id": "emp3"}]
[Index.razor]
@page "/"@inject HttpClient Http@if (employees == null)
{<p>Loading...</p>}else{@foreach (var employee in employees)
{<p>Employee ID: @employee.Id</p>}
}
@code {
private Employee[] employees;
protected override async Task OnInitializedAsync()
{
employees = await Http.GetFromJsonAsync<Employee[]>("employee.json");
}
public class Employee
{
public string Id { get; set; }
}
}
When we run a Blazor application with a SQL Server localdb for storing authentication data, by following these steps we can implement SQLite in it:
Update the NuGet package.
Modify the Startup.cs file and connection string.
Modify the database migration code.
Updating the NuGet package: Remove the Microsoft.EntityFrameWorkCore.SqlServer NuGet package from the current package manager and add the Microsoft.EntityFrameWorkCore.Sqlite package.
Modifying the Startup.cs file: Change the Startup.cs file from options.UseSqlServer to options.UseSqlite.
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.EntityFrameworkCore;
…………………. . .
namespaceBlazSqlite
{
publicclassStartup
{
………………… . .
publicvoidConfigureServices(IServiceCollection services)
{
services.AddDbContext<SqlDbContext>(options =>
options.UseSqlite(
Configuration.GetConnectionString("DefaultConnection")));
services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)…………… . }
Modify the connection string in the AppSettings.json file.
“DataSource=<yourdbname>.db” (points to your sqlite database file)
Modifying the database migration code: Modify the database migration code to avoid the errors that would occur after performing the previous steps. Change the “00000000000000_CreateIdentitySchema.cs” file as follows.
“.HasAnnotation(“SqlServer:ValueGenerationStrategy”, SqlServerValueGenerationStrategy.IdentityColumn)” or “.Annotation(“SqlServer:ValueGenerationStrategy”, SqlServerValueGenerationStrategy.IdentityColumn)”
to “.HasAnnotation(“Sqlite:Autoincrement”, true)” or “.Annotation(“Sqlite:Autoincrement”, true)”
Run the app and start registering a new user for authentication. Refer to this link to learn how to create a SQL database with a Blazor Server application. Refer to this link for more information about authentication with SQLite and Blazor.
When using Blazor WebAssembly to enforce Office 365 authentication, it is necessary to include the tenant ID and client ID in the appsettings.json file, which can be found under your Azure account.
In Azure AD, a tenant is a dedicated Azure service instance that a company receives and owns after signing up for a Microsoft cloud service such as Azure or Microsoft 365. Each tenant ID is distinct and separate from other tenants.
Procedure outline
Create a new environment in Power Apps and note the web API service root URL.
Register your Azure account.
Create a WebAssembly app using Azure AD for authentication.
Update the callback URL in the app to run the app.
Grant API permissions to access data from the dataverse and modify the code to display the data in the app.
Please refer to this link for a detailed explanation of the implementation of Office 365 authentication.
The routing interception concept is sometimes used to restrict user access to some page or link if they did some work or made some changes on a specific page. In the following code, you can use the NavigateTo() method to intercept routing inside the If condition. The routing happens according to the values passed in the condition.
@page "/" @inject Data.RouteData RouteData <p>Type the text below to allow Home page intercepting</p> <textarea @bind="RouteData.Textfield"></textarea>
Check the condition and allow the navigation process in the [NavMenu.razor] page as shown.
We can use NavigationManager, which has a built-in LocationChanged event that will be triggered when the user navigates away from the current page. In the following code, we use an alert JS function by adding the IJSRuntime to show the user has navigated by overriding the OnInitialized() method through the alert message.
[Index.razor]
@page "/"@inject NavigationManager nav@inject IJSRuntime JSRuntime<h1>Detect Navigation events</h1>@code {
protected override void OnInitialized()
{
nav.LocationChanged += (o, e) =>
{
JSRuntime.InvokeVoidAsync("alert", "User has navigated to other page");
}; }}
When the user navigates from the home page to the counter page or vice versa, the alert message stating “User has navigated to other page” will be shown.
We generally use authentication for specific pages to prevent access by unauthorized users. In the case that we do want a specific page to be accessed by any users, not only authorized users, we will use the anonymous users category.
To make a Blazor page accessible by all users, use [AllowAnonymous] with @attribute code in the _Imports.razor file in your app.
[_Imports.razor]
@attribute [AllowAnonymous]
By doing this users can access the secured page (here we secured the fetch data) without a login.
As the Blazor client runs in the browser, both user authorization and authentication for WebAssembly will be completely handled by the back-end API. The back-end web API must handle the authorization on every API call, and it tells the Blazor app whether the user is authenticated and has resource access. It enables your Blazor app to show the correct context to the user.
Create a Blazor WebAssembly app using Visual Studio 2019 with ASP.NET Core hosting enabled.
Reorganize the folder names according to usage:
Sample.Server is renamed to Sample.Api as we are going to use this as our API.
Sample.Client is renamed to Sample.WebApp.
Sample.Shared is renamed to Sample.Common.
In the Sample.Common folder, create a Models folder, and move the generated WeatherForecast class to this folder and change its namespace to Sample.Models. Add the AuthorizedUser class in the Models folder under the Sample.Shared folder.
public AuthorizedUser AuthorizedUser { get; privateset; } = new AuthorizedUser(); publicoverrideasync Task<AuthenticationState> GetAuthenticationStateAsync() { ClaimsPrincipal user; if (!string.IsNullOrEmpty(ApiUriGetAuthorizedUser)) AuthorizedUser = await _httpClient.GetJsonAsync<AuthorizedUser>(ApiUriGetAuthorizedUser); if (string.IsNullOrEmpty(AuthorizedUser.Name)) { user = new ClaimsPrincipal(); } else { var identity = new ClaimsIdentity(CreateClaims(AuthorizedUser), AuthenticationType); user = new ClaimsPrincipal(identity); } returnnew AuthenticationState(user); }
privatestatic IEnumerable<Claim> CreateClaims(AuthorizedUser authorizedUser) { yield return new Claim(ClaimTypes.Name, authorizedUser.Name);
var roles = authorizedUser.Roles?.Split(',') ?? newstring[0]; foreach (var role in roles) yield return new Claim(ClaimTypes.Role,role.Trim()); } } }
Add the following code in the Program.cs file.
using Microsoft.AspNetCore.Components.Authorization; using System.Net.Http; ... publicstaticasync Task Main(string[] args) { var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.Services.AddAuthorizationCore(); builder.Services.AddScoped<ClientAuthorizationService>(CreateAuthorizationService); builder.Services.AddScoped<AuthenticationStateProvider>(sp => sp.GetRequiredService<ClientAuthorizationService>()); builder.Services.AddOptions(); ... privatestatic ClientAuthorizationService CreateAuthorizationService(IServiceProvider serviceProvider){ var httpClient = serviceProvider.GetRequiredService<HttpClient>(); var service = new ClientAuthorizationService(httpClient) { ApiUriGetAuthorizedUser = "api/settings/user",
Run the app with Sample.Api as the startup file and see the output as follows.
Since Windows authorization is not yet implemented in the API, If you click the Sign In button, you will be rerouted to a page stating, “Sorry, there’s nothing at this address.” When you change the code in the GetUser() method in the SettingsController to include the name of the user, the app will be shown as follows.
Role-based authorization is a declarative way of limiting resource access that first appeared in ASP.NET (pre-Core). In order for the user to access certain resources, developers must specify a role that the user belongs to. This is done by using the [Authorize] attribute. Users can have a single role or multiple roles depending on the backing store used. The following procedure explains how to implement role-based authorization.
Create a Blazor WebAssembly app and add the following role service in the Startup class under ConfigureServices.
Add specific roles in your database by overriding the OnModelCreating method of ApplicationDBContext. The User and Admin roles are added in the following code.
builder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "User", NormalizedName = "USER", Id = Guid.NewGuid().ToString(), ConcurrencyStamp = Guid.NewGuid().ToString() }); builder.Entity<IdentityRole>().HasData(new IdentityRole { Name = "Admin", NormalizedName = "ADMIN", Id = Guid.NewGuid().ToString(), ConcurrencyStamp = Guid.NewGuid().ToString() }); } }
Once the roles are added, generate a migration and apply it to your database.
Add – Migration SeedRoles Update-Database
Add users to the roles by updating the action on the Accounts controller. All new users are added to the User role, except for the admin email. [AccountsController.cs]
[HttpPost] publicasync Task<IActionResult> Post([FromBody]RegisterModel model) { var newUser = new IdentityUser { UserName = model.Email, Email = model.Email }; var result = await _userManager.CreateAsync(newUser, model.Password); if (!result.Succeeded) { var errors = result.Errors.Select(x => x.Description); return BadRequest(new RegisterResult { Successful = false, Errors = errors }); } await _userManager.AddToRoleAsync(newUser, "User"); if (newUser.Email.StartsWith("admin")) { await _userManager.AddToRoleAsync(newUser, "Admin"); } return Ok(new RegisterResult { Successful = true }); }
Update the Login method in the LoginController. Add roles as claims to the JSON web token (JWT) since we are assigning new users to roles at signup, so we need to pass this information to Blazor. Add the following code in the Login method.
Current users can be taken through UserManager, which is used to get their roles.
publicasync Task<IActionResult> Login([FromBody] LoginModel login) { …………….. . var user = await _signInManager.UserManager.FindByEmailAsync(login.Email); var roles = await _signInManager.UserManager.GetRolesAsync(user); var claims = new List<Claim>();
foreach (var role in roles) { claims.Add(new Claim(ClaimTypes.Role, role)); } …………….. . . }
Add roles in client-side Blazor. Once the new users are signed up, we have to get those roles via JWT. To do this, we add the following code in the ParseClaimsFromJwt method, which will take JWT, decode it, extract claims, and return it.
private IEnumerable<Claim> ParseClaimsFromJwt(string jwt) { var claims = new List<Claim>(); var payload = jwt.Split('.')[1]; var jsonBytes = ParseBase64WithoutPadding(payload); var keyValuePairs = JsonSerializer.Parse<Dictionary<string, object>>(jsonBytes);
We have to check that the first character is [, indicating it’s a JSON array. If the role claim is present and if the [ character is found, then we have to extract the individual role names from the roles entered. We have to loop these role names and add each as a claim, but if the role is not an array, then it is added as a single role claim.
To call ParseClaimsFromJwt, we need to update the MarkUserAsAuthenticated method as shown.
publicvoidMarkUserAsAuthenticated(string token) { var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt")); var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
NotifyAuthenticationStateChanged(authState); }
Update the Login method on the AuthService to pass the token rather than the email when calling MarkUserAsAuthenticated.
publicasync Task<LoginResult> Login(LoginModel loginModel) { ……………. . var result = await _httpClient.PostJsonAsync<LoginResult>("api/Login", loginModel);
if (result.Successful) { await _localStorage.SetItemAsync("authToken", result.Token); ((ApiAuthenticationStateProvider)_authenticationStateProvider).MarkUserAsAuthenticated(result.Token); _httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", result.Token);
return result; }
return result; }
Apply role-based authentication to the API. We can allow access to a specific page by an admin user alone through the Authorize attribute as shown.
publicclassSampleDataController : Controller { …… . . [Authorize(Roles = "Admin")] [HttpGet("[action]")] public IEnumerable<WeatherForecast> WeatherForecasts() { var rng = new Random(); return Enumerable.Range(1, 5).Select(index => new WeatherForecast { Date = DateTime.Now.AddDays(index), TemperatureC = rng.Next(-20, 55), Summary = Summaries[rng.Next(Summaries.Length)] }); } }
Apply role-based authentication in the Blazor page. Use the @attribute directive with the [Authorize] attribute in a Blazor page to restrict the user access to specific pages. The following code allows the admin user alone to see the fetchdata page.
When we log in using accounts other than admin, we are unable to load the fetchdata page.
We can also add role-based authorization using the AuthorizeView component in the Index.razor page as shown in the following code.
<AuthorizeViewRoles="User"> <p>You can only see this if you satisfy the IsUser policy.</p> </AuthorizeView> <AuthorizeViewRoles="Admin"> <p>You can only see this if you satisfy the IsAdmin policy.</p> </AuthorizeView>
The output text is shown according to the accounts (admin/user) the user is signed in as. Refer to this link for further information about role-based authorization in Blazor WebAssembly.
Google authentication is a process by which the user can use their Google accounts to get authorized to access particular data. Follow this procedure to implement Google authentication.
Set the Authentication Type as Individual Accounts and then click Create.
Go to Tools > NuGet Package Manager > Package Manager Console. Before running the app, we have to perform migration by running the following command in the Package Manager Console.
Update-Database
To configure a Google API Console project, check whether SSL is enabled by right-clicking the project name, selecting Properties, and selecting the Debug property. I need this URL for configuration.
To create a Google API Console project, follow these steps.
Click the Credentials page link under the topic “Create authorization credentials.” Sign in with your Google account and create a project by providing a project name.
Click Create Credentials and select OAuth client ID.
Select the Application type and type the name of the OAuth ID and the redirect URI (localhost URL given to enable SSL in your app) as shown.
Click Create and note your client ID and client secret, which are important for Google authentication.
Install the Google Authentication middleware NuGet package by typing the following command in the Package Manager Console.
Blazor applications are component-based. Blazor components can be used in existing ASP.NET MVC applications. Follow these steps to learn how Blazor components are used in the view page of an MVC application.
Prerequisites:
Visual Studio 2019
.NET Core 3.1
Create a ASP.NET MVC application.
Open Visual Studio 2019 and select ASP.NET Core Web App (Model-View-Controller) in the Create a new project page and configure the project as shown.
Add the reference Microsoft.AspNetCore.Components in your dependencies.
Add the Blazor component folder in the View/Shared folder.
Then add a Razor component inside the Component folder.
Add the following code to the created Component.razor file.
@using Microsoft.AspNetCore.Components <h3>Blazor Component in MVC</h3> <button@onclick="Test"class="btn btn-dark">Click to get answer</button> <br /> <div >@Data</div> @code { [Parameter] public string Data { get; set; } = string.Empty; private void Test() { Data = "Button Clicked"; } }
Add the script reference to the _Layout.cshtml file.
Create an _Imports.razor file in the Component folder and add the following namespaces to the _Imports.razor file to access component features over your components in the application.
Add services.AddServerSideBlazor() under the ConfigureServices method and add endpoints.MapBlazorHub(); under the Configure method in the Startup.cs file.
In the component page, we use the button to change the text defined in the Index.cshtml page inside the component rendering. Clicking the button will change the text shown on the Home page.
Since there is no built-in functionality for saving files in Blazor, it is necessary to write the function in JavaScript and then invoke the JavaScript function from C# code in Blazor. In this solution, we have used JavaScript interop for file saving and generation in client-side Blazor.
Create a new JavaScript file, saveFile.js, in the wwwroot folder and add the following code. [saveFile.js]
functionsaveFile(file, Content) { var link = document.createElement('a'); link.download = name; link.href = "data:text/plain;charset=utf-8," + encodeURIComponent(Content) document.body.appendChild(link); link.click(); document.body.removeChild(link); }
Reference the new script file in the index.html page as shown. [index.html]
In Blazor, there is no significant difference between using these two attributes. The @bind attribute is a shorthand of the @bind-value attribute and its delegate will trigger the ValueChanged event of the component. The usage of both the @bind and @bind-value attributes in the following code examples are functionally equivalent.
We can bind a drop-down list in Blazor WebAssembly using the <select> tag and bind the values to the drop-down list using the @bind attribute in the tag. In the following code example, we have bind a country list along with its country codes. On changing the dropdown list, the codes corresponding to the country will appear below.
[Index.razor]
@page "/"
<p>Select country from the DropDownList</p>
<selectclass="form-control" @bind="@SelectedCountryID">
@foreach (var country in CountryList)
{
<option value="@country.Code"> @country.Name </option>
}
</select>
<br/>
<p>@SelectedCountryID</p>
@code {
string selectedCountryID;
string SelectedCountryID
{
get => selectedCountryID;
set {selectedCountryID = value;}
}
List<Country> CountryList = new List<Country>() { new Country ("IND", "India"),new Country ("USA", "United States"),new Country ("UK", "United Kingdom")};
publicclassCountry
{
publicCountry(string code, string name)
{
Code = code;
Name = name;
}
publicstring Code { get; set; }
publicstring Name { get; set; }
}
}
Note: We also have our Syncfusion Dropdown List component. Please refer to the demo link for more information about our product.
Using MVC in a Blazor application is not yet possible, but we have an option to migrate an existing ASP.NET MVC application to a Blazor Server application.
Browser history can be accessed in Blazor using the window’s popstate event, which is fired when the user navigates the session history. We use the history API to get the history changes in the browser, and we can manually move to a specific page using back(), forward(), go(). When routing takes place in the application or browser, you can use the following code to store the current location:
Unit testing is a level of software testing that is used by developers to ensure that the implemented logic meets the requirements and behaves as expected. The following example uses the bUnit testing library for Blazor components to write comprehensive and stable unit test cases. It allows you to write test cases in C# or Razor syntax to verify outcomes with semantic HTML diffing and comparison logic.
Create a simple Blazor Server/WebAssembly application.
In Visual Studio 2019, right-click on the project solution and select the Add > New Project option.
Select NUnit Test Project (.NET Core) and click Next button.
Enter the project name and then click Create button. The created project will be displayed like the following.
Open the NuGet manager for BlazorTest and search with the keyword bunit.web. The result will be displayed as seen in the following screenshot. Select bunit.web and install it.
Right-click on BlazorTest project dependencies and add the project reference BlazorServerApp.
Blazor prerendering is a process where web page elements are built and compiled on the server and static HTML is hosted in WebAssembly (client side). When Razor pages load, components are prerendered at the same time. This process improves page loading by making it faster for SPAs (single page applications), which improves search engine optimization.
To set up prerendering for a hosted Blazor WebAssembly app:
Create the Blazor web Assembly App with ASP.net core Hosted. Here solution name is BlazorHosted.
Delete wwwroot/index.html file from the Blazor WebAssembly Client project.
In the Client project, delete the following lines in Program.cs:
Add the _Host.cshtml and _Layout.cshtml files to the Pages folder in the Server project. These files are already included in the Blazor Server template and can be obtained from there. Make the following changes to the _Host.cshtml file:
Modify the namespace based on APP namespace as BlazorHosted.Client.
Update the render-mode as ‘WebAssemblyPrerendered’ in host.cshtml
Make the following changes to the _Layout.cshtml file: Update the Pages namespace at the top of the file to match namespace of the Server app’s pages like this,
@namespace BlazorHosted.Server.Pages
Add @using directive for the Client project at the top of the file:
@using BlazorHosted.Client
Update the stylesheet links to point to the WebAssembly project’s stylesheets. So, make the following changes. Remove the following lines
<linkhref="css/site.css"rel="stylesheet" /> <linkhref="{App Name space}.styles.css"rel="stylesheet" /> <componenttype="typeof(App)"render-mode="ServerPrerendered" />
In the endpoint mapping of the Server project in Program.cs, update the fallback from the index.html file to the _Host.cshtml page. Remove the following line
app.MapFallbackToFile("index.html");
Add the following line
app.MapFallbackToPage("/_Host");
If the Client and Server projects use one or more common services during prerendering, factor the service registrations into a method that can be called from both projects. For more information, see ASP.NET Core Blazor dependency injection.
Run the Server project. The hosted Blazor WebAssembly app is prerendered by the Server project for clients.
In the following example, the cookie consent banner temple will display to notify you to accept cookies. Follow the below steps to create a consent cookie in Blazor.
1. Configure the HttpContextAccessor and CookiePolicyOptions to the Program.cs file to create a consent cookie.
Blazor doesn’t manipulate the DOM directly at C# side. You can call the JavaScript method by using JavaScript Interop to get an element by ID or class.
The getElementsByClassName() method returns a collection of all elements in the document with the specified class names.
The getElementById() method returns a collection of all elements in the document with the specified ID names.
[Index.razor]
@page "/"@inject IJSRuntime JsRuntime<h1id="headingElement">Hello, world!</h1><pclass="para-element">Welcome to your new app.</p>@code {
protected override async void OnAfterRender(bool firstRender)
{
await JsRuntime.InvokeVoidAsync("elementId");
}
}
[_Host.cshtml]
<body>
. . .
. . .
<script>
function elementId() {
// Get element with the specified ID name
var idValue = document.getElementById("headingElement");
console.log(idValue.innerHTML);
// Get element with the specified Class name
var classValue = document.getElementsByClassName("para-element");
console.log(classValue[0].innerHTML);
}
</script></body>
Configure the logger in the builder in the Program.Main configuration file. Add a package reference for Microsoft.Extensions.Logging.Configuration to the Blazor app’s project file using the NuGet package manager.
Now, add the namespace as Microsoft.Extensions.Logging to Program.cs and add the builder logging configuration. This configuration will prevent the logging info in the browser console.
In Blazor, you can call a JavaScript method using JavaScript interop to scroll the page to the top position.
In the following code, the button event triggers when the button is clicked and scrolls to the page top.
[Index.razor]
@page "/"@inject IJSRuntime JsRuntime<divstyle="background-color:lightgrey;padding:60px 60px 1000px"><h2>Blazor App</h2>
This example demonstrates how to scroll to the top based on the button click event.<br />
Scroll down and click the button; it scrolls to the top position.
</div><div><br /><button @onclick="OnButtonClick"class="btn btn-primary">Click Button</button></div>@code {
private async void OnButtonClick()
{
await JsRuntime.InvokeVoidAsync("OnScrollEvent");
}
}
[_Host.cshtml]
<body>
. . .
. . .
<script>
// When the user clicks the button, the page scrolls to the top
function OnScrollEvent() {
document.documentElement.scrollTop = 0;
}
</script></body>
2. Delete the Startup.cs file configuration in the existing Blazor Server app and add the required WebAssembly configurations to the Program.cs file. Add the following code for WebAssembly configuration.
[Program.cs]
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.Extensions.DependencyInjection;
using System;
using System.Net.Http;
using System.Threading.Tasks;
namespaceBlazorServerApp
{
publicclassProgram
{
publicstaticasync Task Main(string[] args)
{
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
await builder.Build().RunAsync();
}
}
}
3. Now add the below namespace to your converting application in the _Import.razor file.
4. Delete the _Host.cshtml, Error.cshtml, and Error.cshtm.cs files under the Pages folder and create an index.html file and add the below code snippet under wwwroot/index.html file.
[index.html]
<!DOCTYPE html><html><head><metacharset="utf-8" /><metaname="viewport"content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" /><title>{{Your_Application_Name}}</title><basehref="/" /><linkhref="css/bootstrap/bootstrap.min.css"rel="stylesheet" /><linkhref="css/site.css"rel="stylesheet" /><linkhref="{{Your_Application_Name}}.styles.css"rel="stylesheet" /></head><body><divid="app">Loading...</div><divid="blazor-error-ui">
An unhandled error has occurred.
<ahref=""class="reload">Reload</a><aclass="dismiss">🗙</a></div><scriptsrc="_framework/blazor.webassembly.js"></script></body></html>
5. Now, run the application. The existing Blazor Server project is now converted into a Blazor WebAssembly project.
<body>
. . .
. . .
<script>
function copyClipboard() {
/* Get the text field */
var copyText = document.getElementById("form-control");
/* Select the text field */
copyText.select();
/* Copy the text inside the text field */
document.execCommand("copy");
/* Alert the copied text */
alert("Copied the text: " + copyText.value);
}
</script></body>
As opposed to how session cookies work, when opening a page in a new tab or window, a new session occurs with the browsing context. To access the browser sessionStorage in Blazor apps, write custom
code or use a third-party package. The accessed data can be stored in localStorage and sessionStorage. Know that localStorage is scoped to the user’s browser. If the user reloads the page or closes and reopens the browser, the state persists. Session storage is similar to local storage, but data in the session storage will be cleared after the session.
Install the Blazored.SessionStorage Nuget package in the NuGet package manager to store the session data in Blazor. Add the Blazored SessionStorage configuration to the WebAssembly app.
RenderFragment is a delegate that renders a UI segment. So, it does not have an Empty state. It can be null, which is equivalent to empty in the sense that it will produce no rendered output. In the following example, see that the RenderFragments are in a null state or contain a value.
@if (childContent != null)
{<p>@childContent</p>}else{<p>RenderFragment isnull</p>}<buttonclass="btn btn-primary" @onclick="OnButtonClick">Click</button>@*RenderFragment is null by default, click the button to update the RenderFragment*@@code {
private string textContent = "Welcome to your new Blazor app.";
private RenderFragment childContent { get; set; }
private void OnButtonClick()
{
childContent = BuildRenderTree => BuildRenderTree.AddContent(1, textContent);
}
}
An <iframe> tag is known as an inline frame or frame within a frame. It’s an HTML element that allows documents to be embedded within the current page. The following example illustrates how to embed a URL inside an iframe in the Blazor Web App and Blazor WebAssembly Standalone App targeting .NET 8.0.
Blazor virtualization is a technique for limiting UI rendering to just the parts that are currently visible. It improves the perceived performance of component rendering using the Blazor framework’s built-in virtualization support with the virtualize component. When you are using a long list-item component with a loop, you can use virtualization for better performance.
Use the Virtualize component when:
A set of data items in a loop needs to be rendered.
You can read static files by creating HttpClient Get calls. The GetStringAsync method sends a request to the specific URI and returns the response body as a string in an async operation.
RenderFragment is used to render components or content at run time in Blazor. The RenderFragment class allows you to create the required content or component in a dynamic manner at runtime. In the following code example, the content is created at runtime on OnInitialized.
4. Add the text/content for localization in the Index.razor file.
[Index.Razor]
@page "/"@using BlazorLocaleWASM.Shared.ResourceFiles@inject Microsoft.Extensions.Localization.IStringLocalizer<Resource> Locale<h1>@Locale["Hello world"]</h1>@Locale["Welcome to your new app"]<SurveyPromptTitle="How is Blazor working for you?" />
5. By default, Blazor WebAssembly carries minimal globalization resources required to display values, such as dates and currency, in the user’s culture. Applications that must support dynamically changing the culture should configure BlazorWebAssemblyLoadAllGlobalizationData in the project file.
Follow these steps to create a Blazor WebAssembly (client-side) application using a command-line interface (CLI).
Create a Blazor WebAssembly App in CLI
Open a command prompt where you want your project to be located and run the following command.
dotnet new blazorwasm -o BlazorWebAssemblyApp
Navigate to Blazor WebAssembly App
Run the cd BlazorWebAssemblyApp command to navigate to the BlazorWebAssemblyApp folder.
Run the application
The dotnet run command runs the application. See the following output in the default browser.
Note: If you have installed multiple SDK versions and need a specific framework version (e.g., net5.0, netcoreapp3.1) project, then add the -f flag to the dotnet new blazorwasm command. Refer here for the available flag options.
Follow these steps to create a Blazor Server application using a command-line interface (CLI).
Create a Blazor Server App in CLI
Open a command prompt where you want your project to be located and run the following command.
.NET CLI
dotnet new blazorserver -o BlazorServerApp
Navigate to Blazor Server App
Run the cd BlazorServerApp command to navigate to the BlazorServerApp folder.
Run the apllication.
The dotnet run command runs the application. See the following output in the default browser.
Note: If you have installed multiple SDK versions and need a specific framework version (e.g., .net7.0) project, then add the -f or –framework flag to the dotnet new blazorserver command.
.NET CLI
dotnet new blazorserver -o BlazorServerApp –framework net6.0
Follow the step-by-step procedure below to create a Blazor Server Application in Visual Studio 2019.
Download and install Visual Studio 2019
Download and install the latest version of Visual Studio 2019 with the ASP.NET and web development workload.
Create a new project
Open Visual Studio 2019 and click Create a new project.
Select Blazor app from the template
Select Blazor App from the template list and click the Next button.
Configuring the project
The project configuration window will pop up. Click the Create button to create a new project with the default project configuration.
Choose Blazor Server App
Select a target framework based on your requirement, choose the Blazor Server App from the dashboard, and then click Create to create a new Blazor Server application.
Blazor Server App structure
Now the Blazor Server App is created, and the structure look like the following image.
Run the application.
Press Ctrl + F5 to run the application and find the output in default browser.
Follow the step-by-step procedure below to create a Blazor WebAssembly (client-side) application in Visual Studio 2019.
Download and install Visual Studio 2019
Download and install the latest version of Visual Studio 2019 with the ASP.NET and web development workload.
Create a new project
Open Visual Studio 2019 and select Create a new project.
Select Blazor app from the template Select Blazor App from the template list and click the Next.
Choose Blazor WebAssembly App Select a target framework based on your requirements, choose Blazor WebAssembly App from the dashboard, and then click Create to create a new Blazor WebAssembly application.
Blazor WebAssembly App structure Now the Blazor WebAssemblyApp is created, and the structure look like in the below image.
Run the application. Press ctrl + F5 to run the application and see the below output in default browser.
Data annotation localization in Blazor server-side and WebAssembly (client-side) apps is achieved by referencing the Resource class localized string. Follow these steps to achieve this:
Add the required localized error messages to the Resource file in the Resource folder.
In the validation attribute, set the ErrorMessageResourceType as typeof(Resource).
Assign the required validation message to the ErrorMessageResourceName property.
[Index.razor]
@page "/"@using {{ApplicationName}}.Resource
@using System.ComponentModel.DataAnnotations;<EditFormModel="@_employee"OnValidSubmit="HandleValidSubmit"><DataAnnotationsValidator /><ValidationSummary /><InputTextid="name" @bind-Value="_employee.Name" /><buttontype="submit">Submit</button></EditForm>@code {
public class Employee
{
[Required(ErrorMessageResourceName = "RequiredError", ErrorMessageResourceType = typeof(Resource))]
[StringLength(5, ErrorMessageResourceName = "LengthError", ErrorMessageResourceType = typeof(Resource))]
public string Name { get; set; }
}
private Employee _employee = new Employee();
private void HandleValidSubmit()
{
Console.WriteLine("OnValidSubmit");
}
}
You can add smooth scrolling to a Blazor app using a combination of Blazor components and JavaScript interop, similar to the functionality available in jQuery UI components.
Step 1: Create a New Blazor App Run the following command to create a new Blazor WebAssembly app:
.NET CLI
dotnet new blazorserver -n SmoothScrollDemo
Step 2: Add CSS Styles Open the wwwroot/css/site.css file and add the following CSS class for smooth scrolling:
[wwwroot/css/site.css]
.smooth-scroll {
scroll-behavior: smooth;
}
Step 3: Create a SmoothScroll Component Create a new Blazor component named SmoothScroll.razor:
[SmoothScroll.razor]
<!-- Pages/SmoothScroll.razor -->@page "/Smoothscroll" @inject IJSRuntime JSRuntime <h3>Smooth Scrolling Example</h3><divclass="smooth-scroll"><p>
This is a demonstration of smooth scrolling in a Blazor app.
Click the button below to smoothly scroll to the bottom of the page.
</p><button @onclick="ScrollToBottom">Scroll to Bottom</button></div><divclass="content"><!-- Add some content here to make the page longer --><h4>Smooth Scrolling in Blazor: Elevating User Experience with Elegance</h4><p>In the realm of modern web development, the user experience reigns supreme, and every nuance plays a pivotal role in crafting an immersive and delightful interaction. One such understated yet highly impactful element is the art of smooth scrolling. Blazor, the cutting-edge web framework by Microsoft, empowers developers with the ability to seamlessly integrate this feature into HTML elements. By adding an enchanting fluidity to the scrolling mechanism, Blazor transforms the user journey into an elegant dance, enhancing engagement and delivering a heightened sense of sophistication.</p><h4>The Essence of Smooth Scrolling</h4><p>Smooth scrolling, at its core, is the art of imbuing scrolling actions with an exquisite gracefulness. Unlike the conventional abrupt and jarring movements that characterize traditional scrolling, smooth scrolling introduces a harmonious glide that seamlessly navigates users through various sections or elements on a web page. This simple yet transformative touch has the power to transcend the mundane, transforming user interactions into a symphony of motion and elegance.</p><h4>Unveiling the Benefits</h4><ol><li><h6>Enhanced User Engagement:</h6>
By eliminating the disorienting jumps, smooth scrolling creates a captivating rhythm that keeps users immersed and engaged as they explore the content.
</li><li><h6>Visual Fluidity:</h6>
The graceful transitions between sections establish a visual continuity that feels natural and intuitive, amplifying the overall aesthetics of the website.
</li><li><h6>Improved Readability:</h6>
For lengthy articles or content-rich pages, smooth scrolling guarantees a comfortable reading experience by gradually revealing the content.
</li><li><h6> Subtle Sophistication: </h6>
Smooth scrolling lends an air of refinement to the user journey, elevating the perception of the website's design and enhancing its overall brand image.
</li><li><h6>Extended Time on Page:</h6>
The fluidity and beauty of smooth scrolling entice users to linger, thereby increasing their time spent on the website and fostering a deeper connection.
</li></ol></div>@code {
private async Task ScrollToBottom()
{
await JSRuntime.InvokeVoidAsync("scrollToBottom");
}
}
Step 4: Add the following JavaScript function for scrolling to the bottom of the page in _Host.cshtml.
DateTime.Now.ToShortDateString() and DateTime.Now.ToLongDateString() are methods that return the current culture date format. The string returned by the ToShortDateString and ToLongDateString methods are culture-sensitive. It reflects the pattern defined by the current culture’s date format. You can get the current culture date format by using either of the following methods.
You can customize the loading text in a Blazor WebAssembly application by editing the tag for target framework version 3.* or the tag for target framework version 5.* in the index.html page. In the following example, I have customized the loading text while loading.
In the following example, LoadingScreen will display a loading message while data is loaded asynchronously. Once the data has been loaded, it replaces the loading message with the actual content.
None. Inserting an existing ASP.NET Web Forms app in a Blazor Server app is not possible. You can migrate the ASP.NET Web Forms app to a Blazor Server spp. Follow this documentation to migrate your ASP.NET Web Forms app to Blazor.
Languages are changed by using localization in the Blazor server-side application. In the following example, the languages are changed from English to French and vice versa by clicking a button.
[Program.cs]
builder.Services.AddLocalization();
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
…
var localizeOptions = new RequestLocalizationOptions()
.SetDefaultCulture("en-US")
.AddSupportedCultures("en-US", "fr-FR")
.AddSupportedUICultures("en-US", "fr-FR");
app.UseRequestLocalization(localizeOptions);
app.MapControllers();
…
Add the culture resource files in the Resources/Pages folder.
[Index.razor]
@page "/"@inject Microsoft.Extensions.Localization.IStringLocalizer<Resource> locale<h1>@locale["Hello World"]</h1>@locale["Welcome to your new app."]<SurveyPromptTitle="How is Blazor working for you?" />
Blazor has a built-in InputFile component from .NET 5.0 that can be used to upload files to the server. You can check the file size in the OnChange event and upload or prevent uploading the files to the server.
[Index.razor]
@page “/”<h3>File Upload</h3><InputFileOnChange=”OnInputFileChange” />@if (file?.Size < 1000000)
{<p>Name: @file.Name</p><p>Size in bytes: @file.Size</p><p>Last modified date: @file.LastModified.DateTime.ToShortDateString()</p><p>Content type (not always supplied by the browser): @file.ContentType</p>}
else
{<p>File size exceeds more than 1MB</p>}@code {
IBrowserFile file;
void OnInputFileChange(InputFileChangeEventArgs e)
{
file = e.File;
if (e.File.Size < 1000000)
{
// Uploadfilestotheserverfromhere
}
}
}
Note: Syncfusion offers a feature-rich, easy-to-use File Upload component for Blazor. You can check it out here.
Yes, you can host and deploy the blazor server-side application without using Azure but by using AWS or Firebase. Here you can find the steps for hosting the Blazor application using AWS.
Create the Blazor application
Publish the application using the context menu from the Solution in Solution Explorer in Visual Studio.
Click Publish. If there is no error, your application will be published successfully.