Azure App Service with On-premises Connection

Imagine you get a new project with the ability to use whatever cloud services you want. You jump at the change and dream up an amazing architecture using Azure. Next, you present your plan to the rest of your team and discover a new requirement of having to use an existing on-premises database.

Does this mean your grand plans are shot? Thankfully not, as Azure has multiple solutions that allow you to connect to your existing on-premises resources to enable hybrid cloud strategies.

In this post, we are going to use one of the options, Hybrid Connections, to connect from a web site hosted in an App Service to an on-premises database.

Sample Application

The base sample application we will be using for this post is a new Razor Pages App targeting .NET Core 3. We will walk through actually connecting to the database later in this post. To get started you need the new app created and running in an Azure App Service.

I have multiple walkthroughs of creating a new application and publishing them to Azure so I’m not going to rehash that here. If you need help getting your app created and published to Azure you can check out my Deploying an ASP.NET Core Application to Microsoft Azure post and instead of using the Razor template use the Web App template like the following.

dotnet new webapp

Also, note that Hybrid Connections aren’t available on the free or shared hosting plans so when you are setting up your publish profile avoid those options.

Add a Hybrid Connection to an App Service

From the Azure Portal open the App Serice you created above and under the Settings section of the menu click Networking.

In the networking details, we want to click Configure your hybrid connection endpoints.

I’m going to point out again that Hybrid Connections aren’t available at free and shared scales levels. If your App Service is on a free or shared scale use the Scale up menu option to switch to a scale level that will support Hybrid Connections.

From the Hybrid connections detail page click Download connection manager. When done this will need to be installed on the machine that is running the on-premises database you want to connect to.

Next, click Refresh and then click Add hybrid connection.

Now on the Add hybrid connection page click Create new hybrid connection.

In order to create a new hybrid connection, Azure will require some information. The key parts here are the Endpoint Host which is the name of the machine that is hosting the database you wish to communicate with and the Endpoint Port which will need to be the port that your database is configured to communicate over.

Hybrid Connection Manager on the host machine

Now that the Azure side is configured we need to use the Hybrid Connection Manager application that we installed on the target machine above to allow talk to our App Service.

After opening the Hybrid Connection Manager on the target machine click Add a new Hybrid Connection.

Now Select the Subscription the App Service is a part of. After the list of available connections, loads select the one created above and finally click Save.

After making the above changes my hybrid connection continued to show offline in Azure. After some searching, I found a blog post that suggested restating the Azure Hybrid Connection Manager Service which cleared the problem up for me.

Sample Application Changes to Connect to On-Premises Database

This is a very raw test, but it gets the point across. First, add a reference to the System.Data.SqlClient NuGet package. Next in the Index.cshtml.cs delete the OnGet function and replace it with the following.

public async Task OnGetAsync()
{
    Tables.Clear();
    var connectionString = "data source=Server;initial catalog=master; User Id=User;Password=Password"";
    await using var connection = new SqlConnection(connectionString);
    await connection.OpenAsync();
    await using var command = 
                    new SqlCommand("SELECT name FROM sys.tables", connection);
    await using var reader = command.ExecuteReader();

    while (await reader.ReadAsync())
    {
        Tables.Add(reader["name"].ToString());
    }
}

The above connects to the master database on the specified server and pulls a list of table. Note that you will need to modify the connection string to something valid for your system. It is also important to know that you can’t use integrated security with this setup so you will need to specify a user and password that exists on your SQL Server. Add the following property in the same file.

public List<string> Tables { get; set; } = new List<string>();

Add the following to the bottom of the Index.cshtml which will output the table list we pulled above to the page.

@foreach (var table in Model.Tables)
{
    @table <br/>
}

After the changes are done republish the application to your Azure App Service. After the publish is done your site should show with a list of tables that exist in the master database of your SQL Server.

Wrapping Up

Hybrid connections is a great way to take a workload to the cloud without having to actually move all your data. It is also one of those features of Azure that I had no idea that existed before a week ago.

If you need a lot of hybrid connections look closely at the pricing as the number you can use is tied to what App Service scale you are using. The number of available starts at 5 and can go up to 200 with the more expensive App Service scales.

Publish a .NET Core Worker Service to Azure

In last week’s post, .NET Core Worker Service, we created a .NET Core Worker Service and then showed how to host it as a Windows Service. This week we will be taking the application created in last week’s post and publishing it to Azure. If you haven’t read last week’s post I recommend you at least get through the application creation bits. Feel free to skip the part about making the application run as a Windows Service since we will be pushing to Azure for this post.

Publish to Azure

This post is going to assume you already have an active Azure account. If not you can sign up for a free Azure account. This post is also going to be using Visual Studio 2019 Preview for the publication process.

In Visual Studio right-click on the project and click Publish.

Since this project already has a folder publish setup from last week’s post my screenshot might look different from yours. Click the New link.

This will launch the Publish profile dialog. We will be publishing to Azure WebJobs using the Create New option. After verifying the settings are correct click Create Profile.

The next screen gets the details of the App Service that will be created. I did a new resource group instead of using the one that was defaulted in and a new hosting plan so that I could utilize the free tier, but both of these changes are optional. When you have everything set click the Create button.

Once create is clicked it takes a couple of minutes to deploy the application. This first deploy is going to be a throwaway for us. There are a few settings we need to tweak to get the application running the way we want. After the initial deployment is complete we end up back on the profile details screen. Click the Edit link.

The Publish Profile Settings dialog will show. Since this was written while .NET Core 3 is still in preview I’m using the Self-contained option for Deployment Mode. If you are doing this after the final release then you can skip this step. The second thing I am changing is the WebJob Type and I’m setting it to Continuous. This is because our Service is controlling its own work schedule and not being triggered by something else. Click Save to commit the changes and return to the publish dialog.

Now push the Publish button to push the application to Azure.

Use Azure Portal to Verify Application is Working

Now that our application is running in Azure how do we verify that it is actually executing as we expect? Since the only thing the sample application does it output some logs we are going to have to find a way to show the output of the logging. To start head over to the Azure Portal. Since we just published the application the resource we are interested in should show in your Recent resources section of the Azure Portal homepage. As you can see in the screenshot the one we are interested in is the first option and matches the name we saw above in Visual Studio. Click on the resource.

From the menu section scroll down to the Monitoring section and click App Service logs. Now turn On the option for Application Logging (Filesystem) and for the Level option select Information since that is the log level our sample application is outputting. Then click Save.

Back in the same Monitoring group of the menu select Log stream.

Wrapping Up

Running a worker in Azure ended up being pretty simple. Not that I’m surprised Microsoft tends to make all their products work well with Azure. I’m sure you will find a way to make a more useful worker than we had in this example.

.NET Core Worker Service

A year or so ago I wrote the post Host ASP.NET Core Application as a Windows Service. With the upcoming release of .NET Core 3, we now have another option for creating a service with the new Worker Service template. This post is going to walk through creating a new application using the new Worker Service template and then running the service as a Windows Service.

Project Creation

I’m going to use Visual Studio 2019 Preview for this process. If you would rather you can use the .NET CLI with the following command to create the project instead.

dotnet new worker

For the Visual Studio, open the application and select the Create a new project option.

On the next screen search for Worker Service and click Next.

On the next screen enter a Project name and click the Create button.

Next, click the create button to finally create the project, unless you want to use Docker.

Project Structure

The resulting structure is pretty simple. The two files that we will be dealing with are Program.cs and Worker.cs.

Program.cs is the entry point for the application and defines the different works you want to run. The following is an example that sets up two different workers. The default template only has one worker, but I added the second one to show multiple workers are an option.

public class Program
{
    public static void Main(string[] args)
    {
        CreateHostBuilder(args).Build().Run();
    }

    public static IHostBuilder CreateHostBuilder(string[] args) =>
        Host.CreateDefaultBuilder(args)
            .ConfigureServices((hostContext, services) =>
            {
                services.AddHostedService<Worker>();
                services.AddHostedService<Worker2>();
            });
}

Worker.cs contains the code that gets called to execute work. The following is the default worker that gets created from the template. This worker just writes a log once a second.

public class Worker : BackgroundService
{
    private readonly ILogger<Worker> _logger;

    public Worker(ILogger<Worker> logger)
    {
        _logger = logger;
    }

    protected override async Task ExecuteAsync(CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            _logger.LogInformation("Worker running at: {time}",
                                   DateTimeOffset.Now);
            await Task.Delay(1000, stoppingToken);
        }
    }
}

At this point, you could run the application and it would do whatever work you have it set up to perform.

Run as a Windows Service

To run the project as a Windows Service we need to add a NuGet package. To do this right-click on the project file and select Manage NuGet Packages.

In the NuGet dialog click the Browse tab, check the Include prerelease checkbox, search for Microsoft.Extensions.Hosting.WindowsServices, and finally click Install.

After the package is installed open Program.cs and add a call to UseWindowsService to host builder in the CreateHostBuilder function.

public static IHostBuilder CreateHostBuilder(string[] args) =>
    Host.CreateDefaultBuilder(args)
        .UseWindowsService()
        .ConfigureServices((hostContext, services) =>
        {
            services.AddHostedService<Worker>();
            services.AddHostedService<Worker2>();
        });

Publish the Application

Now that we have the application set up to be able to run as a Windows service we need to publish it. To publish from the .NET CLI you can use the following command in the directory with the solution or project file. There is also an option for an output location if you want it to go to a different directory.

dotnet publish

Or from Visual Studio click the Build > Publish {Solution Name} menu. Select the Folder option on the left and then click Create Profile.

On the next screen click the Publish button.

Service Installation and Management

At this point, the application can be installed and managed like any other Windows service. To install the service open a command prompt in admin mode and run the following command to create a windows service. The binPath needs to be the full path to your exe or your service will fail to start even it is created successfully.

sc create WindowsServiceHosted binPath= "C:\Users\eanderson\Desktop\Worker\Worker\bin\Debug\netcoreapp3.0\publish\Worker.exe"

Also, note that the space after binPath= and before the exe name is needed.

Now that the service is installed run the following command to start it.

sc start Worker

To check the state of your service use the following command.

sc query Worker

To stop your service use the following command.

sc stop Worker

Finally, to uninstall your service use the following command.

sc delete Worker

Wrapping Up

This template makes it really easy to get started with a worker. Hopefully, this will help you get started. Make sure and check out the .NET Core Workers as Windows Services post from Microsoft.

Failed Post

This week I set out to write a continuation of the Blazor themed post I have been doing over the last few weeks. I was going to show how to handle OnSubmit instead of OnValidSubmit as I did in the first post on forms and validation.

I spend most of the week on trying to get this to work, but I failed. I couldn’t find a way to get access to the EditForm in the function that handled the submit. I’m sure there is a way to get this work, but I couldn’t get it to work in the timebox that I had for this post.

Hitting a wall on something like this is frustrating, but having to stretch and learn is one of the things I love about being in the development space. The hard part about a failed post like this week is I really need to cut my losses and move on to a new subject.

One of the things people often ask me about is how I manage to keep doing a post a week in the long run. The timebox I mentioned above is a critical component to the reason my system works. While I would love to be able to solve every problem I hit it just isn’t reasonable to do if I want to hit my goal of a post a week.

Blazor Forms and Validation

This week I’m exploring the basics of using forms and validation in a server-side Blazor. This is an area that the Blazor team is still making a lot of changes too so don’t be surprised if some of the things in this post need to be tweaked. If you need help creating a Blazor application check out my ASP.NET Core Server-Side Blazor with Authentication post, which is the app I’m using to write this post.

Model

For this example, I’m going to be creating a form for editing a contact. Blazor will make use of data annotations and automatically make sure that the conditions are valid. The following is the class I’m using as my model with a few data annotations thrown in. Project structure-wise I added a Models directory and added my model class there.

public class Contact
{
    public int Id { get; set; }
    [Required]
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    [StringLength(5, 
                  MinimumLength = 5, 
                  ErrorMessage = "Postal Code must be 5 characters")]
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    [Required]
    [EmailAddress]
    public string Email { get; set; }
}

As you can see in the class Name and Email are both required fields. Email is also required to be a valid email address. PostalCode isn’t required, but if entered must be 5 characters. If the Postal Code is entered but isn’t 5 characters then the specified error message will show in the UI.

Component

Next, I added a new ContactEdit component. For details on how to add a new component check out Razor Components in Blazor which will walk through adding a new component using Visual Studio. It will also show you have to add the component to an existing page.

The following is the full component. Most of the component is normal HTML form elements. After the code, I will point a few things out.

@using Models
@using System.Diagnostics

<h3>Contact Edit</h3>

<div class="row">
    <div class="col-md-4">
        <EditForm Model="@contact" OnValidSubmit="@ValidSubmit">
            <DataAnnotationsValidator />
            <ValidationSummary />

            <div class="form-group">
                <label for="name" class="control-label">Name: </label>
                <InputText id="name" @bind-value="contact.Name" class="form-control" />
                <ValidationMessage For="@(() => contact.Name)" />
            </div>
            <div class="form-group">
                <label for="address" class="control-label">Address: </label>
                <InputText id="address" @bind-value="contact.Address" class="form-control" />
                <ValidationMessage For="@(() => contact.Address)" />
            </div>
            <div class="form-group">
                <label for="city" class="control-label">City: </label>
                <InputText id="city" @bind-value="contact.City" class="form-control" />
                <ValidationMessage For="@(() => contact.City)" />
            </div>
            <div class="form-group">
                <label for="state" class="control-label">State: </label>
                <InputText id="state" @bind-value="contact.State" class="form-control" />
                <ValidationMessage For="@(() => contact.State)" />
            </div>
            <div class="form-group">
                <label for="postalCode" class="control-label">Postal Code: </label>
                <InputText id="postalCode" @bind-value="contact.PostalCode" class="form-control" />
                <ValidationMessage For="@(() => contact.PostalCode)" />
            </div>
            <div class="form-group">
                <label for="phone" class="control-label">Phone: </label>
                <InputText id="phone" @bind-value="contact.Phone" class="form-control" />
                <ValidationMessage For="@(() => contact.Phone)" />
            </div>
            <div class="form-group">
                <label for="email" class="control-label">Email: </label>
                <InputText id="email" @bind-value="contact.Email" class="form-control" />
                <ValidationMessage For="@(() => contact.Email)" />
            </div>
            <button type="submit">Submit</button>
        </EditForm>
    </div>
</div>

@code {
    private Contact contact = new Contact
    {
        Id = 1,
        Name = "Eric",
        Address = "578 Main St.",
        City = "Nashville",
        State = "TN",
        Phone = "615-555-5555",
        Email = "ericeric.com"
    };

    private void ValidSubmit()
    {
        Debug.WriteLine("ValidSubmit");
    }
}

The following is a subsection of the code from above that is different from standard HTML forms.

<EditForm Model="@contact" OnValidSubmit="@ValidSubmit">
    <DataAnnotationsValidator />
    <ValidationSummary />

    <div class="form-group">
        <label for="name" class="control-label">Name: </label>
        <InputText id="name" @bind-value="contact.Name" class="form-control" />
        <ValidationMessage For="@(() => contact.Name)" />
    </div>
    <button type="submit">Submit</button>
</EditForm>

The EditForm is a component that Microsoft created that will bind to your model and allow you to specify what function is going to be called on submit. In this example, we are using OnValidSubmit to call the ValidSubmit function only if the model validates. Make note of the usage of the DataAnnotationsValidator which is the component that enables validation based on the data annotations that we placed on our model class.

The other thing to note is the usage of the ValidationSummary component which shows a summary of all the validation issues on the model. This example is also using ValidationMessage to show errors in line with the associated fields. In a real application, I doubt both would be used, but I wanted to show how to use both.

Wrapping Up

Hopefully, this has been a helpful introduction to forms and validation in Blazor. I may end up doing a follow-up post on the other submission options.

Make sure and check out the official docs for more information.  Rémi Bourgarel also has a great post on the subject.

Blazor Component Attributes

This post is going to take a look at a couple of new ways, as of ASP.NET Core Preview 7, to make it easier to deal with components that have a lot of attributes. The example we are going to use is an input control as they provide a lot of built-in attributes.

Initial Component

The following is a basic component named InputComponent. It contains a single HTLM input element with properties for ID, Type, and Placeholder text.

<input id="@Id"
       type="@Type"
       placeholder="@Placeholder"/>

@code {
    [Parameter]
    private string Id {get; set;} = "DefaultId";

    [Parameter]
    private string Type {get; set;} = "text";

    [Parameter]
    private string Placeholder {get; set;} = string.Empty;
}

The following is an example usage of the above component to show an email input element.

<InputComponent Id="InputTest" Placeholder="Email Address" Type="email" />

Input Attributes Dictionary

The following code is the same component that has been converted pull attributes out of a dictionary.

<input @attributes="InputAttributes" />

@code {
    [Parameter(CaptureUnmatchedValues = true)]
    private Dictionary<string, object> InputAttributes { get; set; } =
        new Dictionary<string, object>() 
            {
               { "id", "DefaultId" },
               { "type", "text" },
               { "placeholder", "" }
            };
}

The results of both are the same but in this version, you don’t have to pre-define all of the attributes you might expect and it still allows you to provide defaults by prepopulating the dictionary with the default values you would like to use.

Without the [Parameter(CaptureUnmatchedValues = true)]  it seems like you still need parameters on your component to match the attribute values passed in so I’m not sure how useful using a dictionary is without capturing unmatch values other than keeping you from having to specify each value in the HTML element. I was hoping to not need the parameters defined and it captures based on the values in the dictionary.

Wrapping Up

This feature is a nice addition that can save you some keystrokes. Check out the official docs for the full details.

Event Handling in Blazor

This post is a continuation of my Blazor exploration and will be a quick post as the sample application created with Microsoft’s template already contains an example. If you want to see how the sample application is created check out my ASP.NET Core Server-Side Blazor with Authentication post, or check out all my Blazor related posts.

Events

It is hard to write an application without needing to handle user input in some manner. For this post, we are going to be using a button click as an example. We will also be using the counter component as the example which can be found in the Counter.razor file. The following is the code for the component.

@page "/counter"

<h1>Counter</h1>

<p>Current count: @currentCount</p>

<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>

@code {
    int currentCount = 0;

    void IncrementCount()
    {
        currentCount++;
    }
}

In the above example the @onclick=”IncrementCount” is the bit we are interested in. Blazor uses @onEventName with the string that follows is the function in the @code section of the component that should handle the event.

In our sample, the on click event of the button calls the IncrementCount function which changes the currentCount variable which causes the component to update with the new count value.

Just to show that this works with more than just click if you change the button to include an event to mouse over you will see the counter increment when your mouse goes over the button or when the button is clicked.

<button class="btn btn-primary" @onmouseover="IncrementCount" @onclick="IncrementCount">Click me</button>

Wrapping Up

I’m slowing building up the basics of Blazor applications for myself. I hope these more bite-sized chunks of Blazor info are helpful for you all as well. Writing these posts are helping cement the concepts in my mind.

Razor Components in Blazor

Since the release candidate for .NET Core 3.0 is getting closer it seemed like a good time to take a closer look at Blazor, as you can tell from the string of Blazor posts lately. For this post, I’m taking my first look at Razor Components in a Blazor server-side application.

This post is working off the same sample project used in the following posts. The first one contains the creation of the project if you want to follow along.

ASP.NET Core Server-Side Blazor with Authentication
Blazor Authentication: Hide a Nav Menu Item

What are Razor Components?

To quote the docs:

A component is a self-contained chunk of user interface (UI), such as a page, dialog, or form. A component includes HTML markup and the processing logic required to inject data or respond to UI events. Components are flexible and lightweight. They can be nested, reused, and shared among projects.

Basically, Razor Components gives us a way to create smart reusable chunks of UI.

Create a new Razor Component

To start I created a new Components directory in my project. This isn’t required, but it was how one of the Blazor sample projects were set up. Caution, if you do follow this path make sure and add the new namespace to _Imports.razor or your components will fail to render. Please don’t ask how long it took for me to figure that out.

@using System.Net.Http
@using Microsoft.AspNetCore.Components.Forms
@using Microsoft.AspNetCore.Components.Layouts
@using Microsoft.AspNetCore.Components.Routing
@using Microsoft.JSInterop
@using BlazorAuth
@using BlazorAuth.Shared
@using BlazorAuth.Components

Right-click on the directory you want to create the component in and select Add > New Item.

In the Add New Item dialog select Razor Component, give the component a name and click Add.

The resulting file will look like the following.

<h3>HelloWorld</h3>

@code {

}

For this component, I don’t have any code so I deleted that section and added space between Hello and World. To use this component you can add <HelloWorld /> to any of your existing components or pages. For example, in the sample application, I changed the Index.razor to include the new component.

@page "/"

Welcome to your new app.

<HelloWorld />

The above will render as the following.

A Component with a Parameter

The above is great, but we all know that a component that only contains static HTML isn’t going to be super useful without the ability to make parts of the component more dynamic. The following example is only one of the ways to get data into a component.

The following bit of code is a new component that has a private name property that is marked with the Parameter attribute. This property can then be used in the non-code section of the component in the standard Razor syntax way.

<h3>Hello @Name!</h3>

@code {
    [Parameter]
    private string Name {get; set;}
}

The following is the usage of the HelloName component back in the Index.razor and is passing in a name via the name parameter.

@page "/"

Welcome to your new app.

<HelloWorld />
<HelloName Name="Eric" />

And the resulting output when the application is run.

Wrapping Up

Components provide a great unit of reusability. I highly recommend you take some time to play around with them. Also, make sure and check out the Create and use ASP.NET Core Razor components doc from Microsoft as it covers the full range of options when developing components.

Blazor Authentication: Hide a Nav Menu Item

In last week’s post, Server-Side Blazor with Authentication, we covered creating a Server-Side Blazor application with Authentication and then used the attribute to not allow the user to view the Fetch data page if they weren’t logged in.

While the authorize attribute does keep the user from viewing the contents of the page it still allows the user access to the nav menu item for the page they aren’t authorized to access. This is going to be a quick post showing how the AuthorizedView component can be used to hide any content that a user should be logged in to see (or be in a specific role).

Hide a Nav Menu Item

In the Pages/Shared directory open the NavMenu.razor file which is the file where the nav menu is defined. The following code is the code that renders the Fetch data menu item which is the section we want to hide if the user isn’t logged in.

<li class="nav-item px-3">
    <NavLink class="nav-link" href="fetchdata">
        <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
    </NavLink>
</li>

To hide menu item we wrap the list item in the AuthorizeView component.

<AuthorizeView>
    <li class="nav-item px-3">
        <NavLink class="nav-link" href="fetchdata">
            <span class="oi oi-list-rich" aria-hidden="true"></span> Fetch data
        </NavLink>
    </li>
</AuthorizeView>

Do note that you should still use the Authorize attribute on the page that should require authorization and not depend on the menu item being hidden keeping users from finding the page.

Wrapping Up

While the Authorize attribute is still very useful I’m sure that the AuthorizeView will be getting a lot of use in Blazor apps. AuthrozieView has the advantage of not being limited to page component.

Also, note that AuthorizeView also supports roles and policies. Make sure and check out the official AuthorizeView component docs for more details. If interested the code for the component is on GitHub.

ASP.NET Core Server-Side Blazor with Authentication

It has been close to a year since I did my first into post on Blazor, ASP.NET Core Basics: Blazor, and a lot has changed. The biggest thing is that it was announced that Server-Side Blazor is going to ship with .NET Core 3. This post is going to walk through creating a server-side Blazor application including authentication.

Sever-Side Blazor

What is server-side Blazor and how is it different from client-side Blazor? The quick answer is that client-side Blazor uses WebAssembly and Mono to run .NET code in the browser allowing for basically a SPA written in .NET. With Server-Side Blazor the app is executed on the server and update/processing are requested over a SignalR connection.

For a deeper dive into the differences check out the ASP.NET Core Blazor hosting models doc.

Pre-requisites

To start make sure to install at least preview 6 of .NET Core 3. Using a command prompt you can run the following command to see which versions of the .NET Core SDK are installed.

dotnet --list-sdks

The previews of .NET Core 3 can be downloaded from here. Also, make sure to use the latest preview of Visual Studio 2019.

Application Creation

I used the following command from the command prompt to create a new Blazor application using individual authentication.

dotnet new blazorserverside --auth Individual

Visual Studio also has the template available if you select the ASP.NET Core Web Application project type and about three screens in select the Blazor Server App option.

After the creation process is complete open the project in Visual Studio. At this point, if you run the application you will see the standard options to log in or register.

Requiring Auth for a Page

At this point, the application allows account creation and login, but all pages are available to all user, even if they aren’t logged in. There are multiple ways to deal with this. For this post, I’m going with the closest to what I am used to from MVC which is using an Authorize attribute. In the Pages directory open then FetchData.razor file and make the following changes to make the page require the user to be authorized. Note that this method should only be used on page components.

Before:

@page "/fetchdata"
@using BlazorAuth.Data
@inject WeatherForecastService ForecastService

After:

@page "/fetchdata"
@using BlazorAuth.Data
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject WeatherForecastService ForecastService

Now if you go to the Fetch data page without being logged in you will see a Not authorized message. This message can be customized using the AuthorizeView component. You can find more details in the docs.

Wrapping Up

It is neat seeing how far Blazor has come since I last played with it. The docs are great and the product has improved a ton. I may do a follow-up post to go more into how to use the AuthorizeView component.

Make sure to check out the official docs on Blazor authentication and authorization to get the full picture of the subject.