Sharing gRPC ProtoBuf contracts using a REST endpoint

Developer Support

In this post, Premier Consultant Randy Patterson explores ASP.NET Static File middleware as an option to distribute gRPC proto files.


Introduction

gRPC services require a service contract usually defined using the Protocol Buffer Language in proto files. The service contract is then used to generate your C# (or language of your choice) server-side classes and your client side proxies. Sharing these proto contract files is necessary for generating these classes. However, there is no easy way to share these files other than copying them from the server to the client. Sharing files like this can be especially difficult in a Microservices architecture where there can be many different clients developed by many different teams. This post will walk you through the process of adding middleware to a gRPC server to deliver your proto files using a URL instead of files.

Create Project

Create a new project and choose the gRPC Service Template using the latest version of .Net Core

Add Middleware

Open the Startup.cs file and modify the Configure method

First, add the StaticFIles middleware before app.UseRouting() and configure it to only serve proto files located in the /protos directory.

public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
     . . . 

    //only serve .proto files
    var provider = new FileExtensionContentTypeProvider();
    provider.Mappings.Clear();
    provider.Mappings[".proto"] = "text/plain";
    app.UseStaticFiles(new StaticFileOptions
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Protos")),
        RequestPath = "/proto",
        ContentTypeProvider = provider

    });

    app.UseRouting();

    . . .
}}

Update Project File

Next, update the project file to copy the protos directory to the output and publish directories

Before the final </project> element in the .csproj files add the following sections

  <ItemGroup>
    <Content Update="Protos\*">
      <CopyToOutputDirectory>Always</CopyToOutputDirectory>
    </Content>
  </ItemGroup>

  <ItemGroup>
    <Content Include="Protos\*" CopyToPublishDirectory="PreserveNewest" />
  </ItemGroup>

This will copy all the files in the /Protos directory to your output and publish directories

Run the application and navigate to http://localhost:5001/proto/greet.proto . You should see the following screen.

Much like WCF WSDL Endpoints to REST API Swagger endpoints, you now have gRPC endpoints that deliver the contract files to any client that needs them.

Directory Browser

Optionally, you can add middleware to deliver a UI allowing a user to view all your proto files and clicking on any file will display the contents.

Back in your Startup.cs files, add the following MiddleWare

app.UseDirectoryBrowser(new DirectoryBrowserOptions
{
    FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, "Protos")),
    RequestPath = "/proto"
});

Start your application and browse to the http://localhost:5001/proto URL and you should be presented with the following UI

Conclusion

One of the challenges of implementing gRPC endpoints is distributing the required ProtoBuf contracts and updates to clients. There are several ways of accomplishing this including brute force method of copying the files to the client, NuGet Packages or network file shares. Delivering the contracts using a URL can make the services easier to use and discover. This can be crucial in a large micro-service architecture where you could have hundreds of contracts to manage. To view the full source code please visit https://github.com/ranpatterson/GrpcEndpoints

3 comments

Discussion is closed. Login to edit/delete existing comments.

  • Phillip Copley 0

    After we make the .proto files available for consumption, how does the client generate its C# proxies from this as part of the build process?

    • Paul Kreker 0

      In Visual Studio it’s the same approach as selecting the .proto files from disk. You click on the “Connected Services”-Node in your project, select Service References in the opened form, then you click on “Add new gRPC service reference” and a dialog shows up. Here you have the option between File and URL. That’s it. 🙂

Feedback usabilla icon