検索
リンク
タグ
ASP.NET
.NET
ASP.NET MVC
F#
Visual Studio
Azure
ASP.NET Core
ライトニングトーク
Plone
Selenium
AJAX
C#
jQuery
SQL Server
ADO.NET Entity Framework
JavaScript
WebMatrix
EFCore
LINQ
Fizz-Buzz
カテゴリ
最新の記事
最新のコメント
記事ランキング
最新のトラックバック
以前の記事
2024年 03月 2024年 02月 2024年 01月 2023年 12月 2023年 11月 2023年 10月 2023年 09月 2023年 08月 2023年 07月 2023年 06月 2023年 05月 2023年 04月 2023年 03月 2023年 02月 2023年 01月 2022年 12月 2022年 11月 2022年 10月 2022年 09月 2022年 08月 2022年 07月 2022年 06月 2022年 05月 2022年 04月 2022年 03月 2022年 02月 2022年 01月 2021年 12月 2021年 11月 2021年 10月 2021年 09月 2021年 08月 2021年 07月 2021年 06月 2021年 05月 2021年 04月 2021年 03月 2021年 02月 2021年 01月 2020年 12月 2020年 11月 2020年 10月 2020年 09月 2020年 08月 2020年 07月 2020年 06月 2020年 05月 2020年 04月 2020年 03月 2020年 02月 2020年 01月 2019年 12月 2019年 11月 2019年 10月 2019年 09月 2019年 08月 2019年 07月 2019年 06月 2019年 05月 2019年 04月 2019年 03月 2019年 02月 2019年 01月 2018年 12月 2018年 11月 2018年 10月 2018年 09月 2018年 08月 2018年 07月 2018年 06月 2018年 05月 2018年 04月 2018年 03月 2018年 02月 2018年 01月 2017年 12月 2017年 11月 2017年 10月 2017年 09月 2017年 08月 2017年 07月 2017年 06月 2017年 05月 2017年 04月 2017年 02月 2017年 01月 2016年 12月 2016年 11月 2016年 10月 2016年 09月 2016年 08月 2016年 07月 2016年 06月 2016年 05月 2016年 04月 2016年 03月 2016年 02月 2016年 01月 2015年 12月 2015年 11月 2015年 10月 2015年 09月 2015年 08月 2015年 07月 2015年 05月 2015年 04月 2015年 03月 2015年 02月 2015年 01月 2014年 12月 2014年 11月 2014年 10月 2014年 09月 2014年 08月 2014年 06月 2014年 04月 2014年 03月 2014年 02月 2014年 01月 2013年 12月 2013年 10月 2013年 09月 2013年 08月 2013年 07月 2013年 06月 2013年 05月 2013年 04月 2013年 03月 2013年 02月 2013年 01月 2012年 12月 2012年 11月 2012年 10月 2012年 09月 2012年 08月 2012年 07月 2012年 06月 2012年 05月 2012年 04月 2012年 03月 2012年 02月 2012年 01月 2011年 12月 2011年 11月 2011年 10月 2011年 09月 2011年 08月 2011年 07月 2011年 06月 2011年 05月 2011年 04月 2011年 03月 2011年 02月 2011年 01月 2010年 12月 2010年 11月 2010年 10月 2010年 09月 2010年 08月 2010年 07月 2010年 06月 2010年 05月 2010年 04月 2010年 03月 2010年 02月 2010年 01月 2009年 12月 2009年 10月 2009年 09月 2009年 07月 2009年 06月 2009年 05月 2009年 04月 2009年 03月 2009年 02月 2009年 01月 2008年 12月 2008年 11月 2008年 10月 2008年 09月 2008年 08月 2008年 07月 2008年 06月 2008年 05月 2008年 04月 2008年 03月 2008年 02月 2008年 01月 2007年 12月 2007年 11月 2007年 04月 2007年 03月 2007年 02月 2007年 01月 2006年 11月 2006年 10月 2006年 09月 2006年 08月 2006年 07月 |
2018年 02月 27日
シナリオ.NET 版 Web アプリサーバー側フレームワークである ASP.NET Core で実装したWebアプリにおける、サーバー側からもクライアント側への呼び出しを行なうことのできる "Real time Web" 実装、ASP.NET Core SignalR。 今回はその ASP.NET Core SignalR を使っていて遭遇したトラブルとその回避方法の話である。 下記記事のコード例を基に話を進めよう。 但し、上記記事のコード例では、単一文字列を送受信していたところを、文字列の配列に変えてみたのが、今回のテーマ。 サーバー側実装は、上記記事のコード例に対し、下記強調表示のとおり書き換える。
すなわち、クライアント側からサーバー側へ送信された文字列の配列を、そのまま文字列の配列のまま、クライアント側に送り返す実装だ。 クライアント側も同様に下記要領で、SignalR 接続が開設したら、単一文字列 "Hello" を送信していたところを、["Hello", "World"] の文字列の配列を送信するようにする。 且つ、受信した内容を console.log で開発者コンソールに表示する際に、合せてその受信内容の型も表示するようにしてみる。
さて、このように手を加えたサンプルコードを実行、ブラウザで開くと、サーバー側からクライアント側に送信された内容が開発者コンソールに表示される。 その内容の期待値は、文字列の配列を送受信しているわけだから、当然下記のようなものとなる。
ところが実際にやってみると、その実行結果は下記のとおりとなった。
サーバー側からは文字列の配列をクライアント側へ送信しているのに、それを受け取ったクライアント側では、なぜか第1要素のみが受信ハンドラの引数に渡されているのである。 これはおかしいと、ブラウザの開発者コンソールにて通信内容を確認してみた。 すると、なんと、下図(蛍光マーカー表示の箇所)のとおり、サーバー側からは単一文字列が2引数で送信されているように見える。当方の期待するところとしては、ここは ["Hello", "World"] ではなく、[ ["Hello", "World"] ] である。 原因原因は、サーバー側実装にあった。 SignalR における、サーバー側からクライアント側への送信に用いる InvokeAsync メソッドなのだが、これが可変個引数を扱うために object[] を引数にとるようになっている (下記)。
このため、愚直に配列をクライアント側へ送信しようと思って InvokeAsync メソッドの第二引数に渡すと、 配列を引き渡したいつもりが可変個引数として扱われてしまっていた という訳だ。 ちなみに、InvokeAsync メソッドには拡張メソッドによるオーバーロードバージョンも用意されている (下記)。
このオーバーロードバージョンによって、n 個引数での InvokeAsync 呼び出しの際、 InvokeAsync("method", new object[]{ "taro", 24 })と書かずに InvokeAsync("method", "taro", 24)と略して書けるようになっている。 回避方法回避方法はいくつかある。 「可変個引数のうち、第一引数に、文字列の配列を渡しますよ」ということを、略記せずにきっちり記述することで回避できる。
いちばん直球勝負で正直な実装方法だが、ちょっとくどい。 あるいはまた、「object[] args」のシグネチャにマッチするのを回避しつつ、クライアント側 JavaScript では配列として扱われる List<T> に変換してから渡す方法もある。
いったん List<T> を生成するのでメモリ効率的に気持ち悪いが。 はたまた、「object[] args」のシグネチャにマッチしなければよいので、InvokeAsync(string, object arg1, object arg2) などにマッチするよう、ダミーの引数を付加することもできよう。
しかし、前者でさえ「なぜわざわざ List<T> にするの?」という点で可読性低いのに、このダミー引数版はさらに可読性ダダ下がりな感じで、個人的には採用したくない手法。 「object[] args」のシグネチャにマッチしないようにオーバーロードバージョンの使用を誘導するのであれば、as 演算子で型を指定することもできる。
クライアント側実装もあわせて変えてよければ、同じく「object[] args」のシグネチャにマッチしないよう、匿名型オブジェクトにくるむ方法もある。
クライアント側はこうなる。
ざっと思いつく回避方法はこんなところだ。 ちなみに可変個引数は、例えば string.Format メソッドとかをはじめ、いろいろなところでよく使われる一般的な技法ではある。 ただ、例えば string.Format では配列を書式化したいとかいう需要がさほどないであろうから、そんな感じであまり問題にはならないのだろう。 まとめ以上、こんな感じで回避はできる。 とはいえ、やっぱり「なんでそのまま引数に渡さずにコネコネしてるの?」というように可読性は低いし、将来の保守で壊してしまったり、あるいは新規実装でもたびたびこのワナに陥りそうでちょっと嫌ではある。 ということで、この件は GitHub 上の Issue でもちょうど検討中らしい。 ASP.NET Core SignalR は、まだ Alpha バージョンである。 この件に関しても今後、何かしら変更や改善など進展が見られるかもしれない。 注目しておこうと思う。
by developer-adjust
| 2018-02-27 12:39
| .NET
|
Comments(0)
|
ファン申請 |
||