ASP.NET Core

Using NSwag to Generate C# Client Classes for ASP.NET Core 3

This post is going to use one of the tools provided by NSwag to generate C# client classes to provide access to an API. While the NSwag tooling provides multiple ways to discover the definition of an API we will be using the tooling to generate C# classes from an OpenAPI/Swagger specification.

For details on how to use NSwag to provide OpenAPI/Swagger for your APIs check out my Swagger/OpenAPI with NSwag and ASP.NET Core 3 post. You can grab the API I’m using in the post from this GitHub repo if you need an API to play around with. If you do grab the sample API from GitHub not that it does use Entity Framework Core and SQLite which means you will need to create the associated database. Details of how to do that can be found in the Create and Apply Initial Migration section of my ASP.NET Core 3: Add Entity Framework Core to Existing Project post.

The following is the same style post for different frontends.

Swagger/OpenAPI with NSwag and ASP.NET Core 3
ASP.NET Core 3: Add Entity Framework Core to Existing Project
New Razor Pages Project Backed with an API
Using NSwag to Generate Angular Client for an ASP.NET Core 3 API
Using NSwag to Generate React Client for an ASP.NET Core 3 API
Using NSwag to Generate Blazor Server Client for an ASP.NET Core 3.1 API
Using NSwag to Generate a Vue Client for an ASP.NET Core 3.1 API

Sample Client Application

For this example, we will spin up a Razor Pages application using the .NET CLI with the following command from your favorite terminal application in the directory you want the application created.

dotnet new webapp

NSwag Client Generation

NSwag provides multiple options for client generation including a CLI option, code, and a Windows application. This post is going to use the Windows application which is called NSwagStudio. Download and install NSwagStudio from here.

Next, make sure your API is running and get the URL of its OpenAPI/Swagger specification URL. For example, I am using a local instance of my API and the URL I need is https://localhost:5001/swagger/v1/swagger.json. If you are using the Swagger UI you can find a link to your swagger.json under the API title.

Now that we have the OpenAPI/Swager specification URL for the API we are dealing with open NSwagStudio. The application will open with a new document ready to go. There are a few options we will need to set. First, we want to use the NetCore30 Runtime. Next, select the OpenAPI/Swagger Specification tab and enter your API’s specification URL in the Specification URL box.

In the Outputs section check the CSharp Client checkbox and then select the CSharp Client tab. As you can see from the screenshot below there are a ton of options to tweak. For this example, we are taking the defaults for all of them except for Namespace, which I set to ContactsApi, and Output file path, which is only needed if you use the Generate Files option. Click the Generate Files button and NSwagStudio will create a file that contains all the code needed to access the API described in the OpenAPI/Swager specification selected in the Input section.

Note, the Generate Outputs button can be used if you want to see what the generated code will look in the Output tab on the same level as Settings.

Use Generated Client from the Sample Project

In the sample project, I created an APIs directory and dropped the ContactsApi.cs created with NSwagStudio there. The files generated with NSwagStudio are expecting JSON.NET to be present so the sample project will need a reference to the Microsoft.AspNetCore.Mvc.NewtonsoftJson NuGet package.

Now that the project has a reference to JSON.NET in the ConfigureServices function of the Startup class we need to tell the app to make JSON.NET available via dependency injection with the following change.

services.AddRazorPages()
        .AddNewtonsoftJson();

Now to test out the client I used the following OnGet function in the Index.cshtml.cs file.

public async Task OnGet()
{
    using (var httpClient = new HttpClient())
    {
        var contactsClient = new ContactsClient(httpClient);
        var contacts = await contactsClient.GetContactsAsync();
    }
}

Note the above is only meant to show that the generated client work and isn’t meant to be a production-grade example. For more production-grade scenarios make sure and following Microsoft’s guidance on HTTP client usage.

Wrapping Up

NSwag’s client generation seems to be an easy way to get started consuming API’s. I’m not sure if the CLI would provide more options for how the client code is generated or not with support of HTTPClientFactory and strongly typed HTTP Clients. This will be something I may explorer more in a future post.

Using NSwag to Generate C# Client Classes for ASP.NET Core 3 Read More »

Entity Framework Core: No database provider has been configured for this DbContext

When writing ASP.NET Core 3: Add Entity Framework Core to Existing Project I got to the point where I was going to add my initial Entity Framework Core migration when I got a huge error message with the last bit being the following in red.

No database provider has been configured for this DbContext. A provider can be configured by overriding the DbContext.OnConfiguring method or by using AddDbContext on the application service provider. If AddDbContext is used, then also ensure that your DbContext type accepts a DbContextOptions<TContext> object in its constructor and passes it to the base constructor for DbContext.

State of the Project

The project I was working on was an API that had a single model defined as the following.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

And the DbContext looked like this.

public class ContactsDbContext : DbContext
{
    public DbSet<Contact> Contacts { get; set; }
}

Finally the ConfigureServices function of Startup.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ContactsDbContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));
    services.AddControllers();
}

The Error

At this point, I ran the following command from the command prompt to add a migration.

dotnet ef migrations add Initial

Which results in the following error.

Stay Calm, Read, and Fix

Don’t make the same mistake I did and runoff and double-check everything in your application. The yellow and red sections of the exception message tell you what the fix should be.

In the case of the application in question, I wanted to use the connection string setup in Startup.ConfigureServices. To do that, as the error states if you bother to read it, the DbContext needs a constructor added that takes a DbContextOptions and passes that value to the base class’ constructor like the following.

public ContactsDbContext(DbContextOptions<ContactsDbContext> options) : base(options)
{ }

Alternatively, if you aren’t to the point in your application that you want to get your database information from configuration you can override OnConfiguring in your DbContext and set your connection string there like the following.

protected override void OnConfiguring(DbContextOptionsBuilder options)
    => options.UseSqlite("DataSource=app.db");

I don’t recommend the second option, but since it is valid I feel like it needs to be included.

Wrapping Up

For me, this served as a good reminder to slow down and actually read errors even if they are a wall of text. Hopefully making myself write this post will help this lesson stick.

Entity Framework Core: No database provider has been configured for this DbContext Read More »

ASP.NET Core 3: Add Entity Framework Core to Existing Project

Last week was an unofficial kicked off a series of posts associated with a refresh of the ASP.NET Basics repo frequently reference in this blog to reflect the state of affairs now that .NET Core 3 has been released. The new repo is ASP.NET Basics Refresh because naming is hard.

This post is going to take the API project created last week for the Swagger/OpenAPI with NSwag and ASP.NET Core 3 post and replace the generated data with a database using Entity Framework Core. If you want to follow along with this post the files before any changes can be found here.

Add NuGet Packages

Entity Framework Core is no longer included with .NET Core by default so we install a couple of NuGet packages to get started. I’m going to give the .NET CLI command, but this could also be done using the Visual Studio NuGet Package Manager UI. This post will also be using SQLite, but Entity Framework Core supports multiple databases you would need to install the package for the database you are interested in using.

Here are the commands to install the package we will be using. This is also assuming your terminal is in the same directory as the project file.

dotnet add package Microsoft.EntityFrameworkCore.Sqlite
dotnet add package Microsoft.EntityFrameworkCore.Design

Add a DbContext

Just as a reminder we already have a Contact class in the Models directory with the following definition.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, I added a Data directory to the project and then added a new class called ContactedDbContext. The DbContext only exposes one DbSet for Contacts.

public class ContactsDbContext : DbContext
{
    public DbSet<Contact> Contacts { get; set; }

    public ContactsDbContext(DbContextOptions<ContactsDbContext> options) 
        : base(options)
    { }
}

Configuration for the Connection String

In the appsettings.json file, which is where the application will pull configuration from by default, we are going to add a connection strings section to hold our default connection. The following is my full appsettings.json with the connection string for SQLite. If you are using a different database provider your connection string could be drastically different.

{
  "ConnectionStrings": {
    "DefaultConnection": "DataSource=app.db"
  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*"
}

Check out Configuration in ASP.NET Core for more details on the different ways to handle configuration.

Register DbContext with the Services Container

Open Startup.cs and in the ConfigureServices function, we are going to use the AddDbContext extension method to add our new DbContext and tell it to use SQLite with the connection string from our appsettings.json. The following is the full function with the first two lines being the ones we added.

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ContactsDbContext>(options =>
        options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));

    services.AddControllers();
    services.AddOpenApiDocument(document => 
        document.PostProcess = d => d.Info.Title = "Contacts API");
}

Check out the official doc for more information on Dependency injection in ASP.NET Core.

Create and Apply Initial Migration

For this bit, we are going to head back to the command line open to the directory that contains the csproj for the project we are working with. The first thing we need to do is to install the Entity Framework Core Tool using the following command which will install the tool globally.

dotnet tool install --global dotnet-ef

Next, we will create a migration called Initial that output in the Data/Migrations directory using the following command.

dotnet ef migrations add Initial -o Data/Migrations

Now that we have a migration lets use it to create our database. Note that the same command will be used in the future when applying migrations to an existing database.

dotnet ef database update

Check out the official docs for more information on the Entity Framework Core Tool or Global Tools in general.

Scaffold a New Controller

If you are using the code from GitHub at this point you will need to delete the ContactsController as it is going to be recreated using Visual Studio’s tooling.

Right-click on the directory where the controller should be created, the Controllers directory in the example, and select Add and then Controller.

On the dialog that pops up, we want to select API Controller with actions, using Entity Framework and then click Add.

On the next screen specify the model class, data context, and controller name before clicking Add. In the sample case, we are going to use our Contact class for the model, ContactDbContext for the data context to generate a controller named ContactController.

After clicking add the requested controller will be generated with all the functions needed for CRUD operations for the selected model class. The code for our sample controller can be found here.

Try it out

Running the application and hitting our swagger UI with the help of NSwag we can see all the options our API has available and even try them out which will now hit our application’s database.

Another great option to test out APIs which has a lot of really great features is Postman. Either option will allow you to try out your API without having to build a client.

Wrapping Up

Hopefully, this post will help you get a jump start on integrating Entity Framework Core in your ASP.NET Core 3 applications. As a reminder Entity Framework Core supports a lot of different database providers. If you have any question I recommend checking Microsoft’s official docs on Getting Started with Entity Framework Core.

The code with all the above changes can be found here.

ASP.NET Core 3: Add Entity Framework Core to Existing Project Read More »

Swagger/OpenAPI with NSwag and ASP.NET Core 3

Now that .NET Core 3 is out I thought it would be a good time to revisit exposing API documentation using Swagger/OpenAPI. In the past, I have written posts on using Swashbuckle to expose Swagger documentation, but for this post, I’m going to try out NSwag.

What is OpenAPI vs Swagger?

To quote the Swagger docs:

OpenAPI Specification (formerly Swagger Specification) is an API description format for REST APIs. An OpenAPI file allows you to describe your entire API. API specifications can be written in YAML or JSON. The format is easy to learn and readable to both humans and machines.

Swagger is a set of open-source tools built around the OpenAPI Specification that can help you design, build, document and consume REST APIs.

What is NSwag?

Quoting the NSwag GitHub readme:

NSwag is a Swagger/OpenAPI 2.0 and 3.0 toolchain for .NET, .NET Core, Web API, ASP.NET Core, TypeScript (jQuery, AngularJS, Angular 2+, Aurelia, KnockoutJS and more) and other platforms, written in C#. The OpenAPI/Swagger specification uses JSON and JSON Schema to describe a RESTful web API. The NSwag project provides tools to generate OpenAPI specifications from existing ASP.NET Web API controllers and client code from these OpenAPI specifications.

One neat thing about NSwag is it also has the tooling to help generate the API consumer side in addition to the OpenAPI specs.

Sample Project

For this post, I created a new API project via the .NET CLI using the following command. Not that all this can be done via the Visual Studio UI if that is your preference.

dotnet new webapi

For me, this project is going to be the start of a new series of posts so I also added a solution file and added the project created above to it. These commands are optional.

dotnet add sln
dotnet sln add src\ContactsApi\ContactsApi.csproj

Add NSwag

Using the CLI in the same directory as the project file use the following command to add a reference to NSwag.AspNetCore to the project.

dotnet add package NSwag.AspNetCore

Next, in your favorite editor open the project/directory we created and open the Startup.cs file. In the ConfigureServices function add services.AddOpenApiDoccument.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllers();
    services.AddOpenApiDocument();
}

Then at the end of the Configure function add calls to app.UseOpenApi and app.UseSwaggerUi3.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    if (env.IsDevelopment()) app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();
    app.UseRouting();
    app.UseAuthorization();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapControllers();
    });

    app.UseOpenApi();
    app.UseSwaggerUi3();
}

Note that NSwag also supports ReDoc if you prefer that over Swagger UI.

Sample Model and Controller

Now that we have NSwag installed let’s create a new endpoint for it to display. As per my norm, I will be doing this using contacts as an example. First I created a Models directory and then added the following Contact class to it.

public class Contact
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, in the Controllers directory add a ContactsController, which in the following code returns a list of 5 generic contacts.

[ApiController]
[Route("[controller]")]
public class ContactsController : ControllerBase
{
    private readonly ILogger<ContactsController> _logger;

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

    [HttpGet]
    public IEnumerable<Contact> Get()
    {
        return Enumerable.Range(1, 5).Select(index => new Contact
        {
            Id = index,
            Name = $"Test{index}",
            Address = $"{index} Main St.",
            City = "Nashville",
            State = "TN",
            PostalCode = "37219",
            Phone = "615-555-5555",
            Email = $"test{index}@test.com"
        });
    }
}

Results

Run your project and then in a browser navigate to your base URL /swagger. For example my for my project that is https://localhost:5001/swagger. You should see something like the following that will let you explore your API and even execute requests against your API using the Try it out button you see in the UI.

Wrapping Up

Just like with Swashbuckle, NSwag makes it very easy to get started providing API documentation. This post just covers the very basics and I’m looking forward to digging into some of the more advanced features that NSwag has such as client generation.

Microsoft has a great article on Getting Started with NSwag on their docs site that I recommend reading. This is a preview of something I plan to cover in the future, but there are attributes that can be added to controllers that help NSwag provide better details about what your API can return and Microsoft has a doc on Use web API conventions that makes it easy to apply some of the common conventions.

Swagger/OpenAPI with NSwag and ASP.NET Core 3 Read More »

Migration from ASP.NET Core 2.2 to 3.0

On September 23rd .NET Core 3.0 was released including ASP.NET Core 3.0 and Entity Framework Core 3.0. This post will be taking the Contacts project used in the ASP.NET Basics series and migrating it from .NET Core 2.2 to .NET Core 3.0. Most of the information used for this migration comes from the Microsoft docs which will cover way more scenarios than this post will.

The code before any changes can be found in this GitHub repo. A reminder that the Contacts project is the only project being updated with this post the projects in the repo will remain on ASP.NET Core 2.2 for now.

Installation

If you are a Visual Studio user you can get .NET Core 3.0 by installing at least Visual Studio 16.3. For those not using Visual Studio, you can download and install .NET Core 3.0 SDK from here. As with previous versions, the SDK is available for Windows, Linux, and Mac.

After installation is complete you can runt the following command from a command prompt to see all the versions of the .NET Core SDK you have installed.

dotnet --list-sdks

You should see 3.0.100 listed. If you are like me you might also see a few preview versions of the SDK that can be uninstalled at this point.

Project File Changes

Right-click on the project and select Edit projectName.csproj.

Change the TargetFramework to netcoreapp3.0.

Before: 
<TargetFramework>netcoreapp2.2</TargetFramework> 

After: 
<TargetFramework>netcoreapp3.0</TargetFramework>

The packages section has a lot of changes. Microsoft.AspNetCore.App is now gone and part of .NET Core without needing a specific reference. The other thing to note is that Entity Framework Core is no longer “in the box” so you will see a lot of references add to make Entity Framework Core usable.

Before:
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="2.2.0" PrivateAssets="All" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="4.0.1" />

After:
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
<PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" />
<PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" PrivateAssets="All" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />

The last thing to note is that Swashbuckle doesn’t have a final version ready for .NET Core 3 so you will have to make sure you are using version 5 rc2 at a minimum.

The following is my full project file for reference.

<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <AspNetCoreHostingModel>InProcess</AspNetCoreHostingModel>
    <UserSecretsId>aspnet-Contacts-cd2c7b27-e79c-43c7-b3ef-1ecb04374b70</UserSecretsId>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="3.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Identity.UI" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.0.0" />
    <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.0.0" PrivateAssets="All" />
    <PackageReference Include="Swashbuckle.AspNetCore" Version="5.0.0-rc4" />
  </ItemGroup>

</Project>

Program Changes

In Program.cs some changes to the way the host is constructed. The over version may or may not have worked, but I created a new app and pulled this out of it just to make sure I’m using the current set up.

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Hosting;

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

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .ConfigureWebHostDefaults(webBuilder =>
                                          {
                                              webBuilder.UseStartup<Startup>();
                                          });
    }
}

Startup Changes

In Startup.cs we have quite a few changes to make. As long as you haven’t do any customization in the constructor you can replace it with the following.

public Startup(IConfiguration configuration)
{
    Configuration = configuration;
}

Next, they type on the configuration property changed from IConfigurationRoot to IConfiguration.

Before:
public IConfigurationRoot Configuration { get; }

After:
public IConfiguration Configuration { get; }

Moving on to the ConfigureServices function has a couple of changes to make. The first is a result of updating to the newer version of the Swagger package where the Info class has been replaced with OpenApiInfo.

Before:
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1", new Info { Title = "Contacts API", Version = "v1"});
});

After:
services.AddSwaggerGen(c =>
{
    c.SwaggerDoc("v1",  new OpenApiInfo { Title = "Contacts API", Version = "v1" })
});

Next, we are going to move from using UserMvc to the new AddControllersWithViews which is one of the new more targeted ways to add just the bits of the framework you need.

Before:
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

After:
services.AddControllersWithViews();

Now in the Configure function, the function signature needs to be updated and the logging factory bits removed. If you do need to configure logging that should be handled as part of the HostBuilder.

Before:
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    loggerFactory.AddConsole(Configuration.GetSection("Logging"));
    loggerFactory.AddDebug();

After:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{

For the next set of changes, I’m just going to show the result and not the before. The UseCors may or may not apply but the addition of UserRouting and the replacement of UseMvc with UserEndpoint will if you want to use the new endpoint routing features.

app.UseStaticFiles();
app.UseRouting();

app.UseCors(builder =>
            {
                builder.AllowAnyHeader();
                builder.AllowAnyMethod();
                builder.AllowAnyOrigin();
            }
           );

app.UseAuthentication();
app.UseAuthorization();

app.UseEndpoints(endpoints =>
                 {
                     endpoints.MapControllerRoute(
                                                  name: "default",
                                                  pattern: "{controller=Home}/{action=Index}/{id?}");
                     endpoints.MapRazorPages();
                 });

Other Miscellaneous Changes

The only other change I had was the removal of @using Microsoft.AspNetCore.Http.Authentication in a few cshtml files related to login.

Wrapping Up

The migration from 2.2 to 3.0 is a bit more involved than the move from 2.1 to 2.2, but that isn’t surprising with all the changes in this release. Remember to check out the official migration guide for more details.

The code for the Contacts project after the above changes can be found on GitHub.

Migration from ASP.NET Core 2.2 to 3.0 Read More »

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 Forms and Validation Read More »

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.

Blazor Component Attributes Read More »

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.

Event Handling in Blazor Read More »

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.

Razor Components in Blazor Read More »

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.

Blazor Authentication: Hide a Nav Menu Item Read More »