ASP.NET Core

ASP.NET Core 2.1: ActionResult

This post is going to take the Contacts API from my ASP.NET Basics set of posts and move it from using IActionResultto ActionResult<T> which was introduced with the 2.1 release. The changes are really simple, but if you are using OpenAPI/Swagger I have a call out later in the post about something I noticed. The code before any changes can be found here.

IActionResult vs ActionResult<T>

The official docs explain the three different ways to return data in an API which are a specific type, IActionResult type, or ActionResult<T> type.

A specific type is great if you don’t have to do any sort of validation or the like, but as soon as you need to return a different HTTP status than OK is no longer sufficient. This is where you would have to move to IActionResult.

IActionResult allows different HTTP statuses to be returned. In the following example, NotFound is returned if a contact with the supplied ID isn’t found or OK(contact) if a contact is found.

public async Task<IActionResult> GetContact([FromRoute] int id)
{
     var contact = await _context.Contact
                                 .SingleOrDefaultAsync(m => m.Id == id);

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

The advantage of ActionResult<T> it is the return type of the function is clear. You can see in the following example where GetContact has been changed to use ActionResult<T> that if all goes well you will be dealing with a Contact object in the end without the need to wrap the result in an OK.

public async Task<ActionResult<Contact>> GetContact([FromRoute] int id)
{
     var contact = await _context.Contact
                             .SingleOrDefaultAsync(m => m.Id == id);

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

    return contact;
}

OpenAPI/Swagger

If you are using OpenAPI/Swagger in your project with a function with the following definition it will automatically pick up the return type if you switch to using ActionResult<T>.

public async Task<ActionResult<Contact>> GetContact([FromRoute] int id)

The above function results in the following in OpenAPI/Swagger UI.

This is awesome and saves you from having to ProducesResponseType attributes to your API functions. Just note that as soon as you do add a ProducesResponseType for say a NotFound response you will still need include a response for OK with the proper type or you will lose the return type in the OpenAPI/Swagger UI.

I’m calling that last bit out because I spent time trying to figure out why all the samples I saw the return type was automatically picked up, but in my sample application it wasn’t.

Wrapping Up

I’m a huge fan of ActionResult<T> mostly because of the clarity it adds to API function definitions. The fact that OpenAPI/Swagger can pick up on it in the simple cases is an added bonus.

If you are looking for more info check out the Exploring ActionResult<T> in ASP.NET Core 2.1 post by Joonas Westlin in which there is more info on how the functionality is actually implemented. If you didn’t already make sure and check out the Controller action return types in ASP.NET Core Web API page in the official docs for a detailed comparison of the return type options for APIs.

The completed code can be found here.

ASP.NET Core 2.1: ActionResult Read More »

Host ASP.NET Core Application as a Windows Service

.NET Core 2.1 had a ton of cool stuff in it. David Fowler did a bunch of tweets a while back on some of the hidden gems in this release and one that really jumped out at me was the ability to host an ASP.NET Core application in a Windows Service. This post is going to walk through creating a new ASP.NET Core application and then making the changes needed for it to run as a Windows Service. I pulled most of the information I needed from the official docs.

Project Creation

We will be using the .NET CLI to create the project, but you can also use Visual Studio if you like. Open a command prompt in the directory where you want the project created and run the following commands.

dotnet new razor --no-https
dotnet new sln
dotnet sln add WindowsServiceHosted.csproj

Open the new solution in Visual Studio.

Project File Changes

Right click on your project field and select Edit.

The first step is to add a runtime identifier. The docs are using win7-x64 so we are going to use the same. I did try using win and win7 but they don’t work since there isn’t a specific runtime associated with them. In this same step, we are going to add a reference to the Microsoft.AspNetCore.Hosting.WindowServices NuGet package.

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
  </ItemGroup>

</Project>

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

  <PropertyGroup>
    <TargetFramework>netcoreapp2.1</TargetFramework>
    <RuntimeIdentifier>win7-x64</RuntimeIdentifier>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.App" />
    <PackageReference Include="Microsoft.AspNetCore.Hosting.WindowsServices" Version="2.1.1" />
  </ItemGroup>

</Project>

Program Class Changes

Open the Program project’s  class. In the Main function, Run call on the Web Host needs to change to RunAsService.

Before:
CreateWebHostBuilder(args).Build().Run();

After:
CreateWebHostBuilder(args).Build().RunAsService();

Next, in the CreateWebHostBuilder function, we need to change the content root to be the directory of the application. We are using the Process class to pull the filename and using that to get the directory the process is running in.

Before:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

After:
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseContentRoot(Path
                        .GetDirectoryName(Process
                                          .GetCurrentProcess()
                                          .MainModule
                                          .FileName))
        .UseStartup<Startup>();

Publish

In the pre-core versions this step could have been skipped, but for .NET Core the only way to get an actual exe out of your project that can be installed is to publish the application. You can either use the .NET CLI or Visual Studio to publish the application. I’m going to use the following .NET CLI command run from the same directory as the project file.

dotnet publish

Since I didn’t specify a configuration value the project was built in debug and ended up in the bin\Debug\netcoreapp2.1\win7-x64\publish directory.

Installation

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:\WindowsServiceHosted\bin\Debug\netcoreapp2.1\win7-x64\publish\WindowsServiceHosted.exe"

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

Service Management

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

sc start WindowsServiceHosted

After the service is started you can open a browser and go to http://localhost:5000/ and see your application running.

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

sc query WindowsServiceHosted

To stop your service use the following command.

sc stop WindowsServiceHosted

Finally, to uninstall your service use the following command.

sc delete WindowsServiceHosted

Debugging

While debugging a Windows Service can be done, it is a pain. Thankfully the docs walk us through away to run the application normally if it is run in debug mode, but this does require more changes in the Program class.

First, change the CreateWebHostBuilder back to its original state.

public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
    WebHost.CreateDefaultBuilder(args)
        .UseStartup<Startup>();

Next, in the Main function, we have to decide if we are running as a service or not and if so switch around how we start the application.

public static void Main(string[] args)
{
    var runAsService = !Debugger.IsAttached;
    var builder = CreateWebHostBuilder(args);

    if (runAsService)
    {
        builder.UseContentRoot(Path
                               .GetDirectoryName(Process
                                                 .GetCurrentProcess()
                                                 .MainModule.FileName));
    }

    var host = builder.Build();

    if (runAsService)
    {
        host.RunAsService();
    }
    else
    {
        host.Run();
    }
}

For this example, we are going to run as a service only if the debugger isn’t attached. You can see how the rest of the codes is using this runAsService boolean to change between the setup needed for a service and that of a normal web application host.

Wrapping Up

I’m very happy to have the ability to host an ASP.NET Core application as a Window Service. This seems to be a case I run into a lot more that one would think.

I hope to see things that simplify Windows Services like Topshelf add support for .NET Core 2.1 (this issue has links to all the issues related to 2.1 if you want to check on the progress). It will be nice to have .NET Core Windows Services with the same level of support and the previous version of .NET.

Host ASP.NET Core Application as a Windows Service Read More »

ASP.NET Core Basics: Blazor

Blazor is a single page application framework that uses .NET running in the browser through the magic of WebAssembly and Mono. Check out How Blazor runs .NET in the browser for more information. You can think of Blazor like you do Angular or React, but written in .NET.

Please make note that this project is still an unsupported experiment and shouldn’t be used for production applications. This is part of the reason I held off on trying it until now.

I will be adding the Blazor project to my ASP.NET Core Basics repo. The code before any changes can be found here.

Getting Started

For an experiment, Blazor already has some really good docs. A lot of this post is going to mirror the Get started with Blazor docs page, but I try and document as I go. First, make sure you have the latest version of .NET Core 2.1.x SDK installed.

If you are going to be using Visual Studio you will need at least version 15.7. In addition, you will need to install the Blazor Language Services extension. From within Visual Studio, this can be done from the Tools > Extension and Updates menu. Select Online and search for Blazor. It should come up with just one item and you can click Download to start the install process.

Project Creation

We are going to use the .NET CLI to install the Blazor templates and add the resulting project to the ASP.NET Core Basics solution. First, open a command prompt and use the following command to get the Blazor template installed.

dotnet new -i Microsoft.AspNetCore.Blazor.Templates

If you are using the sample code I am running the commands from a new Blazor directory in the existing src directory. Then run the following command to create the Blazor project.

dotnet new blazor

The next command will add the new project to the existing solution. The path to the solution file isn’t required if the command is being run from the same directory as the solution file, but in our case, we are running the commands two level down from where the solution file is located.

dotnet sln "../../ASP.NET Core Basics.sln" add Blazor.csproj

At this point, you can use the following command to run the application.

dotnet run

Adding the Contact List

As with the other post in the ASP.NET Basics category, we are going to add a contact list page that pulls a list of contacts from an API. For this example, the API is part of the Contacts project that already exists in the sample solution. All the changes in the section take place in the Blazor project we created above.

In the Pages directory add a ContactList.cshtml file with the following contents. A break down of some of the parts of this file will follow.

@page "/contacts"
@inject HttpClient Http

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    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; }
    }
}

This has a lot going on so we are going to start with the functions section which is essentially a way to block off code needed by the page. It can contain functions, classes, or whatever else C# construct the page may need. The following is just the functions section of the above page.

@functions {
    Contact[] contacts;

    protected override async Task OnInitAsync()
    {
        contacts = await Http.GetJsonAsync<Contact[]>("http://localhost:13322/api/contactsApi/");
    }

    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; }
    }
}

In our sample, we are using the functions to define a Contact class to hold the data we get back from the API call in the OnInitAsync function. The OnInitAsync function is one of the lifecycle functions provided by the Blazor components. We aren’t going to dive into components, I recommend you check out the component docs for more information.

The @page "/contacts" is defining the route that the page will be served for. Next, @inject HttpClient Http is showing how to use ASP.NET Core’s dependency injection to get an instance of an HttpClient.

The remaining bit of the file is normal Razor. Everything defined in the functions section is available for use in your layout. For example, we are using the list of contacts filled by the OnInitAsync to loop and create a table to display our contact list.

<h1>Contact List</h1>

@if (contacts == null)
{
    <p><em>Loading...</em></p>
}
else
{
    <table class="table">
        <thead>
            <tr>
                <th>ID</th>
                <th>Name</th>
            </tr>
        </thead>
        <tbody>
            @foreach (var contact in contacts)
            {
                <tr>
                    <td>@contact.Id</td>
                    <td>@contact.Name</td>
                </tr>
            }
        </tbody>
    </table>
}

Wrapping Up

Blazor is a very interesting concept. I hope it is able to make it through the experimental phase into a supported project. It seems like it would be a great option for .NET developers. It was a lot of fun to finally try out. Go give it a try and make sure and provide feedback to Microsoft so they can make an informed decision on how to proceed with the project.

The finished code can be found here.

ASP.NET Core Basics: Blazor Read More »

Deploying an ASP.NET Core Application to DigitalOcean

This is the fourth post in a series on deploying a very simple ASP.NET Core application different cloud provides. This post is going to be dealing with setup and deployment to DigitalOcean.

Google Cloud Platform
Amazon Web Services
Microsoft Azure
DigitalOcean (this post)

Sample Application

The sample application ended up becoming its own blog post since it looks like the easiest deployment to DigitalOcean for .NET is going to be using Docker. Check out my Adding Docker to an ASP.NET Core Application post to get your application setup with Docker and published to a registry.

DigitalOcean

Head over to DigitalOcean and sign up for an account. Using that link will get you $10 in free credit (I will get some credit too if you spend $25 or more, but the main point is to get you some credit to get started with).

As part of the sign-up process, you will have to enter a credit card. It won’t be charged as long as you don’t go over your free credit.

After you finish the sign-up process you will be dropped on the dashboard for your account. Click the Create Droplet button to get started.

On the next page select One-click apps, and then the Docker option.

Scroll down and select your Droplet size. Since this is a basic example and will never have any real traffic I went with the cheapest option which is $5 a month.

There are a lot of options, but with the two selections above we can take the defaults are the rest of them for this sample. Scroll all the way down and click the Create button.

This will drop you back to your Dashboard and you will have your new Droplet listed. Click on the name of the Droplet to get to its details.

There is a lot of information on this page, but the thing we are interested in is the Console link in the top right of the summary.

A new browser window should open with a console that is running on your Droplet.

If you are like me and took the defaults when creating your Droplet then you will have gotten an email from DigitalOcean with the username and password you can use to log in. You will be forced to change your password on your first log in.

Installing the sample application

Now that our Droplet is up and we are logged in it is time to get our application up and running. All of this section is going to be happening in the console of the Droplet. First, use the following command to log in with Docker.

docker login

Next, we need to pull the image for our application (your image name will be different).

docker pull elanderson/testrepository

The following command can then be used to run the application. -p 80:80 in the command is binding port 80 from the container to port 80 on the host. Hopefully, if you took the defaults on everything this will just work for you, but if not you will tweak this part of the command.

docker run -p 80:80 elanderson/testrepository

Wrapping Up

There were some details to work out, but after getting over those humps Docker is amazing. This post was about DigitalOcean, but I could take the image used in this post and deploy it to any Linux image that supports ASP.NET Core and Docker. Hopefully, I will find an excuse to play around more with Docker soon.

Deploying an ASP.NET Core Application to DigitalOcean Read More »

Adding Docker to an ASP.NET Core Application

I have a series of post about deploying an ASP.NET Core application to different cloud providers which centered around clouds that provided a service that supported ASP.NET Core. The following are all the post in that vein if you are interested.

Google Cloud Platform
Amazon Web Services
Microsoft Azure

I was asked if I was going to do a post on deployment to DigitalOcean. While not in my original plan it was a good idea. The thing is DigitalOcean doesn’t have a service to support ASP.NET Core, but they do support Docker so this post is going to cover adding Docker support to a sample ASP.NET Core application. Look for a future post on how to deploy to DigitalOcean.

Docker

What is Docker? To quote Wikipedia:

Docker is a computer program that performs operating-system-level virtualization also known as containerization. It was first released in 2013 and is developed by Docker, Inc.

Docker is used to run software packages called “containers”. In a typical example use case, one container runs a web server and web application, while a second container runs a database server that is used by the web application. Containers are isolated from each other and use their own set of tools and libraries; they can communicate through well-defined channels. All containers use the same kernel and are therefore more lightweight than virtual machines. Containers are created from “images” which specify their precise contents. Images are often created by combining and modifying standard images downloaded from repositories.

Installing Docker

Head to this link and click the Get Docker link to download the installer. After the install is complete you will have to log out and back in. When I logged back in I got a message about Hyper-V not being enabled.

After logging back in I then got the following message about hardware-assisted virtualization not being enabled.

After tweaking my BIOS settings and logging back in I was greeted by the Docker welcome screen.

Open a command prompt and run the following command.

docker run hello-world

You should output that starts with the following if your installation is working.

Hello from Docker!
This message shows that your installation appears to be working correctly.

Sample Application

This is the same as in the cloud series, but am including it in case you missed that post. The sample application that we will be deploying is the basic Razor Pages applications created using the .NET CLI. The following commands are what I used to create the application, create a solution, and add the project to the solution. I ran all these commands in a CloudSample directory.

dotnet new razor --no-https
dotnet new sln
dotnet sln add CloudSample.csproj

Add Docker Support

Open the solution created above in Visual Studio and right-click the project and select Add > Docker Support.

Next, you will have the select the OS you want to target.

This will add the following four files to your project.

docker-compose.dcproj
docker-compose.override.yml
docker-compose.yml
Dockerfile

The process will also change your project to start in Docker when you hit run from in Visual Studio.

Publishing

In order to publish we need an account with a registry that we want to publish to. There are multiple options, but I am going to be using Docker Hub. Go to Docker Hub and sign up for an account. After you get signed in on your Repositories tab click Create Repository.

On the next page enter a name for your repository, select if you want it to be private or public and click Create. I’m using the name TestRepository and making it private.

Now that we have a Docker Hub account hope back to Visual Studio and right-click on your project and select Publish.

On the next on the dialog select the Container Registry option and then Docker Hub. Then click the Publish button.

On the next dialog enter your username and password for Docker Hub and click Save.

After saving Visual Studio will build and publish the application to Docker Hub.

Issues

If you get luck the above will work for you. I hit a couple of issues that made the above fail for some reason. The following is the first error I got.

Error: Service ‘cloudsample’ failed to build: The command ‘/bin/sh -c dotnet restore /CloudSample.csproj’ returned a non-zero code: 1

After some digging, I found this GitHub issue. The gist of the fix is to change the following in the DockerFile.

Before:
RUN dotnet restore /CloudSample.csproj

After:
RUN dotnet restore -nowarn:msb3202,nu1503 -p:RestoreUseSkipNonexistentTargets=false

The above fixed the build when in release mode, but publish still failed on me with the following error when the tools were attempting to tag the image.

System.Exception: Running the docker.exe tag command failed.
at Microsoft.VisualStudio.Web.Azure.Publish.ContainerRegistryProfileVisual.DockerTag(ProcessStartInfo startInfo, String serverUrlString)
at Microsoft.VisualStudio.Web.Azure.Publish.ContainerRegistryProfileVisual.<PostPublishAsync>d__24.MoveNext()
— End of stack trace from previous location where exception was thrown —
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at Microsoft.VisualStudio.ApplicationCapabilities.Publish.ViewModel.ProfileSelectorViewModel.<RunPublishTaskAsync>d__116.MoveNext()

I haven’t found a way to get around this issue. I ended up using the Docker CLI to push my image. This takes a few steps. First, use the following command to log in.

docker login

Next, use the docker images command to find the image you are trying to push. In my case, it was the image with ID f83e5adab340. When the ID we can now use the following command to tag the image.

docker tag f83e5adab340 elanderson/testrepository

It is important that the image is tagged with the name of the repository it is going to be pushed to. Finally, run the following command to push the image with the specified tag into your repository.

docker push elanderson/testrepository

Wrapping Up

The teams at Microsoft have made adding Docker support to an existing project super simple. Docker is something that I have had a surface level awareness of for a while, and I am looking forward to trying an actual deployment to see how that works with DigitalOcean.

Adding Docker to an ASP.NET Core Application Read More »

GraphQL using .NET Boxed: Subscriptions

This post is going to continue my exploration of GraphQL using the .NET Boxed template as a jumping off point. The code I am starting with can be found here. Check out GraphQL using .NET Boxed: Mutations from last week for an exploration of mutations.

Subscriptions are GraphQL’s way of allowing a client to request notification of changes to the data.

Starting Point

As discovered a few weeks ago, MainSchema is the central point to finding how GraphQL is set up in this template. For reference here is the full class.

public class MainSchema : Schema
{
    public MainSchema(
        QueryObject query,
        MutationObject mutation,
        SubscriptionObject subscription,
        IDependencyResolver resolver)
        : base(resolver)
    {
        this.Query = resolver.Resolve<QueryObject>();
        this.Mutation = mutation;
        this.Subscription = subscription;
    }
}

Today we are interested in the Subscription property which is being assigned a SubscriptionObject.

Subscription Object

The following is the full SubscriptionObject for reference. I will point out a few details after the code.

public class SubscriptionObject : ObjectGraphType<object>
{
    public SubscriptionObject(IHumanRepository humanRepository)
    {
        this.Name = "Subscription";
        this.Description = "The subscription type, represents all updates can be pushed to the client in real time over web sockets.";

        this.AddField(
            new EventStreamFieldType()
            {
                Name = "humanCreated",
                Description = "Subscribe to human created events.",
                Arguments = new QueryArguments(
                    new QueryArgument<ListGraphType<StringGraphType>>()
                    {
                        Name = "homePlanets",
                    }),
                Type = typeof(HumanCreatedEvent),
                Resolver = new FuncFieldResolver<Human>(context => 
                                  context.Source as Human),
                Subscriber = new EventStreamResolver<Human>(context =>
                {
                    var homePlanets = 
                           context.GetArgument<List<string>>("homePlanets");
                    return humanRepository
                        .WhenHumanCreated
                        .Where(x => homePlanets == null || 
                                    homePlanets.Contains(x.HomePlanet));
                }),
            });
    }
}

A lot of this is going to look very similar to the other types we have reviewed for queries and mutations. For example, the Type is HumanCreatedEvent which derives from HumanObject which is ObjectGraphType around the Human class.

Type = typeof(HumanCreatedEvent)

One of the hardest things exploring GraphQL is getting a good handle on the object graph. I highly recommend you spend some time in these classes getting the connection solid in your mind.

As another example that should look pretty similar to things we coved in the other post is the Resolver which is dealing with the base Human type.

Resolver = new FuncFieldResolver<Human>(context => context.Source as Human)

This next bit is new and deals with the actual notification of GraphQL when the HumanRepository creates a new human. The following code has had the home planet related stuff removed for clarity.

Subscriber = new EventStreamResolver<Human>(context =>
{
    return humanRepository
        .WhenHumanCreated;
})

What is WhenHumanCreated? Looks like it is an observable provided by theHumanRepository.

public IObservable<Human> WhenHumanCreated => 
                          this.whenHumanCreated.AsObservable();

Looking at the AddHuman function you will see that this observable is provided a new value everytime a human is created which in turn provides notification to our GraphQL setup to notify any clients that are subscribed that a new human was added.

public Task<Human> AddHuman(Human human, CancellationToken cancellationToken)
{
    human.Id = Guid.NewGuid();
    Database.Humans.Add(human);
    this.whenHumanCreated.OnNext(human);
    return Task.FromResult(human);
}

Wrapping Up

That covers my exploration of subscriptions. For me, this was the coolest part of the things I have seen in GraphQL.

I know this was a bit of a strange series as we just looked at the code generated by a template. I hope you found it useful. I know it helped me get a better grip on the idea behind GraphQL and how it can be handled in .NET Core.

The associated sample code can be found here.

GraphQL using .NET Boxed: Subscriptions Read More »

GraphQL using .NET Boxed: Mutations

This post is going to continue my exploration of GraphQL using the .NET Boxed template as a jumping off point. The code I am starting with can be found here. Check out GraphQL using .NET Boxed: Queries from last week for an exploration of queries.

Mutations are GraphQL’s way of allowing a client to request changes to the data on the server-side.

Starting Point

As we discovered last week, MainSchema is the central point to finding how GraphQL is set up in this template. Just for reference here is the full class.

public class MainSchema : Schema
{
    public MainSchema(
        QueryObject query,
        MutationObject mutation,
        SubscriptionObject subscription,
        IDependencyResolver resolver)
        : base(resolver)
    {
        this.Query = resolver.Resolve<QueryObject>();
        this.Mutation = mutation;
        this.Subscription = subscription;
    }
}

We are interested in the Mutation property which is being assigned a MutationObject.

Mutation Object

The following is the full MutationObject class which defines what mutations are allowed for which objects on this server and what happens when a mutation request is received.

public class MutationObject : ObjectGraphType<object>
{
    public MutationObject(IHumanRepository humanRepository)
    {
        this.Name = "Mutation";
        this.Description = "The mutation type for updates to our data.";
        this.FieldAsync<HumanObject, Human>(
            "createHuman",
            "Create a new human.",
            arguments: new QueryArguments(
                new QueryArgument<NonNullGraphType<HumanInputObject>>()
                {
                    Name = "human",
                    Description = "The human you want to create.",
                }),
            resolve: context =>
            {
                var human = context.GetArgument<Human>("human");
                return humanRepository.AddHuman(human,
                                                context.CancellationToken);
            });
    }
}

This is very similar to have the QueryObject from last week was set up. The first big difference is in the QueryArguments. The mutation is taking a HumanInputObject class instead of an ID. If you look at the query argument you will also see that this argument isn’t allowed to be null.

new QueryArgument<NonNullGraphType<HumanInputObject>>()

What is the HumanInputObject class? It is an InputObjectGraphType and defines the shape of what the mutation query argument looks like. As you can see in the following it provides a name, description, and list of fields.

public class HumanInputObject : InputObjectGraphType
{
    public HumanInputObject()
    {
        this.Name = "HumanInput";
        this.Description = "A humanoid creature from Star Wars.";
        this.Field<NonNullGraphType<StringGraphType>>(nameof(Human.Name));
        this.Field<StringGraphType>(nameof(Human.HomePlanet));
        this.Field<ListGraphType<EpisodeEnumeration>>(nameof(Human.AppearsIn), "Which movie they appear in.");
    }
}

Also, note that the fields are using nameof on the properties of the Human class to make sure the names match which will prevent any problems with the mapping between the 3 different human classes this project is working with. Here is an example of the field definition pulled out from the above sample.

this.Field<NonNullGraphType<StringGraphType>>(nameof(Human.Name));

Another thing to make note of is that even at the field level you can set if a field is allowed to be null or not on top of setting the type of the field.

Back over in the MutationObject let’s look at the resolve inside of the FieldAsync call.

resolve: context =>
{
    var human = context.GetArgument<Human>("human");
    return humanRepository.AddHuman(human, context.CancellationToken);
});

This is pulling the human query argument and it is being translated into an instance of the Human class and then sent to the repository to be saved.

Wrapping Up

That covers the basic exploration of mutations. I’m thinking about looking at subscriptions.

The associated sample code can be found here.

GraphQL using .NET Boxed: Mutations Read More »

GraphQL using .NET Boxed: Queries

This post is going to continue my exploration of GraphQL using the .NET Boxed template as a jumping off point. The code I am starting with can be found here. If you want to start at the very basics of getting the .NET Boxed templates installed, check out my ASP.NET Core with GraphQL using .NET Boxed post.

Finding a Thread

As stated in the last post the backing data for the project is in a static class found in the Repositories/Database.cs file. The data is Star Wars themed and consists of two lists of characters one for droid and one for humans which get combined into a list of characters.

Instead of starting with the data and finding where it is used I’m going to approach this from the perspective of the way the application handles requests. For an ASP.NET Core application, this means looking at the Configure function of the Startup class, which is where the HTTP pipeline is configured.

In the Configure function, we find the following two calls related to GraphQL. I dropped the actual setting of options out of both calls.

.UseGraphQLWebSocket<MainSchema>(new GraphQLWebSocketsOptions())
.UseGraphQLHttp<MainSchema>(new GraphQLHttpOptions())

Looks like MainSchema is the thread we needed to follow.

MainSchema

There isn’t a lot of code in the MainSchema class. The following is the full class as it was generated by the template.

public class MainSchema : Schema
{
    public MainSchema(
        QueryObject query,
        MutationObject mutation,
        SubscriptionObject subscription,
        IDependencyResolver resolver)
        : base(resolver)
    {
        this.Query = resolver.Resolve<QueryObject>();
        this.Mutation = mutation;
        this.Subscription = subscription;
    }
}

The Schema class that is the base class is provided by the GraphQL for .NET library. Just like any other schema in GraphQL it is used to define the data available to the client and the types of queries that can be used. For now, we are going to stick with following the Query type and leave Mutation and Subscription for future posts.

Query Object

For the template, we are using the schema for queries is located in the QueryObject class. Below is the class but simplified to only include the setup of one entity. For our sample Star Wars data, I am using the human bits and dropping the droids.

public class QueryObject : ObjectGraphType<object>
{
    public QueryObject(IHumanRepository humanRepository)
    {
        this.Name = "Query";
        this.Description = "The query type, represents all of the entry points into our object graph.";

        this.FieldAsync<HumanObject, Human>(
            "human",
            "Get a human by it's unique identifier.",
            arguments: new QueryArguments(
                new QueryArgument<IdGraphType>()
                {
                    Name = "id",
                    Description = "The unique identifier of the human.",
                }),
            resolve: context => humanRepository.GetHuman(
                context.GetArgument("id", 
                                    defaultValue: new Guid("94fbd693-2027-4804-bf40-ed427fe76fda")),
                context.CancellationToken));
    }
}

The class Constructor needs an instance of a class that is used to access the data for the entity the query is being defined for, in this case, an IHumanRepository.

The key bit in this class is the FieldAsync<HumanObject, Human> call. It is the definition of the query allowed for getting a single human. The first parameter is the name of the query, the second is the query’s description.

Next, are the arguments the query needs to execute.

arguments: new QueryArguments(
                new QueryArgument<IdGraphType>()
                {
                    Name = "id",
                    Description = "The unique identifier of the human.",
                })

In this example, the query can take a single argument for the ID of the human to be returned. The final bit is how this query should be resolved to the actual backing data.

resolve: context => humanRepository.GetHuman(
            context.GetArgument("id", 
                                defaultValue: new Guid("94fbd693-2027-4804-bf40-ed427fe76fda")),
            context.CancellationToken))

Here the context allows us to pull the parameters passed by the client using the context.GetArgument function call with name, as defined in the argument section, and use them in the call to the humanRepository.

Object Graph Type

The last point I want to touch on is the difference between the two types on the FieldAsync<HumanObject, Human> call. Human is the type the entity used by the data access. HumanObject is Human wrapped in an ObjectGraphType. The following is the full HumanObject class.

public HumanObject(IHumanRepository humanRepository)
{
    this.Name = "Human";
    this.Description = "A humanoid creature from the Star Wars universe.";
    this.Field(x => x.Id, 
                    type: typeof(IdGraphType))
              .Description("The unique identifier of the human.");
    this.Field(x => x.Name)
              .Description("The name of the human.");
    this.Field(x => x.HomePlanet, nullable: true)
              .Description("The home planet of the human.");
    this.Field<ListGraphType<EpisodeEnumeration>>
              (nameof(Character.AppearsIn), 
               "Which movie they appear in.");
    
    this.FieldAsync<ListGraphType<CharacterInterface>, 
                    List<Character>>(
        nameof(Human.Friends),
        "The friends of the character, or an empty list if they have none.",
        resolve: context => 
                 humanRepository.GetFriends(context.Source,
                                            context.CancellationToken));
    this.Interface<CharacterInterface>();
}

This pattern allows extra metadata to be added to the type being wrapped. You can see this work in the schema area playground that the sample application launches when in development mode.

Wrapping Up

My previous post on GraphQL left me feeling like it was pretty magical. That is true from the client side perspective. From the server side, that magic comes with some complexity. Don’t take that as a judgment on GraphQL it is just one of the aspects that must be considered before selecting a technology. As I get more familiar with the server side of GraphQL I’m sure some of what I am seeing as complexity when just learning will become clear.

The associated sample code can be found here.

GraphQL using .NET Boxed: Queries Read More »

ASP.NET Core with GraphQL using .NET Boxed

GraphQL is something I have been meaning to look into for a while, but haven’t found the time. Muhammad Rehan Saeed recent release of .NET Boxed, which is a rebranding of his ASP.NET Core Boilerplate templates, contains a template for GraphQL. This brought GraphQL back to the front of my mind so this post is going to walk through installing and using .NET Boxed to get a GraphQL project up and running.

Template Installation

As with all templates, installation is very easy using the .NET CLI. Open a command prompt and enter the following command.

dotnet new --install "Boxed.Templates::*"

The * at the end of the command is just making sure the latest version gets installed. After the installation is done you will get a list of all the template you have installed. The two new ones provided by .NET Boxed are highlighted in the screenshot.

Project Creation

For this post, we will be creating a project using the graphql template. Both of the templates provided by .NET Boxed have a lot of optional flags that can be used configure the resulting project. Make sure to run the help command for the template you are using to see if there are any option you want to set. For example, the following command would list all the options for the GraphQL template.

dotnet new graphql --help

Create and navigate to the directory you want the new project to be created in and then run the following command to create the project with the default setting with the exception of turning off HTTPS. Not something you want to turn off for a production application, but it reduces the complexity of the initial exploration.

dotnet new graphql --https-everywhere false

With the project created run the following command from the same directory to open it in Visual Studio Code.

code .

Some Project Notes

The project generation creates a ReadMe.html in the root of the project. Make sure and check it out. It has a list of pre-requisites needed for the project as well as a lot of good information on general good practices.

We aren’t going to dig too far into the project itself in this post, but it is helpful to know where the data lives and what it looks like for when we are trying out some GraphQL queries. The backing data is in a static class found in the Repositories/Database.cs file.

The data is Star Wars themed and consists of two lists of characters one for droid and one for humans which get combined into a list of characters. The following is the Database class for reference.

public static class Database
{
    static Database()
    {
        Droids = new List<Droid>()
        {
            new Droid()
            {
                Id = new Guid("1ae34c3b-c1a0-4b7b-9375-c5a221d49e68"),
                Name = "R2-D2",
                Friends = new List<Guid>()
                {
                    new Guid("94fbd693-2027-4804-bf40-ed427fe76fda"),
                    new Guid("c2bbf949-764b-4d4f-bce6-0404211810fa")
                },
                AppearsIn = new List<Episode>() { Episode.NEWHOPE,
                                                  Episode.EMPIRE,
                                                  Episode.JEDI, },
                PrimaryFunction = "Astromech"
            },
            new Droid()
            {
                Id = new Guid("c2bbf949-764b-4d4f-bce6-0404211810fa"),
                Name = "C-3PO",
                Friends = new List<Guid>(),
                AppearsIn = new List<Episode>() { Episode.NEWHOPE,
                                                  Episode.EMPIRE,
                                                  Episode.JEDI, },
                PrimaryFunction = "Protocol"
            }
        };
        Humans = new List<Human>()
        {
            new Human()
            {
                Id = new Guid("94fbd693-2027-4804-bf40-ed427fe76fda"),
                Name = "Luke Skywalker",
                Friends = new List<Guid>()
                {
                    new Guid("1ae34c3b-c1a0-4b7b-9375-c5a221d49e68"),
                    new Guid("c2bbf949-764b-4d4f-bce6-0404211810fa")
                },
                AppearsIn = new List<Episode>() { Episode.NEWHOPE,
                                                  Episode.EMPIRE,
                                                  Episode.JEDI, },
                HomePlanet = "Tatooine"
            },
            new Human()
            {
                Id = new Guid("7f7bf389-2cfb-45f4-b91e-9d95441c1ecc"),
                Name = "Darth Vader",
                Friends = new List<Guid>(),
                AppearsIn = new List<Episode>() { Episode.NEWHOPE,
                                                  Episode.EMPIRE,
                                                  Episode.JEDI, },
                HomePlanet = "Tatooine"
            }
        };
        Characters = Droids.AsEnumerable<Character>()
                           .Concat(Humans)
                           .ToList();
    }

    public static List<Character> Characters { get; }

    public static List<Droid> Droids { get; }

    public static List<Human> Humans { get; }
}

Try it out

When you run the project in development mode (the default) it will show a GraphQL playground which is made available by GraphQL.NET. It looks like the following.

Box 1 is the area where you enter the query you want to execute against the GraphQL backend. Box 2 is the play button which sends the query to the backend. Finally, box 3 is where the results of the query are displayed.

The following query is asking for ID, Name, and Appears In properties for the human that matches the provided ID.

query getHuman{
  human(id: "94fbd693-2027-4804-bf40-ed427fe76fda")
  {
    id,
    name,
    appearsIn    
  }
}

On our sample data, the query returns the following.

{
  "data": {
    "human": {
      "id": "94fbd693-2027-4804-bf40-ed427fe76fda",
      "name": "Luke Skywalker",
      "appearsIn": [
        "NEWHOPE",
        "EMPIRE",
        "JEDI"
      ]
    }
  }
}

Now let’s try creating a new human. Clear the query area and enter the following query.

mutation createHuman($human: HumanInput!) {
  createHuman(human: $human) {
    id
    name
  }
}

If you tried to run the above it would fail. For this query to work we need to define what $human is. You do this in the Query Variables area which is right below box 1 in the screenshot above. Enter the following and hit the play button.

{
  "human": {
    "name": "Eric Anderson",
    "homePlanet": "Earth"
  }
}

This will result in the following. Your ID will be different of course.

{
  "data": {
    "createHuman": {
      "id": "22297c0e-01b4-4322-8e25-16d455a0c8e2",
      "name": "Eric Anderson"
    }
  }
}

Wrapping Up

The above information is enough to get started playing with GraphQL with ASP.NET Core. There is a lot more that I want to dig into so look for more posts on these topics. The code can be found here.

ASP.NET Core with GraphQL using .NET Boxed Read More »

Deploying an ASP.NET Core Application to Microsoft Azure

This is the third post in a series on deploying a very simple ASP.NET Core application to the major cloud provides. This post is going to be dealing with setup and deployment to Microsoft Azure.

The following is are the other posts in this series.

Google Cloud Platform
Amazon Web Services
Microsoft Azure (this post)

Sample Application

This is the same as the first post in the series, but am including it in case you missed that post. The sample application that we will be deploying is the basic Razor Pages applications created using the .NET CLI. The following commands are what I used to create the application, create a solution, and add the project to the solution. I ran all these commands in a CloudSample directory.

dotnet new razor
dotnet new sln
dotnet sln add CloudSample.csproj

Microsoft Azure

The rest of this post is going to be based on the official Create an ASP.NET Core web app in Azure documentation. I already have all the Azure related stuff installed and have used it before, so it will be much easier for me to miss a step. If that happens please leave a comment and I will get the post fixed.

Azure Development for Visual Studio

The additional tools need to use Azure from Visual Studio are part of the Visual Studio installer. I’m assuming that Visual Studio is already installed. To add Azure select the Tools > Get Tools and Features menu.

After the installer launches close all instances of Visual Studio. From the list of features select Azure development and click the Modify button to start the installation.

Sign up for Azure

While the tools are installing is a good time to sign up for Azure if you don’t already have an account. You can sign up here. This is one of the parts that doesn’t work well when you already have an account, but the link above should guide you through the process.

Application Publication

Hope back in Visual Studio and open the solution you want to publish. In the Solution Explorer window right-click on the project and select the Publish menu option.

This will show the publish target dialog where you can select what you want to publish to. In this example, we are going to be publishing to an App Service. The details area select Create New option. Then click the Publish button to move to the next screen

The next step collects the information needed to Create an App Service. The first thing to set is the account in the upper right corner of the screen. This could already be set based on how you are logged in to Visual Studio. Next, click the New link next to the Resource Group and enter the name you want to use. Then click the New link next to the Hosting Plan.

In the Hosting Plan dialog, you get options to give the plan a name, pick your hosting location, and the size. For the Size, I recommend starting with the Free option. After all the options are set click OK.

This will return you to the Create App Service dialog where you can click the Create button to deploy the application. After deployment finishes the site will open in your default browser.

Wrapping Up

For me using Azure from Visual Studio is the simplest experience of all the cloud providers I have tried so far. I don’t guess that is surprising since Microsoft controls both products. Forgetting the integration with Visual Studio it seems that Azure App Services, Google App Engine, and Amazon Elastic Beanstalk are all on par with each other.

As always don’t forget to shutdown/delete the associated resources for your test project to avoid changes.

Deploying an ASP.NET Core Application to Microsoft Azure Read More »