LoginSignup
0
0

More than 1 year has passed since last update.

Blazor WebAssemblyでRestSharpを使ってみる(その2)

Last updated at Posted at 2022-09-21

はじめに

RestSharp

注意!!
v107以降で記述方法が大分変更となっています。
現在は、V108です。

  • そのため、Postmanで表示されるコードは、使用できません。
    image.png

BOCCO emo

  • ユカイ工学さんが提供しているコミュニケーションロボットです。
  • とってもかわいいロボットなんですが、法人向けにAPIが用意されています。
    • 使用するには、法人アカウントを取得する必要があります。
    • APIには、メッセージをおくるとBoccoがしゃべったり、モーションをさせたり、センサーの情報を取得できたりします。

BOCCO emo API

BOCCO emo

開発環境

RestSharpの適用

  • .Serverを右クリックして、Nugetパッケージの管理 を選択
    • RestSharpと入力、その際、プレリリースを含めるのチェックボックスはオフにする。

前回は、Clientで追加していますが、今回は、ServerにRestSharpを適用しています。

image.png

Newton.Jsonの適用

  • .Serverを右クリックして、Nugetパッケージの管理 を選択
    • Newtonsoft.jsonと入力、その際、プレリリースを含めるのチェックボックスはオフにする。

別にNewtonsoft.jsonじゃなくてもよいのですが、使い慣れているので、適用しています。

image.png

実装

  • ClientのPagesに新しいRazorコンポ―ネットを追加します。

image.png

  • BoccoSensor.razorを作成

image.png

アクセストークンの取得処理

モデルの作成

データモデルの作成
  • *.Sharedのプロジェクトを右クリックして、追加 > クラスで「ApiTokenModel」を作成

image.png

  • データモデル
    • internalをpublicへ変更
ApiTokenModel.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ApexChartsSample.Shared
{
-    internal class ApiTokenModel
+    public class ApiTokenModel
    {
+        public string access_token { get; set; }
+        public string refresh_token { get; set; }
    }
}

レスポンスモデルの作成
  • *.Sharedのプロジェクトを右クリックして、追加 > クラスで「BoccoApiTokenResponse」を作成

image.png

  • レスポンスモデル
    • internalをpublicへ変更
BoccoApiTokenResponse.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ApexChartsSample.Shared
{
-    internal class BoccoApiTokenResponse
+    public class BoccoApiTokenResponse
    {
+        /// <summary>
+        /// 処理結果
+        /// </summary>
+        public bool IsSucceed { get; set; }
+
+        /// <summary>
+        /// メッセージ
+        /// </summary>
+        public string? ResponseMessage { get; set; }
+
+        /// <summary>
+        /// APIトークン
+        /// </summary>
+        public ApiTokenModel? ApiToken { get; set; }
    }
}


リポジトリの作成

もしかしたら、この手順は不要かもしれませんが、いままでWPFで作ってたやり方をBlazorでそのまま使用しているので、インターフェース等を作っちゃってます。

  • *.Serverのプロジェクトを右クリックして、追加 > 新しいフォルダ―で「Repositories」を作成

image.png

  • Repositories」を右クリックして、追加 > 新しいフォルダ―で「Interface」を作成

image.png

  • Interface」を右クリックして、追加 > 新規項目 > インターフェースで「IBoccoServiceRepository」を作成

image.png

  • IBoccoServiceRepositoryの記述
IBoccoServiceRepository.cs
using ApexChartsSample.Shared;

namespace ApexChartsSample.Server.Repositories.Interface
{
    public interface IBoccoServiceRepository
    {
+        /// <summary>
+        /// アクセストークンの取得
+        /// </summary>
+        /// <returns></returns>
+        public Task<BoccoApiTokenResponse> GetAccessToken();
    }
}

  • Repositories」を右クリックして、追加 > クラスで、「BoccoServiceRepository」を作成

image.png

  • BoccoServiceRepositoryの記述
    • IBoccoServiceRepositoryを継承
BoccoServiceRepository.cs
+ using ApexChartsSample.Shared;
+ using ApexChartsSample.Server.Repositories.Interface;
+ using RestSharp;
+ using Newtonsoft.Json;

namespace ApexChartsSample.Server.Repositories
{
-    public class BoccoServiceRepository
+    public class BoccoServiceRepository : IBoccoServiceRepository
    {
+        // Bocco API リフレッシュトークン
+        private readonly string _refreshToken = "{法人アカウントで割り振られたリフレッシュトークン}";

+        /// <summary>
+        /// Boccoアクセストークンの取得
+        /// </summary>
+        /// <returns>トークンモデル</returns>
+        public async Task<BoccoApiTokenResponse> GetAccessToken()
+        {
+            var restClient = new RestClient();
+            var url = "https://platform-api.bocco.me/oauth/token/refresh";
+            var request = new RestRequest(url, Method.Post);
+            request.AddHeader("Content-Type", "application/json");
+            
+            var body = new { refresh_token = _refreshToken };
+            var bodyJson = JsonConvert.SerializeObject(body);
+            request.AddBody(bodyJson, "application/json");
+            RestResponse response = await restClient.ExecuteAsync(request);
+
+            var model = new ApiTokenModel();
+            var returnModel = new BoccoApiTokenResponse();
+            if (response.IsSuccessful)
+            {
+                model = JsonConvert.DeserializeObject<ApiTokenModel>(response.Content);
+                returnModel.IsSucceed = true;
+                returnModel.ResponseMessage = response.StatusDescription;
+                returnModel.ApiToken = model;
+            }
+            else
+            {
+                model = null;
+
+                returnModel.IsSucceed = false;
+                returnModel.ResponseMessage = response.ErrorMessage;
+                returnModel.ApiToken = model;
+            }
+
+            return returnModel;
+        }
    }
}

補足:Postmanの場合

  • PostmanでRestsharp変換を見ると

image.png

  • AddParameterの記述の仕方等が異なることがわかるかと思います。
  • なので、Postmanでテストしてそのままコードが流用できないのが残念。。。。
Postmanのコード変換機能の場合
var client = new RestClient("https://platform-api.bocco.me/oauth/token/refresh");
client.Timeout = -1;
var request = new RestRequest(Method.POST);
request.AddHeader("Content-Type", "application/json");
var body = @"{""refresh_token"": ""{法人アカウントで割り振られたリフレッシュトークン}""}";
request.AddParameter("application/json", body,  ParameterType.RequestBody);
IRestResponse response = client.Execute(request);
Console.WriteLine(response.Content);

コントローラーの作成

  • *.Serverのプロジェクトを右クリックして、追加 > 新しい項目で「BoccoServiceController」を作成

image.png

  • ちょっと変則な処理ですが、コントローラー側では、GetでRepositoryでは、Postになっているのは、Repository側でPostパラメータを処理しているため、そのような形にしました。
BoccoServiceController.cs
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
+ using ApexChartsSample.Server.Repositories;
+ using ApexChartsSample.Server.Repositories.Interface;
+ using ApexChartsSample.Shared;

namespace ApexChartsSample.Server.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BoccoServiceController : ControllerBase
    {
+        private readonly ILogger<BoccoServiceController> _logger;
+
+        private IBoccoServiceRepository boccoServiceRepository;
+
+        public BoccoServiceController(ILogger<BoccoServiceController> logger)
+        {
+            _logger = logger;
+            this.boccoServiceRepository = new BoccoServiceRepository();
+        }
+
+        /// <summary>
+        /// アクセストークン取得
+        /// </summary>
+        /// <returns></returns>
+        [HttpGet("/GetAccessToken")]
+        public async Task<BoccoApiTokenResponse> GetAccessToken()
+        {
+            var returnModel = new BoccoApiTokenResponse();
+            returnModel = await boccoServiceRepository.GetAccessToken();
+            return returnModel;
+        }
    }
}

ページデザイン

  • デザインを作成
    • MudOverlayは、MudBlazorのページ読み込み時等に使用できるモーダルパーツでLoadingを表示したいときに使用してます。
BoccoSensor.razor(デザイン部分)

@page "/BoccoSensor"

@using ApexChartsSample.Shared

@using RestSharp
@inject RestClient _restClient;
@inject NavigationManager _navigationManager
@inject ISnackbar Snackbar;

<PageTitle>部屋センサー ログ</PageTitle>

<MudText Typo="Typo.h4" GutterBottom="true">部屋センサー ログ</MudText>
<div class="d-flex flex-grow-1 flex-row">
    <MudGrid>
        <MudItem xs="12" >
            <MudPaper Class="d-flex">
                <MudTextField @bind-Value="_accessToken" Label="Read Only" ReadOnly="true" Variant="Variant.Text" />
                <MudButton OnClick="@(() => GetToken())" Variant="Variant.Outlined" Color="MudBlazor.Color.Secondary" Size="Size.Small" >トークン取得</MudButton>
            </MudPaper>
        </MudItem>
    </MudGrid>
</div>

<MudOverlay @bind-Visible="_loading" DarkBackground="true" ZIndex="9999" AutoClose="false">
    <center><MudProgressCircular Color="MudBlazor.Color.Primary" Size="Size.Large" Indeterminate="true"/></center>
    <MudText Typo="Typo.h1" Color="MudBlazor.Color.Dark">Loading...</MudText>
</MudOverlay>
  • 処理部分
BoccoSensor.razor(処理部分)
@code {
+    /// <summary>
+    /// 画面抑止用
+    /// </summary>
+    private bool _loading;
+
+    /// <summary>
+    /// アクセストークン
+    /// </summary>
+    public string _accessToken { get; set; } = String.Empty;
+
+    /// <summary>
+    /// 初期処理
+    /// </summary>
+    /// <returns></returns>
+    protected override async Task OnInitializedAsync()
+    {
+        _loading = true;
+
+        try
+        {
+            await Task.Delay(2000);
+        }
+        catch (Exception ex)
+        {
+            Snackbar.Add(ex.Message, Severity.Error);
+        }
+        finally
+        {
+            _loading = false;
+        }
+    }
+
+    /// <summary>
+    /// アクセストークンの取得
+    /// </summary>
+    /// <returns></returns>
+    private async Task GetToken()
+    {
+        _loading = true;
+        try
+        {
+            var returnModel = new BoccoApiTokenResponse();
+            var url = _navigationManager.BaseUri + "GetAccessToken";
+            returnModel = await _restClient.GetJsonAsync<BoccoApiTokenResponse>(url);
+
+            if(returnModel.IsSucceed == true)
+            {
+                _accessToken = returnModel.ApiToken.access_token;
+                StateHasChanged();
+            }
+        }
+        catch (Exception ex)
+        {
+            Snackbar.Add(ex.Message, Severity.Error);
+        }
+        finally
+        {
+            _loading = false;
+        }
+    }
}
  • ナビゲーションの追加
    • 先ほど作成したページへ遷移できるようにナビゲーションメニューに項目を追加
NavMenu.razor
<MudNavMenu>
    <MudNavLink Href="" Match="NavLinkMatch.All" Icon="@Icons.Material.Filled.Home">Home</MudNavLink>
    <MudNavLink Href="counter" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Add">Counter</MudNavLink>
    <MudNavLink Href="fetchdata" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.List">Fetch data</MudNavLink>
    
+    <MudNavLink Href="BoccoSensor" Match="NavLinkMatch.Prefix" Icon="@Icons.Material.Filled.Sensors">部屋センサー</MudNavLink>
</MudNavMenu>

デバッグ実行

  • デバッグを実行し、ナビゲーションからトークン取得ボタンを押下すると、InputBoxにトークンが無事表示されていることが確認できました。

デバッグ.gif

補足

  • タイトルの部屋センサーの取得までやろうと思ったのですが、一旦トークンの取得までで投稿しました。
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