Home Calling gRPC Microservices from .Net Core 3.0 Web Apis
Post
Cancel

Calling gRPC Microservices from .Net Core 3.0 Web Apis

Alt text

We now need something to call our gRPC services. Here I will create an Asp.Net Core Web Api. I would look at this as the application’s gateway to the microservices.

I decided to break out this piece into three posts. The others are:

The corresponding code for this post is located on GitHub.

Please note that the code demonstrated here is for illustration and learning, not production. I have not broken out code into separate classes much just to keep things as simple to follow as possible.

Let’s Get Started

We will start by adding an ASP.NET Core Web Application to the solution that we created in the previous article.

Alt text

I will name the project “Apothecaric.Authentication.Api”. And then let’s Create!

Alt text

Let’s create an Api project that targets the .Net Core .30 framework. We will with no authentication and keep the default checks for HTTPS and Enabling Docker.

Alt text

We will then select the Empty Api Controller.

Alt text

Clear Up Some Template Files

Now let’s clean up a couple of files that were created with the Api template. Delete the WeatherForcast.cs file in the root of the project and also the WeatherForecastController.cs file from the Controllers folder.

Alt text

Start With A Controller

Now right click on the Controller menu and select Add -> Controller. I will name this Controller AuthenticationController.

Alt text

Protos Again

Before we code out our new Authentication Controller, we need to allow the build process to create some code files for us in order for us to connect to, and consume the gRPC Authentication Services. Usually you would keep a directory with proto files and you could share that proto directory with several projects.

For simplicity’s sake, let’s just copy the proto file from our Apothecaric.Authentication.Service project.

Create a Protos folder in the Apothecaric.Authentication.Api project and copy the Authentication.proto file from our Service project, into our Api project.

Alt text

Edit Project File

Next we will adjust our Apothecaric.Authentication.Api project file to allow the build creation of the Client Authentication files we need to connect to the Service.

Open up the project file and delete the ItemGroup that holds our newly copied Authentication.proto file. This is just a “new file” designation.

Alt text

Now add the path to the Authentication.protos file to the project file. This time, however, we want to designate that the files created for gRPC be Client files and NOT Server files. We want to consume the services in our Api project, not serve them!

Your project file should look something similar to this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<Project Sdk="Microsoft.NET.Sdk.Web">

  <PropertyGroup>
    <TargetFramework>netcoreapp3.0</TargetFramework>
    <UserSecretsId>123456-2222-4444-aaaa-98654321</UserSecretsId>
    <DockerDefaultTargetOS>Linux</DockerDefaultTargetOS>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.1.0" />
    <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="3.1.0">
      <PrivateAssets>all</PrivateAssets>
      <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
    </PackageReference>
    <PackageReference Include="Microsoft.Extensions.Logging.Debug" Version="3.1.0" />
    <PackageReference Include="Microsoft.VisualStudio.Azure.Containers.Tools.Targets" Version="1.9.5" />
   <PackageReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Design" Version="3.1.0" />
  </ItemGroup>

  <ItemGroup>
    <Protobuf Include="Protos\Authentication.proto" GrpcServices="Client" />
  </ItemGroup>

</Project>

Again, don’t forget to designate Client for the type of GrpServices.

1
<Protobuf Include="Protos\Authentication.proto" GrpcServices="Client" />

Needed Nuget Packages.

We also need some packages from Nuget in order for our gRPC-based files to be created. In our Service project, the template took care of this for us. In the Api project, we need to go grab some dependencies.

Add the following Nuget packages to our Apothecaric.Authentication.Api project.

Alt text

Time For A Build

Now build (or sometimes rebuild) the solution and our client Authentication gRPC files should be created.

After the build, we can look for our newly created Client Authentication.cs and AuthenticationGrpc.cs files. These are in much of the same location as the Service project.

Alt text

Back To The Controller

Our AuthenticationController code:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
[Route("api/[controller]")]
[ApiController]
public class AuthenticationController : ControllerBase
{
    [HttpPost]
    [AllowAnonymous]
    [Route("Token")]
    public async Task&lt;IActionResult&gt; CreateToken([FromBody] LoginViewModel login)
    {
        var channel = GrpcChannel.ForAddress("https://localhost:5001");
        var client = new Service.Protos.Authentication.AuthenticationClient(channel);

        var request = new LoginRequest
        {
            Email = login.Email,
            Password = login.Password
        };

        var response = await client.CreateTokenAsync(request);

        if (response != null)
        {
            return Ok(response);
        }
        else
        {
            return Unauthorized();
        }
    }

    [HttpPost]
    [AllowAnonymous]
    [Route("Token/Refresh")]
    public async Task&lt;IActionResult&gt; RefreshToken([FromBody] UserViewModel user)
    {
        var channel = GrpcChannel.ForAddress("https://localhost:5001");
        var client = new Service.Protos.Authentication.AuthenticationClient(channel);

        var request = new RefreshTokenRequest
        {
            AuthToken = user.AuthToken,
            RefreshToken = user.RefreshToken,
            FirstName = user.FirstName,
            LastName = user.LastName
        };

        var response = await client.RefreshTokenAsync(request);

        if (response != null)
        {
            return Ok(response);
        }
        else
        {
            return Unauthorized();
        }
    }
}

In both of our methods we need to define our gPRC Channel. Remember from when we created our Service project, the Apothecaric.Authentication.Service project will run on port 5001. Here we point to that service.

1
var channel = GrpcChannel.ForAddress("https://localhost:5001");

Then we create our client. This is the object where we will make our method calls from.

1
var client = new Service.Protos.Authentication.AuthenticationClient(channel);

In the next step were we create our Request object, would usually be a great place to use a tool like AutoMapper. Again, we are keeping things simple for now.

1
2
3
4
5
var request = new LoginRequest
{
      Email = login.Email,
      Password = login.Password
};

After the request data is all set, we can make our method call and set our response.

1
var response = await client.CreateTokenAsync(request);

Notice that we have chosen to call the Async methods. Yes! Async and Sync methods were created for us with the Client build.

Alt text

Then we just check for an object in our response and, for now, just send back the mocked data we get returned from our Service.

1
2
3
4
5
6
7
8
if (response != null)
{
    return Ok(response);
}
else
{
    return Unauthorized();
}

One More Thing Before We Run

Now that we have more than one project to run, we need to set up for starting multiple projects.

Right click on the Solution and choose the Set Startup Projects… context menu option.

Alt text

Select the Multiple startup projects radio button and set both of our project to Start in the Actions dropdown. Now both projects will startup when we debug/run our Solution.

Alt text

Set The Port – Last Step

If we leave things alone, both projects will try to run on our localhost’s port 5001. This is the default that the template has set. We will set our Api project to run on port 5002. Collision issue solved.

Go into the launchSettings.json file. You can also change this by selecting the Properties context menu if you right click on the project.

Alt text

In the spot that will run the Kestrel server, update the https port to point to port 5002. You can also change the http port if you are running without https.

Alt text

Runnin’

If you run the project now, you should see two command prompts pop up and also your default browser.

Alt text

Test Call

Now we can run Postman and try out our Authentication call.

In Postman, create a POST call that points to https://localhost:5002/api/authentication/token.

For the POST body, make sure you select raw and JSON. We then can create our LoginViewModel JSON object in the POST body.

1
2
3
4
{
  "email": "your@email.com",
  "password": "reallycoolpassword!"
}

Alt text

If all goes well, you will see the response that you pre-defined in the Service project from the first article.

Alt text

You can then test the Refresh call by creating another Postman POST call that points to https://localhost:5002/api/authentication/token/refresh. Just use the JSON response from the token call in the body of the Refresh call.

Next Steps…

In the next article, we will create a library to do the actual authentication and auth database creation. Stay tuned…..

Hope to see you then!

This post is licensed under CC BY 4.0 by the author.