0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MagicOnionでgRPC-Webを使う

Last updated at Posted at 2025-03-09

概要

C#でAPIを立てる際、最近はMagicOnionばっかり使ってます。今までBlazorServerやWinFormsとMagicOnionサーバを通信させることが多かったんですが、最近はBlazorWebAssemblyを使用することが多くなってきました。その際に、WebAssemblyだと普通のgRPCが使えないため、MagicOnionをgRPC-Webに対応させる必要がありました。ネット上にその方法がなかなか落ちていなかったので、備忘録的な感じで残しておきます。
なお、この記事ではMagicOnionの環境がすでに整っている前提で手順を書きます。そもそもMagicOnionの使い方がわからないという方はこちらの時期を参照ください。

ちなみに今回説明しているコードは以下のリポジトリにありますので、参考にしていただければと思います。
https://github.com/Uta-member/SampleProject.MO.Web

環境

  • VisualStudio 2022 Community
  • .NET8
  • C# 13
  • MagicOnion 7.0.2

サーバ側の設定

サーバのサービスクラス側は特に変える必要がなく、パッケージを追加してProgram.csをちょっと変えれば対応できます。

パッケージの追加

サーバ側のプロジェクトに以下のパッケージをインストールします。

  • Grpc.AspNetCore.Web
    image.png

Program.csの修正

以下のように修正を行います。

Program.cs
var builder = WebApplication.CreateBuilder(args);

builder.Services.AddGrpc();
builder.Services.AddMagicOnion();

// ここから追加 >>>
// CorePolicyを追加
// 内容はプロジェクトによって合わせてください
builder.Services
    .AddCors(
        o => o.AddPolicy(
            "AllowAll",
            builder =>
            {
                builder.AllowAnyOrigin()
                    .AllowAnyMethod()
                    .AllowAnyHeader()
                    .WithExposedHeaders("Grpc-Status", "Grpc-Message", "Grpc-Encoding", "Grpc-Accept-Encoding");
            }));
// ここまで <<<

var app = builder.Build();

// ここから追加 >>>
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();

app.UseGrpcWeb(new GrpcWebOptions { DefaultEnabled = true });

app.UseCors();
// ここまで <<<

// ミドルウェアの追加
// app.MapMagicOnionService();
app.MapMagicOnionService()
    // gRPC-webを有効化
    .EnableGrpcWeb()
    // 上で設定したCORS Policy名を指定する
    .RequireCors("AllowAll");

app.MapGet(
    "/",
    () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");

app.Run();

基本的にはCORSの設定を行いgRPC-webを有効化するだけです。

クライアント側の設定

クライアント側もソース自体というよりはGrpcChannelのインスタンスの設定のみで対応可能です。

パッケージの追加

クライアント側のプロジェクトに以下のパッケージをインストールします。

  • Grpc.Net.Client.Web

image.png

GrpcChannelの修正

今回はとりあえず最低限の動きを再現するためにコンソールアプリで実装します。
以下のようにProgram.csを記述します。

Program.cs
using Grpc.Net.Client;
using Grpc.Net.Client.Web;
using MagicOnion.Client;
using SampleProject.MO.Web.Interface;

// gRPC-Webのクライアントを作成
var httpClient = new HttpClient(new GrpcWebHandler(GrpcWebMode.GrpcWeb, new HttpClientHandler()));
// サーバのIPを入れる
// 実際のアプリではDIコンテナに入れて共有などを行うと思う
// オプションにgRPC-WebのHTTPクライアントを指定
GrpcChannel channel = GrpcChannel.ForAddress(
    "https://localhost:7283",
    new GrpcChannelOptions { HttpClient = httpClient });

// チャンネルを使ってサービスのクライアントを作成する
IMOUserService userService = MagicOnionClient.Create<IMOUserService>(channel);

// 実行
var userResult = userService.FindUserByUserId("userId");
var user = userResult.GetAwaiter().GetResult();

// 普通にawaitも使えます
// var user = await userService.FindUserByUserId("userId");

if(user != null)
{
    Console.WriteLine($"UserId: {user.Id}");
    Console.WriteLine($"UserName: {user.Name}");
} else
{
    Console.WriteLine("ユーザが見つかりませんでした");
}

Console.ReadLine();

実行

実行するとちゃんとサーバ側の処理を呼べているのがわかりますね。
image.png

実際にはコンソールではなくBlazorWebAssemblyなどで使うことになると思います。
また、これはC#に限らずReactなどのような別の言語からも呼べるはずなので、そのあたりも気力があれば記事にしていきたいと思います。

さいごに

ネット上になかなかこの方法が落ちておらず、gRPC-Webに関してもそこまで詳しくなかったので、ちゃんとBlazorWASMで通信できるようになるまでかなり時間がかかりました。。この記事で救われる人がいれば幸いです。

ちなみにSwaggerとの共存も可能です。基本的にはgRPC-WebのミドルウェアのあとにSwaggerのミドルウェアをかまして、最後にMagicOnionのミドルウェアをかませればOKですが、そのあたりの細かい解説はMagicOnionをSwaggerでテストする方法の記事にまとめたいと思います。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?