.NET Core

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 »

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.

Azure App Service with On-premises Connection Read More »

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.

Publish a .NET Core Worker Service to Azure Read More »

.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.

.NET Core Worker Service 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 »