FlexGridでオープンデータを表示する(ローカルWeb APIの作成まで)
FlexGridを利用して、次のようなページを作成します。
新型コロナウイルス関連のオープンデータとして「COVID-19 Japan Web API」で提供されている都道府県毎の感染者数を利用しています。
プロジェクトの新規作成
Visual Studioを起動して、新しいプロジェクトの作成を選択し、プロジェクトテンプレートとして、Blazor WebAssemblyアプリを選択します。プロジェクト名(BlazorAppCovid19)を設定した後、次の追加情報ダイアログでは、ターゲットフレームワークを.NET5.0にして、「ASP.NET Coreでホストされた」に必ずチェックを入れます。
「ASP.NET Coreでホストされた」にチェックを入れると、生成されるソリューションには、Blazorアプリ単体(BlazorAppCovid19.Client)、ASP.NET Core(BlazorAppCovid19.Server)、さらにソリューション全体で共有するクラスを定義するプロジェクト(BlazorAppCovid19.Shared)と、3つのプロジェクトが生成されます。
今回は外部サイトのWebAPIを利用しますが、その場合、同一生成元ポリシー(Same-Origin Policy)という考え方に基づき、ブラウザ上で動作するプログラムでは、異なるサイトのアクセスが制約されることがあります。これはセキュリティ攻撃を防止するためのもので、回避するにはサイト側でアクセスを許可する設定(CORS、Cross-Origin Resource Sharingと呼ばれる仕組み)が必要となります。
そのため、Blazorアプリ単体で直接アクセスするのではなく、ローカルでASP.NET CoreのWeb APIサーバーを作成し(ASP.NET Core hosted)、ASP.NET Coreで外部WebAPIを参照するようにします。ASP.NET Coreのプログラムでは、外部サイトのアクセスに制限はありません。Blazorアプリは、ローカルのWeb APIを通じて、外部サイトとアクセスする形になります。
なお今回のソリューションファイルのうち、編集、追加するファイルは以下の通りです。
BlazorAppCovid19.Client
- \wwwroot\index.html:トップページ(編集)
- \Shared\NavMenu.razor:各ページに遷移するメニュー(編集)
- \Pages\PrefecturesSum.razor:都道府県毎の累計グリッド表示(新規)
- \Pages\Chart.razor:東京都の日別感染者数グラフ表示(新規)
BlazorAppCovid19.Server
- \Controllers\Covid19Controller.cs:Web API(コントローラー)クラス(新規)
BlazorAppCovid19.Shared
- \Covid19.cs:共有オブジェクトの定義(新規)
プロジェクトにパッケージを組み込む
プロジェクトのひな形が作成できたところで、プロジェクトにFlexGrid、FlexChartのパッケージをNuGetを使って組み込みます。Visual Studioのソリューションエクスプローラーで、先頭のソリューションを選択して右クリックし、表示されたメニューから[ソリューションのNuGet パッケージの管理]を選びます。そして参照タブをクリックし、「C1.Blazor.Grid.Ja」を検索します。右ペインのプロジェクトで、ClientとServerにチェックして、インストールボタンをクリックします。同様に、「C1.Blazor.Chart.Ja」もインストールします。
次に、プロジェクトのwwwrootフォルダにある、index.htmlを開き、<head>タグ内にCSSファイルと、<body>タグ内の最後にJavaScriptファイルのURLを追加します。
~略~ <link rel="stylesheet" href="/_content/C1.Blazor.Core/styles.css" /> <link rel="stylesheet" href="/_content/C1.Blazor.Grid/styles.css" /> <link rel="stylesheet" href="/_content/C1.Blazor.ListView/styles.css" /> <link rel="stylesheet" href="/_content/C1.Blazor.Input/styles.css" /> </head> ~略~ <script src="/_content/C1.Blazor.Core/scripts.js"></script> <script src="/_content/C1.Blazor.Input/scripts.js"></script> <script src="/_content/C1.Blazor.Grid/scripts.js"></script> <script src="/_content/C1.Blazor.Chart/scripts.js"></script> </body> ~略~
FlexGridで表示するオブジェクトの定義
今度は、FlexGridで表示するデータを準備します。FlexGridのデータソースとしては、配列やListオブジェクトを設定することができます。ここでは、都道府県毎の累計数を示すエンティティクラスPrefectureListを定義しました。陽性率などは、プロパティを使って計算した値を返すようにしています。
~略~ // 都道府県毎の累計 public class PrefectureList { public string Name_ja { get; set; } // 都道府県 public int Population { get; set; } // 人口 public int Cases { get; set; } // 陽性者数 public int Deaths { get; set; } // 死亡者数 public int Pcr { get; set; } // 検査数 public int Hospitalize { get; set; } // 入院患者数 public int Severe { get; set; } // 重症者数 // 陽性率 public float Positive_rate => Cases * 100f / Pcr; // 死亡率 public float Deaths_rate => Deaths * 100f / Cases; // 人口10万人あたりの陽性者数 public float CasesHt => Cases * 100000f / Population; } ~略~
このクラスを定義するファイルは、Blazorアプリ単体とASP.NET Coreサーバーで共通して利用できるように作成します。ソリューションエクスプローラーで、プロジェクト名.Sharedフォルダを選択して、右クリックして表示されるメニューから、[追加]-[新しい項目]を選びます。次にクラスを選択し、ファイル名(本記事ではCovid19.cs)を入力して追加します。
ローカルのWeb APIを作成する
次は、このPrefectureListの配列をJSONデータとして返すWeb APIを作成しましょう。ASP.NET Coreサーバープロジェクトに処理を追加します。大部分は、ひな形のフレームワーク(ASP.NET Core Web API)でまかなえますので、追加するコードは多くありません。
ソリューションエクスプローラーで、プロジェクト名.ServerにあるControllersフォルダを選択して、右クリックして表示されるメニューから、[追加]-[コントローラー]を選びます。
次の画面では、APIコントローラー-空を選択して、追加ボタンをクリックします。さらにファイル名(Covid19Controller.cs)を入力して、追加ボタンをクリックします。追加されるファイルは、ControllerBaseクラスを継承した、Web APIのコントローラークラスです。クラスの内容を次のように変更します。
~略~ [ApiController] [Route("api/[controller]")] public class Covid19Controller : ControllerBase { static readonly HttpClient Client = new HttpClient(); // 外部APIのJSONデータ参照用クラス private class Prefecture { ~略~ } ~略~ [Route("Prefectures")] public IEnumerable<PrefectureList> GetPrefectures() { // JSONデータをPrefectureオブジェクトの配列に変換する(1) var prefecture = Client.GetFromJsonAsync<Prefecture[]>( "https://covid19-japan-web-api.now.sh/api/v1/prefectures").Result; var list = new List<PrefectureList>(); foreach (Prefecture p in prefecture) { // PrefectureListオブジェクトに変換する(2) list.Add(new PrefectureList { Name_ja = p.name_ja, Pcr = p.pcr, Cases = p.cases, Deaths = p.deaths, Hospitalize = p.hospitalize, Severe = p.severe, Population = p.population }); } return list; } } ~略~
都道府県毎の感染者数APIからは、次のようなJSONデータが返却されるので、GetFromJsonAsyncメソッドを使って、いったんC#のオブジェクト(Prefecture[])に変換します(1)。
[ { "id":1, "name_ja":"北海道", "name_en":"Hokkaido", "lat":43.46722222, "lng":142.8277778, "population":5248552, "last_updated":{ ~略~ }, "cases":18674, "deaths":647, "pcr":361220, "hospitalize":798, "severe":13, "discharge":17229, "symptom_confirming":0 }, ~略~
その後に必要なデータのみを参照して、PrefectureListオブジェクトに変換します(2)。
Prefectureクラスは、一時的にJSONデータを保持するためのエンティティクラスで、Visual Studioの機能を利用して作成可能です。このAPIのURLをブラウザ等でアクセスし、得られたJSONデータをコピーします。そして、Visual Studioの編集メニューから、[形式を選択して貼り付け]-[JSONをクラスとして貼り付ける]を選ぶと、JSONデータの内容に応じたエンティティクラスが自動で生成できます。
なお、コントローラークラスのメソッドのルーティングは、Route属性で指定しています。GetPrefecturesメソッドは、[https://localhost:44383/]api/covid19/prefecturesというURLで呼び出されるようになります。またこのメソッドでは、単にListオブジェクトを返しているだけですが、これだけでJSON文字列を返すWeb APIとなります。