ASP.NET Core

Basic ASP.NET Core API Test with Postman

I had a reader email me about using Postman with ASP.NET Core API base on this post from a couple of years ago. Rather than working through that their specific issues are with that code, I thought it might be more helpful to write a post on creating a super basic ASP.NET Core API and use Postman to test it.

API Creation

We are going to use the .NET CLI to create and run API project so no Visual Studio or other IDE will be needed. The first step is to open a command prompt and navigate to (or create) the directory where you want the API project to live. Run the following command to create the API project.

dotnet new webapi

The webapi template creates a ValuesController with a Get action that returns an array with two values in it which we will be using as our test endpoint.

After the process finished we can now run the project using the following command.

dotnet run

After the run command, you should see something like the following.

Hosting environment: Production
Content root path: C:\YourProjectPath\ApiTest
Now listening on: http://localhost:5000
Application started. Press Ctrl+C to shut down.

The key bit in the above you need to look for is the Now listening on line as that is the URL we will need to use in Postman to test.

Testing with Postman

Postman is a great tool that to use when developing an API. It allows me to exercise all the functions of the API before any clients have been built. You can do some of the same things using a browser, but Postman was built for this type of usage and it shows. Postman is free and you can grab it here.

Run Postman and you will see something similar to the following screenshot.

For our simple test we want to do a Get request, which is the default, so all we need to do is past the URL from above into the address box and add in the route to the controller we are trying to test. For our sample to test the Get action on the ValuesController our URL ends up being http://localhost:5000/api/values.

Click the Send button and the results will show the lower area Postman (the large red box in the screenshot).

Wrapping Up

This is the simplest setup I could think of to get up and going with Postman and ASP.NET Core. Postman has so many more functions than I showed in this post so I hope this will be a good jumping off point for you all to learn more about this great tool.

Basic ASP.NET Core API Test with Postman Read More »

Electron.NET: Custom Application Menus

This post will take the existing sample Electron.NET application used in Create a Desktop Application using ASP.NET Core and Electron.NET and Electron.NET with a Web API and expand it to customize the application menu. I leaned heavily on the Electron.NET API Demos repo to guide how this should be done. The code before any changes can be found here.

Menu Controller

While not a requirement I follow the API Demo example of putting the application level menus in its own controller. Add a MenusController to the Controllers directory. The following is the full class.

public class MenusController : Controller
{
    public IActionResult Index()
    {
        if (HybridSupport.IsElectronActive)
        {
            var menu = new MenuItem[] {
            new MenuItem { Label = "Edit", Submenu = new MenuItem[] {
                new MenuItem { Label = "Undo", Accelerator = "CmdOrCtrl+Z", Role = MenuRole.undo },
                new MenuItem { Label = "Redo", Accelerator = "Shift+CmdOrCtrl+Z", Role = MenuRole.redo },
                new MenuItem { Type = MenuType.separator },
                new MenuItem { Label = "Cut", Accelerator = "CmdOrCtrl+X", Role = MenuRole.cut },
                new MenuItem { Label = "Copy", Accelerator = "CmdOrCtrl+C", Role = MenuRole.copy },
                new MenuItem { Label = "Paste", Accelerator = "CmdOrCtrl+V", Role = MenuRole.paste },
                new MenuItem { Label = "Select All", Accelerator = "CmdOrCtrl+A", Role = MenuRole.selectall }
            }
            },
            new MenuItem { Label = "View", Submenu = new MenuItem[] {
                new MenuItem
                {
                    Label = "Reload",
                    Accelerator = "CmdOrCtrl+R",
                    Click = () =>
                    {
                        // on reload, start fresh and close any old
                        // open secondary windows
                        Electron.WindowManager.BrowserWindows.ToList().ForEach(browserWindow => {
                            if(browserWindow.Id != 1)
                            {
                                browserWindow.Close();
                            }
                            else
                            {
                                browserWindow.Reload();
                            }
                        });
                    }
                },
                new MenuItem
                {
                    Label = "Toggle Full Screen",
                    Accelerator = "CmdOrCtrl+F",
                    Click = async () =>
                    {
                        bool isFullScreen = await Electron.WindowManager.BrowserWindows.First().IsFullScreenAsync();
                        Electron.WindowManager.BrowserWindows.First().SetFullScreen(!isFullScreen);
                    }
                },
                new MenuItem
                {
                    Label = "Open Developer Tools",
                    Accelerator = "CmdOrCtrl+I",
                    Click = () => Electron.WindowManager.BrowserWindows.First().WebContents.OpenDevTools()
                },
                new MenuItem
                {
                    Type = MenuType.separator
                },
                new MenuItem
                {
                    Label = "App Menu Demo",
                    Click = async () => {
                        var options = new MessageBoxOptions("This demo is for the Menu section, showing how to create a clickable menu item in the application menu.");
                        options.Type = MessageBoxType.info;
                        options.Title = "Application Menu Demo";
                        await Electron.Dialog.ShowMessageBoxAsync(options);
                    }
                }
            }
            },
            new MenuItem { Label = "Window", Role = MenuRole.window, Submenu = new MenuItem[] {
                 new MenuItem { Label = "Minimize", Accelerator = "CmdOrCtrl+M", Role = MenuRole.minimize },
                 new MenuItem { Label = "Close", Accelerator = "CmdOrCtrl+W", Role = MenuRole.close }
                 }
            },
            new MenuItem { Label = "Contacts", Role = MenuRole.window, Submenu = new MenuItem[] {
                 new MenuItem { Label = "Create", 
                                Accelerator = "Shift+CmdOrCtrl+C",
                                Click = () => Electron.WindowManager.BrowserWindows.First().LoadURL($"http://localhost:{BridgeSettings.WebPort}/Contacts/Create")
                              }
                 }
            }
        };

            Electron.Menu.SetApplicationMenu(menu);
        }

        return Ok();
    }
}

What the above comes down to is building an array of MenuItem types and then using Electron.Menu.SetApplicationMenu(menu) to pass the array to Electron which handles replacing the default set of menus with the ones defined in the array.

For most of the items that were on the default set of menus all that is needed to add back the default functionality is to set the Role to the function you want. For example in the above for a Copy menu item, we can assign Role to MenuRole.copy and Electron will handle the implementation of a copy without us having to write any additional code.

Navigate to a page from the application menu

One thing I wanted to be able to do was from a menu create a new contact. It was easy enough to add a top-level menu for Contacts and a sub-item for Create. It took me a while, but I finally figured out how to build a URL that would work. The following code is the menu items for the Contacts menu.

new MenuItem { Label = "Contacts", Role = MenuRole.window, Submenu = new MenuItem[] {
     new MenuItem { Label = "Create", 
                    Accelerator = "Shift+CmdOrCtrl+C",
                    Click = () => Electron.WindowManager.BrowserWindows.First().LoadURL($"http://localhost:{BridgeSettings.WebPort}/Contacts/Create")
                  }
     }
}

The ASP.NET Core backend is running on localhost, the key that took me a while to locate was the port. In the end, I found that the port being used can be found using BridgeSettings.WebPort.

Include the menu

The final change that is needed is to make sure the new set of menus get rendered. For the sample application open the _Layout.cshtml file in the Views/Shared directory. Inside the head tag add the following line which will force a call to the MenusController when the application loads.

<link rel="import" href="menus">

Wrapping Up

Customizing the application menu ended up being pretty easy. If I hadn’t wanted to navigate to a specific page I would have been done in no time, but hitting the issue with navigation helped me learn more about how Electron.NET is working. You can check out the finished code here.

Electron.NET: Custom Application Menus Read More »

.NET CLI Errors Due to VSTS Package Source

At work, we use Visual Studio Team Services for source control, internal NuGet package management, and continuous integration. It has been a great tool that has really helped streamline our processes.

.NET CLI Issue

The problem with the setup is if the .NET CLI calls anything that uses NuGet (restore, installing new templates) with the VSTS package source enable it results in the following unauthorized error.

C:\Program Files\dotnet\sdk\2.1.103\NuGet.targets(104,5): error : Unable to load the service index for source https://company.pkgs.visualstudio.com/_packaging/feedname/nuget/v3/index.json. [project.csproj]
C:\Program Files\dotnet\sdk\2.1.103\NuGet.targets(104,5): error : Response status code does not indicate success: 401 (Unauthorized). [project.csproj]

I have been working around this by disabling the VSTS package source when working with the .NET CLI. It is a bit of a pain, but it works since I’m not using any of the packages from our private feed.

A Fix

I had the opportunity to talk to one of the VSTS product managers (PM) for the package management area and they are aware that this issue. While not the ultimate fix the PM pointed out that I could use a personal access token to get around the error.

Create a Personal Access Token

Log in to VSTS and hover over your profile picture and select security.

Next, click the add button on the Personal access tokens screen.

The next page you will need to enter a description for the token and select how long the token should be good for. It is also very important to change the Authorized Scopes off of all and only select the ones you want the token to be valid for. In my case, I selected everything package related, but Packaging (read) would be enough if you aren’t going adding packages to the feed.

At the bottom of the above screen click the Create Token button. This will take you back to the token list page with a new item for your new token and this will be your only opportunity to get a copy of the token.

Add NuGet Source with Token

Now that you have a token open up a command prompt and use the following command to add the NuGet source that will use your new personal access token.

nuget.exe sources add -name {your feed name} -source {your feed URL} -username {anything} -password {your token}

Wrapping Up

It turned out to be pretty easy fix this issue. Don’t be like me and just deal with it by disabling the package sources causing the problem. Just make sure that you don’t check-in your NuGet config file that contains your personal access token.

.NET CLI Errors Due to VSTS Package Source Read More »

Electron.NET with a Web API

This post will be expanding on the introduction to Electron.NET that I did here to add in a Web API hit to pull some data as well as the UI on the Electron side to use this data. The code before any changes can be found here.

API Creation

To create the API I used the following from the command prompt in the folder where I wanted the new project to be created.

dotnet new webapi

API Data

Now that the API project is created we need to add in the ability to interact with a database with Entity Framework Core. Adding in Entity Framework Core ended up turning into a post of its own when you can read here.

The model and DB Context of the API project match what was in the blog post I linked above, but I am going to include them here. The following is the model.

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 Subregion { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Next, is the DB Context, which is empty other than the DB Set for the contacts table.

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

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

    }
}

With our model and context setup, we can run the following two commands to add the initial migration and apply the migration to the database.

dotnet ef migrations add Contacts
dotnet ef database update

API Endpoints

The API is just going to handle the basic CRUD (create, read, update, delete) operations for contact. Instead of hand coding the controller we are going to use some code generation provided by Microsoft. First, we need to add the Microsoft.VisualStudio.Web.CodeGeneration.Design NuGet package to the API project using the following command in a command prompt set to the root of the API project.

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design

Now with the above package installed, we can use the following command to generate a controller with the CRUD operations already implemented.

dotnet aspnet-codegenerator controller -name ContactsController --model Contact --dataContext ContactsDbContext -outDir Controllers -api

There is a lot of switches when using aspnet-codegenerator. The following is a rundown of the ones used above.

  • controller tells the code generator we are creating a controller
  • name defines the name of the resulting controller
  • model is the model class that will be used for the generation
  • dataContext is the DB Context that will be used for the generation
  • outDir is the directory the output will be in relative to the current directory of your command prompt
  • api tells the code generator this controller is for a REST style API and that no views should be generated

With the code generation complete the API should be good to go.

Electron Model

Over in the Electron project, we need a model to match the data the API is returning. This could be the point where a third project is added to allow the API and the Electron app to share common items, but just to keep the example simple I’m just going add a copy of the contact model from the API project to the Electron project.  The following is the full contact model class.

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 Subregion { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Electron Views

Now that we have a model in our Electron project we need to create the views that go along with it. Start by adding the code generation package like we did above using the following command.

dotnet add package Microsoft.VisualStudio.Web.CodeGeneration.Design

Unfortunately, controller generation needs a DBContext to work which our project doesn’t have, so we have to take the long way about to generate our views and then manually create a controller to go with them. In order to get view generation to work, I had to add references to the Entity Framework Core Tools package using the following command.

dotnet add package Microsoft.EntityFrameworkCore.Tools

In the csproj file add the following .NET CLI tool reference.

<DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.2" />

Now the project is ready to use the command prompt to generate the views we will need for our CRUD operations related to our contacts. Use the following commands to create the full range of views needed (Create, Edit, List, Delete, Details).

dotnet aspnet-codegenerator view Create Create --model Contact --useDefaultLayout -outDir Views/Contacts

dotnet aspnet-codegenerator view Edit Edit --model Contact --useDefaultLayout -outDir Views/Contacts

dotnet aspnet-codegenerator view Index List --model Contact --useDefaultLayout -outDir Views/Contacts

dotnet aspnet-codegenerator view Delete Delete --model Contact --useDefaultLayout -outDir Views/Contacts

dotnet aspnet-codegenerator view Details Details --model Contact --useDefaultLayout -outDir Views/Contacts

Again there is a lot of switches when using aspnet-codegenerator. The following is a rundown of the ones used above.

  • view  tells the code generator we are creating a view
  • the next two items are the name of the view and the name of the view template
  • model is the model class that will be used for the generation
  • useDefaultLayout uses the default layout (surprise!)
  • outDir is the directory the output will be in relative to the current directory of your command prompt

The Index.cshtml generated above comes with links for Edit, Details, and Delete that won’t work as generated. Open the file and make the following changes to pass the key of the contact trying to be opened.

Before:
@Html.ActionLink("Edit", "Edit", new { /* id=item.PrimaryKey */ }) |
@Html.ActionLink("Details", "Details", new {/* id=item.PrimaryKey */ }) |
@Html.ActionLink("Delete", "Delete", new { /* id=item.PrimaryKey */ })

After:
@Html.ActionLink("Edit", "Edit", new {  id=item.Id }) |
@Html.ActionLink("Details", "Details", new { id=item.Id }) |
@Html.ActionLink("Delete", "Delete", new { id=item.Id })

Electron Controller

With the views complete let’s add a ContactsController.cs to the Controllers directory. The code for the controller follows, but I’m not going to go into the details. I took a controller from another contact base project and just replaces all the Entity Framework stuff with calls to the API we created above. Please don’t use this as an example of how something like this should be done it is just quick and dirty to show that it can work.

public class ContactsController : Controller
{
    private string _apiBaseUrl = "http://localhost:5000/api/contacts/";

    // GET: Contacts
    public async Task<IActionResult> Index()
    {
        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            return View(JsonConvert.DeserializeObject<List<Contact>>(await (await client.GetAsync("")).Content.ReadAsStringAsync()));
        }
    }

    // GET: Contacts/Details/5
    public async Task<IActionResult> Details(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            var contact = JsonConvert.DeserializeObject<Contact>(await (await client.GetAsync(id.ToString())).Content.ReadAsStringAsync());

            if (contact == null)
            {
                return NotFound();
            }

            return View(contact);
        }
    }

    // GET: Contacts/Create
    public IActionResult Create()
    {
        return View();
    }

    // POST: Contacts/Create
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Create([Bind("Id,Address,City,Email,Name,Phone,PostalCode,State")] Contact contact)
    {
        if (ModelState.IsValid)
        {
            using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
            {
                await client.PostAsync("", new StringContent(JsonConvert.SerializeObject(contact), Encoding.UTF8, "application/json"));
            }

            return RedirectToAction("Index");
        }
        return View(contact);
    }

    // GET: Contacts/Edit/5
    public async Task<IActionResult> Edit(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            var contact = JsonConvert.DeserializeObject<Contact>(await (await client.GetAsync(id.ToString())).Content.ReadAsStringAsync());

            if (contact == null)
            {
                return NotFound();
            }

            return View(contact);
        }
    }

    // POST: Contacts/Edit/5
    [HttpPost]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> Edit(int id, [Bind("Id,Address,City,Email,Name,Phone,PostalCode,State")] Contact contact)
    {
        if (id != contact.Id)
        {
            return NotFound();
        }

        if (ModelState.IsValid)
        {
            using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
            {
                await client.PutAsync(id.ToString(), new StringContent(JsonConvert.SerializeObject(contact), Encoding.UTF8, "application/json"));
            }
            return RedirectToAction("Index");
        }
        return View(contact);
    }

    // GET: Contacts/Delete/5
    public async Task<IActionResult> Delete(int? id)
    {
        if (id == null)
        {
            return NotFound();
        }

        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            var contact = JsonConvert.DeserializeObject<Contact>(await (await client.GetAsync(id.ToString())).Content.ReadAsStringAsync());

            if (contact == null)
            {
                return NotFound();
            }

            return View(contact);
        }

    }

    // POST: Contacts/Delete/5
    [HttpPost, ActionName("Delete")]
    [ValidateAntiForgeryToken]
    public async Task<IActionResult> DeleteConfirmed(int id)
    {
        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            await client.DeleteAsync(id.ToString());
            return RedirectToAction("Index");
        }
    }

    private async Task<bool> ContactExists(int id)
    {
        using (var client = new HttpClient { BaseAddress = new Uri(_apiBaseUrl) })
        {
            return JsonConvert.DeserializeObject<Contact>(await (await client.GetAsync("id")).Content.ReadAsStringAsync()) != null;
        }
    }
}

Electron Add Link To Navigation

The final step to add a link to the list of contacts to the navigation bar of the application. Open the _Layout.cshtml and in the unordered list for the nav bar add the following line.

<li><a asp-area="" asp-controller="Contacts" asp-action="Index">Contacts</a></li>

Wrapping Up

That is all the changes to get the application up and running. If you run the API and then use dotnet electronize start from a command prompt in the ElectronTest project root all should be good to go.

The completed code can be found here.

Electron.NET with a Web API Read More »

Add Entity Framework Core to an Existing ASP.NET Core Project

I had a Web API application that I was using to test something that had no database interaction at all that I needed to add database interaction too. Going through my posts I didn’t find a guide to add Entity Framework Core to an existing project, so that is what this post is going to cover. We will be using SQLite for our database.

Project Creation

The project we are starting with is just a new ASP.NET Core Web API created using the .NET CLI using the following command from a command prompt.

dotnet new webapi

This gives us a new Web API with no database interaction and makes sure we are all on the same page for the rest of the post.

Project File Changes

Open the csproj file associated with your project. First, we need to add a package reference to the Entity Framework Core tools.

Before:
<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
</ItemGroup>

After:
<ItemGroup>
  <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.5" />
  <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.1" PrivateAssets="All" />
</ItemGroup>

Next, we need to add a reference to the Entity Framework Core Tools for the .NET CLI.

Before:
<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
</ItemGroup>

After:
<ItemGroup>
  <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
  <DotNetCliToolReference Include="Microsoft.EntityFrameworkCore.Tools.DotNet" Version="2.0.1" />
</ItemGroup>

The final change to the project file is only needed if you are using SQLite and it is to keep the database file from showing up in the file list. Add the following and adjust app.db to match your database name.

<ItemGroup>
  <None Update="app.db" CopyToOutputDirectory="PreserveNewest" />
</ItemGroup>

App Settings

Now we need to store the database connection string. Again we are using SQLite in this example so if you are trying to use SQL Server (include LocalDb) your connection string will look much different. This is also a place where you need to replace app.db with the database name you want to use.

Open the appsettings.json file and add a ConnectionStrings section similar to the following.

"ConnectionStrings": {
  "DefaultConnection": "DataSource=app.db"
}

The following is my full settings file after the change just to make sure the context is clear.

{
  "ConnectionStrings": {
    "DefaultConnection": "DataSource=app.db"
  },
  "Logging": {
    "IncludeScopes": false,
    "Debug": {
      "LogLevel": {
        "Default": "Warning"
      }
    },
    "Console": {
      "LogLevel": {
        "Default": "Warning"
      }
    }
  }
}

Model and Db Context

If you are a long time reader it will be no surprise that the model we will be using is that of a contact. The following is my full contact model.

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 Subregion { get; set; }
    public string PostalCode { get; set; }
    public string Phone { get; set; }
    public string Email { get; set; }
}

Now that we have a model we need to add a DBContext.

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

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

    }
}

Startup

Now that we have the application settings, model, and context from above open up the Startup class and in the ConfigureServices function add the following code to get the ContactsDbContext into the container.

services.AddDbContext<ContactsDbContext>(options => 
    options.UseSqlite(Configuration.GetConnectionString("DefaultConnection")));

Initial Migration

Now that the project is all set to go let’s add an initial migration that will get the table for our contacts set up. From a command prompt in the project directory run the following command.

dotnet ef migrations add Contacts

This will add a Migrations directory to the project with the code needed to add the contacts table. If you want to go ahead and apply the migration to the database run the following command.

dotnet ef database update

Since we didn’t have a database yet the above command creates one which will show up in the root of our project with a name that matches our application settings since we are using SQLite.

Wrapping Up

Adding Entity Framework Core to a project is pretty easy, but not something I do a lot, so this will serve as a good reminder of the steps. Hope it helps you out as well.

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

Create a Desktop Application using ASP.NET Core and Electron.NET

Electron is a cross-platform (Windows, Linux, and Mac) library for building desktop applications using JavaScript, HTML, and CSS. Even if you have never head of Electron I’m sure you have used some of the desktop applications it has been used to build such as Visual Studio Code, Atom, Slack.

Electron.NET provides a wrapper around Electron with an ASP.NET Core MVC application in the mix. Here is the reason why this was done from the creates of the project.

Well… there are lots of different approaches how to get a X-plat desktop app running. We thought it would be nice for .NET devs to use the ASP.NET Core environment and just embed it inside a pretty robust X-plat enviroment called Electron. Porting Electron to .NET is not a goal of this project, at least we don’t have any clue how to do it. We just combine ASP.NET Core & Electron.

Project Creation

Seems only fitting to use VS Code for this post since it is built using the same base library. From the command line create a new ASP.NET Core MVC application using the following command.

dotnet new mvc

Make note that it is important at this time that you use the MVC template when attempting this and not a Razor Page application. This is more of a warning if you are using Visual Studio to do your project creation and not the CLI command above.

Next, we need to reference the ElectronNET.API NuGet package which can be added using the following command.

dotnet add package ElectronNet.API

Then, open the csproj and add a reference for the Electron.NET CLI tool which should match the following.

<ItemGroup>
     <DotNetCliToolReference Include="ElectronNET.CLI" Version="0.0.9" />
</ItemGroup>

After that make sure and restore packages using the following command.

dotnet restore

Wire-up Election.NET

Open Program.cs and add UseElectron(args) to the WebHost builder chain.

WebHost.CreateDefaultBuilder(args)
    .UseElectron(args)
    .UseStartup<Startup>()
    .Build();

Net, open Startup.cs and add the following line to the bottom of the Configure function. This is what will open the Electron window on startup.

Task.Run(async () => await Electron.WindowManager.CreateWindowAsync());

Finally, run the following from the command prompt to get the project ready to run under Electron. This should only need to be done once.

dotnet electronize init

Run the application

At this point, the application is ready to go. The neat part is you can just hit F5 and it will run like any normal ASP.NET Core application (this would change when you get into Electron specific calls I’m sure) or if you run the following command it will run inside of the Electron shell.

dotnet electronize start

Wrapping up

It was surprisingly simple to get a new application up and running, of course so far the app isn’t anything other than a web site hosted in Electron. My plan is to take this base application and create my normal basic contacts application, which will be the next post. From there I may look into layering in some Electron features.

The completed code can be found here.

Create a Desktop Application using ASP.NET Core and Electron.NET Read More »

Two-factor Authentication in ASP.NET Core 2

This post was going to be an update of the SMS using Twilio Rest API in ASP.NET Core post a made a year or so ago, but once I got the example project created I noticed that the default template has removed SMS as an option for two-factor authentication in favor of authenticator auth support.

This post is going to explore the setup of this new two-factor authentication style. In a follow-up post, I may look at adding back support for SMS as the second factor as that seems like a more common scenario albeit a less secure one.

Project Setup

To create a new Razor Pages application using individual authentication I used the following command from a command prompt. Make sure you are in the directory you want the files to end up. The only reason I mention this is I just spend the last 5 minutes cleaning up my user directory because I forgot to change directories.

dotnet new razor --auth Individual

Next, I move up a directory and used the following command to add a new solution file.

dotnet new sln -n TwoFactorAuth

Finally, I used the following command to add the new project to the solution file. If you aren’t using Visual Studio then you don’t have to have the solution file.

dotnet sln add TwoFactorAuth\TwoFactorAuth.csproj

The project after the above can be found here.

Add a QR Code

Strictly speaking, a QR code isn’t required, but it is much better for users so they don’t have to enter a 32 character key into their authenticator application manually. I followed the official docs to enable QR code generation.

The first step is to download a Javascript QR Code library. I just used the one recommended in the docs, but any would work. This link will take you to a zip download. Open the download and copy qrcode.js and qrcode.min.js into a new qrcode directory inside of your project’s wwwroot/lib/ directory.

Next, find your project’s EnableAuthenticator.cshtml file and update the scripts section at the bottom of the page to the following.

@section Scripts {
    @await Html.PartialAsync("_ValidationScriptsPartial")
    
    <script type="text/javascript" src="~/lib/qrcode/qrcode.js"></script>
    <script type="text/javascript">
        new QRCode(document.getElementById("qrCode"),
            {
                text: "@Html.Raw(Model.AuthenticatorUri)",
                width: 150,
                height: 150
            });
    </script>

Enabling Two-Factor Authentication

The above changes are all that is required, and now we are going to walk through what it looks like for the user. Once logged in click on your user in in the upper right after of the site to open user management.

Next, click the Two-factor authentication link.

Then, click Configure authenticator app link.

This will land you on the page with the QR code.

Now using the authenticator application of your choice you can scan the QR code. Once scanned your authenticator application will display a code. Enter the code in the Verification Code box and click Verify. If all goes well you will be taken to a page that lists a set of recovery code for use if you can’t use your authenticator application for some reason.

Wrapping Up

I think it is awesome how easy the ASP.NET Core team has made the use two-factor authentication. With this being built into the templates it pushes all in the right direction. I do wish they would have left SMS as an option, but hopefully, it wouldn’t be hard to put back in.

The code in the final state can be found here.

Two-factor Authentication in ASP.NET Core 2 Read More »

ASP.NET Core 2 Fails to Publish With Angular 5

I had an issue opened on my Identity Server GitHub repo saying that publishing the client application fails with something like the following error when using server-side rendering.

Can’t resolve ‘./../$$_gendir/ClientApp/app/app.module.browser.ngfactory’

This was only an issue after moving the project to target Angular 5. After some research, it turns out that Angular tools for Webpack has to use a different plugin for ahead of time compiling for Angular 5+. I ended up finding a fix in this issue.

The Fix

In order to resolve the issue, I made the following changes in the webpack.config.js file. The first change is in the require statements at the top of the file.

Before:
const AotPlugin = require('@ngtools/webpack').AotPlugin;

After:
const AngularCompilerPlugin = require('@ngtools/webpack').AngularCompilerPlugin;

Next, make the following replacement in the rest of the file, which should only be two places.

Before:
new AotPlugin

After:
new AngularCompilerPlugin

Wrapping Up

Most of the projects I reference on this blog are written to specifically target the topic I am trying to cover and as such I miss things like testing publish since I’m never going to production with these applications. I really appreciate those of you who find issues and take the time to open an issue on GitHub. Keep them coming, and if you find a solution before I do feel free to submit a pull request.

 

ASP.NET Core 2 Fails to Publish With Angular 5 Read More »

Entity Framework Core with Postgres

With last week’s post, I now have Postgres running in a Docker container. This post is going to cover using Entity Framework Core with Postgres which will happen to be running in the Docker container from last week, but that bit isn’t a requirement for this post. This post is going to be very similar to this one which covered Entity Framework Core with SQLite.

Starting Point

Using Visual Studio 2017 I started with a new ASP.NET Core project using the Web Application template with Individual User Accounts for Authentication. Using Individual User Accounts is an easy way to get all the Entity Framework Core stuff setup.

Add Postgres Nuget Package

Right-click on the project file and click Manage NuGet Packages.

On the Browse tab search for Npgsql.EntityFrameworkCore.PostgreSQL and then click install.

Configuration Changes

Open the appsettings.json file and change the DefaultConnection in the ConnectionString section to a valid Postgres connection string as in the following example.

Before:
"ConnectionStrings": {
  "DefaultConnection": "Server=(localdb)\\mssqllocaldb;Database=aspnet-Postgres-53bc9b9d-9d6a-45d4-8429-2a2761773502;Trusted_Connection=True;MultipleActiveResultSets=true"
}

After:
"ConnectionStrings": {
  "DefaultConnection": "Server=localhost;Database=aspnet-Postgres-53bc9b9d-9d6a-45d4-8429-2a2761773502;UserId=yourUserName;Password=yourPassword"
}

Not that a user ID and password are needed. If you are going to be checking your project into source control I recommend in addition to the above you only store the connection string with the real user ID and password in user secrets which don’t get checked into source control. You can find more information on user secrets here.

Startup Changes

The final change needed before running the application is in the ConfigureServices function of the Startup class to switch out SQL Server for Postgres. The following shows an example of the change for the ApplicationDbContext.

Before:
services.AddDbContext<ApplicationDbContext>(options =>
    options
      .UseSqlServer(Configuration
                    .GetConnectionString("DefaultConnection")));

After:
services.AddDbContext<ApplicationDbContext>(options =>
    options
      .UseNpgsql(Configuration
                 .GetConnectionString("DefaultConnection")));

Run the App

Running the application at this point will work fine until you hit a function that wants to talk to the database. For example, attempting to register a user would result in the following error.

If you see this error don’t panic just follow the instructions and they will get you going. The simplest solution is to just click the blue Apply Migrations button and continue your testing.

Wrapping Up

The application is now ready to go using Postgres. The Entity Framework Core team, as well as the Postgres Entity Framework Core Provider team, have done a great job making everything work with no pain.

The official docs for the provider can be found here. I would love to offer some tooling recommendations for working with Postgres, but I haven’t been working with it enough yet to provide any. If you have any Postgres tools you recommend please leave a comment.

The code in its final state, which has been expanded to include my standard contacts example, can be found here.

Entity Framework Core with Postgres Read More »

Trying the New ASP.NET Core Angular Template with CLI Support

I got hit by the flu that has been going around and now that the fever has passed I thought it would be a good time to try out the new version of the Angular template for ASP.NET Core that works well with the Angular CLI.

Template Installation

Note that at the time of this writing the templates are in the release candidate stage and a new version could be available by the time you are reading this so make sure and check this page for potential updates.

Running the following command from a command prompt will install the RC version of the templates.

dotnet new --install Microsoft.DotNet.Web.Spa.ProjectTemplates::2.0.0-rc1-final

Project Creation

Create a directory for the project and navigate to it in a command prompt. Run the following command to create the new Angular project.

dotnet new angular

Next, if you have a solution you want to add the new project to that can be done with the following command adjusting for the naming of your project and solution.

dotnet sln "ASP.NET Core Basics.sln" add src\AngularWithCli\AngularWithCli.csproj

Installation of Angular CLI

From the command prompt run the following command to install the Angular CLI globally.

npm install -g @angular/cli

After the above, I got the following error trying to run any Angular CLI commands.

You seem to not be depending on “@angular/core”. This is an error.

The problem ended up being that I had not installed all the packages for the project. The issue was cleared up by the following command.

npm install

Angular CLI Usage

Navigate to the ClientApp directory and you can then use all the Angular CLI commands as you would in a stand along Angular application. Some of which can be found here. If you are looking for a quick command to verify all is work the following command works well by running a linter on your project.

ng lint

Wrapping Up

Having templates that are compatible with the Angular and React CLI is a big step forward. The CLIs provide a lot of functionality and by having a setup that doesn’t restrict their usages is a great move. Make note that server-side rendering is no longer enabled by default, but can still be enabled for Angular projects, but not React based projects.

I recommend you check out the official documentation which can be found here.

I hope we see these functionality moves to the other templates that are outside of the templates in this package in order to support Aurelia and Vue.

Trying the New ASP.NET Core Angular Template with CLI Support Read More »