本記事では、gRPCでの共通プロジェクトの分離方法について説明します。具体的には、annotations.protoやhttp.protoファイルをサーバーおよびクライアントで共有するための手法を取り上げます。
共通プロジェクトの設定
以下は、共通プロジェクトの.csprojファイルの例です。この設定により、必要なパッケージがインストールされます。
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.AspNetCore" Version="2.70.0" />
</ItemGroup>
</Project>
プロトコルバッファ定義
次に、プロトコルバッファファイル(.proto)の例を示します。ここでは、学生情報の取得サービスを定義しています。
syntax = "proto3";
option csharp_namespace = "StudentServiceLib";
package student;
import "google/api/annotations.proto";
service StudentInfoService {
rpc FetchStudent (SearchRequest) returns (SearchResponse) {
option (google.api.http) = {
get: "/v1/students/{keyword}"
};
}
}
message SearchRequest {
string keyword = 1;
}
message SearchResponse {
repeated Student students = 1;
}
message Student {
string id = 1;
string name = 2;
}
サービス実装
以下は、上記のプロトコルバッファに基づくgRPCサービスの実装例です。
using Google.Protobuf.WellKnownTypes;
using Grpc.Core;
using System.Collections.Generic;
using System.Linq;
namespace StudentServiceLib
{
public class StudentInfoServiceImpl : StudentInfoService.StudentInfoServiceBase
{
private static readonly List<Student> _students = new()
{
new() { Id = "S001", Name = "太郎" },
new() { Id = "S002", Name = "花子" }
};
public override Task<SearchResponse> FetchStudent(SearchRequest request, ServerCallContext context)
{
var filteredStudents = _students.Where(s => s.Name.Contains(request.Keyword)).ToList();
return Task.FromResult(new SearchResponse { Students = { filteredStudents } });
}
}
}
WebAPIプロジェクトの設定
WebAPIプロジェクトでは、以下の.csprojファイルを使用します。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Google.Api.CommonProtos" Version="2.16.0" />
<PackageReference Include="Grpc.AspNetCore" Version="2.70.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\SharedGrpcProject.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="StudentInfoService.proto">
<AdditionalImportDirs>../../Common</AdditionalImportDirs>
</Protobuf>
</ItemGroup>
</Project>
クライアント側の実装
最後に、クライアント側の実装例を示します。
using Grpc.Net.Client;
using Microsoft.AspNetCore.Mvc;
using StudentServiceLib;
namespace ClientApp.Controllers
{
[ApiController]
[Route("api/[controller]")]
public class StudentController : ControllerBase
{
[HttpGet("{query}")]
public IActionResult Get(string query)
{
var channel = GrpcChannel.ForAddress("https://localhost:5001");
var client = new StudentInfoService.StudentInfoServiceClient(channel);
var response = client.FetchStudent(new SearchRequest { Keyword = query });
return Ok(response.Students);
}
}
}
クライアントプロジェクトの設定
クライアントプロジェクトでは、以下のような.csprojファイルを使用します。
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Grpc.Net.Client" Version="2.70.0" />
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Common\SharedGrpcProject.csproj" />
</ItemGroup>
<ItemGroup>
<Protobuf Include="StudentInfoService.proto" GrpcServices="Client">
<AdditionalImportDirs>../../Common</AdditionalImportDirs>
</Protobuf>
</ItemGroup>
</Project>