Sharing a proto file between the client and the server
In .NET, if you want to share common functionality between different applications, you would put this functionality into a class library and then add this library to all the projects that need to use it. The good news is that you can do the same with proto files. To share this between applications, you can just add it to a class library and then add the class library as a reference.
Let's do this with our client and server projects.
Creating a shared class library
Inside the folder that holds both the BasicGrpcService
and BasicGrpcClient
project folders, create a new class library project and call it GrpcDependencies
.
If you are using an IDE, you can add a project by choosing the Class Library
template. Please ensure that .NET 5 is selected as the framework. Otherwise, keep all other options as-is.
If you prefer to use a CLI, you can execute the following command inside the folder hosting your existing projects to create a class library:
dotnet new classlib -o GrpcDependencies
Please note that, with a class library that is shared between projects, it would be more convenient to manage them if you have all these projects, including the class library itself, added to a solution.
If you have been using an IDE up to this point with all the default options selected, unless specified otherwise, you probably have the solution set up and all of your projects will already be a part of it.
If this is what your setup already looks like, you can skip to the next section. Otherwise, you can execute the following command inside the folder that hosts all your project folders to create a solution file:
dotnet new sln
This will create a file with the .sln
extension that has the same name as the folder that hosts it.
Now, you can add all your projects to the folder by executing the following commands:
dotnet sln add GrpcDependencies/GrpcDependencies.csproj dotnet sln add BasicGrpcService/BasicGrpcService.csproj dotnet sln add BasicGrpcClient/BasicGrpcClient.csproj
You should now have a solution set up and all projects added to it. If you choose the build solution
option, all the projects will be built together. You no longer have to build them individually.
Adding shared gRPC components to the class library
Since you now have a shared library for storing proto files, you no longer need to store a copy of the greeter.proto
file in every project that uses it. You just need to store one copy in the class library itself.
So, copy the entire proto folder from either the BasicGrpcService
or BasicGrpcClient
folder into the GrpcDependencies
folder.
Next, we will need to add the right NuGet dependencies to our GrpcDependencies
class library. The dependencies that we used to reference our client and server projects will only need to be referenced in the class library, so our dependency tree will be kept clean.
To add the required dependencies, execute the following CLI commands inside the GrpcDependencies
folder:
dotnet add GrpcDependencies.csproj package Grpc.Net.Client dotnet add GrpcDependencies.csproj package Google.Protobuf dotnet add GrpcDependencies.csproj package Grpc.Tools dotnet add GrpcDependencies.csproj package Grpc.AspNetCore
Please note that these are the standard NuGet packages that are used by both the gRPC client and server. Because our shared class library will be used by both types of applications, we need both sets of dependencies.
Now, add a proto reference to your GrpcDependencies.csproj
file. We will amend the GrpcServices
element to this as we need to be able to build both the client and server gRPC components from the class library. Therefore, the markup block that we need to add to the project file will look like this:
<ItemGroup> <Protobuf Include="Protos\greeter.proto" /> </ItemGroup>
Finally, remove any other greet.proto
file references from your project file, which could have been auto-generated when you copied the file into the project folder.
Now, the content of your GrpcDependencies.csproj
file should look similar to this:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <PackageReference Include="Google.Protobuf" Version="3.17.3" /> <PackageReference Include="Grpc.Net.Client" Version="2.38.0" /> <PackageReference Include="Grpc.Tools" Version="2.38.1"> <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets> <PrivateAssets>all</PrivateAssets> </PackageReference> <PackageReference Include="Grpc.AspNetCore" Version="2.34.0" /> </ItemGroup> <ItemGroup> <Protobuf Include="Protos\greeter.proto" /> </ItemGroup> </Project>
Now, we are ready to use this class library in our applications.
Sharing gRPC dependencies between different projects
First, you will need to reference the newly created class library from both the BasicGrpcService.csproj
and BasicGrpcClient.csproj
files. To do so, add the following section to both of the files:
<ItemGroup> <ProjectReference Include="..\GrpcDependencies\GrpcDependencies.csproj" /> </ItemGroup>
Now, you can remove all the gRPC-related NuGet dependencies from both of those files. All of them are present in the shared class library, so when you reference the class library, all of those dependencies will be implicitly referenced too.
After cleaning up your project files, the BasicGrpcService.csproj
file should look similar to this:
<Project Sdk="Microsoft.NET.Sdk.Web"> <PropertyGroup> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\GrpcDependencies\GrpcDependencies.csproj" /> </ItemGroup> </Project>
The content of the BasicGrpcClient.csproj
file should be very similar and look like this:
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net5.0</TargetFramework> </PropertyGroup> <ItemGroup> <ProjectReference Include="..\GrpcDependencies\GrpcDependencies.csproj" /> </ItemGroup> </Project>
Please note that the only differences between the two project files are the SDK type and the output type, which represent different types of applications.
Now, to verify that all the dependencies have been set up successfully, build your solution and ensure there aren't any build errors. If it builds successfully, launch your BasicGrpcService
project, followed by the BasicGrpcClient
project, to ensure that everything still works correctly.
The applications are expected to produce the same output that they did previously. However, this time, a single copy of the proto file will be shared between them, so you no longer run the risk of making two copies of the file incompatible while updating them.
Another important thing to note is that, just like any other class library, a library containing proto files can be published as a NuGet package.