blazor JSからC#メソッド呼び出し

asp.net core blazorでJavascriptからC#メソッドを呼び出す方法をMSのサイトや、他のサイトで検索した結果、staticメソッドや他クラスインスタンスメソッドを呼び出す方法については書いてあったが、ページクラスのメソッド呼出しについて書いてあるサイトが見つからなかった。

ページクラスのメソッドが呼べれば、クラス変数がそのまま使用できるので、変数とバインドされているHTMLエレメント値を直接いじれるので便利だと思い、色々試してみた。

サイトに書かれていた説明では、呼出されるC#メソッドには[JSInvokable]属性をつける必要がある。これはどのサイトでも同じことが書かれている。

staticメソッドの場合は、 下記のような感じでJavascriptから呼び出すことが可能。

Dotnet.invokeMethod(<アプリ名>,<メソッド名>[,パラメータ1[,パラメータ2...]])
または
Dotnet.invokeMethodAsync(上記と同様)

ただし、staticメソッドなので、バインドされたページインスタンス変数にはアクセスできない。

もう一つ例が載っているのが、ヘルパークラスを介した呼出し。

C#側
var helper = new MyJsHelper();
await JSRuntime.InvokeVoidAsync("JsFunc",
  DotNetObjectReference.Create(helper));

JS側
function JsFunc(helper) {
  helper.invokeMethodAsync(・・・); // invokeMethodも使用可
}

でも、同じようにバインドされたページインスタンス変数にはアクセスできないよね。(もちろん、ページインスタンスをヘルパーインスタンス内に保存すれば大丈夫かもしれないけれど・・・)

で、上記を見てもしかしてと思って以下のようなコードを書いてみた。

C#側
private string Mesg = "";
・・・
[JSInvokable]
public void CSMethod(int p1, double p2, string p3) {
  Mesg = $"p1={p1}, p2={p2}, p3={p3}";
  this.StateHasChanged(); // JSから呼び出された場合は自動更新されないので
}
・・・
  await JSRuntime.InvokeVoidAsync("JsFunc",
    DotNetObjectReference.Create(this), 
    "CSMethod",10,3.14,"Hello");

JS側
function JsFunc(helper,func,p1,p2,p3) {
  helper.invokeMethodAsync(func,p1,p2,p3);
}

見事に動いてくれました。

で、これ使って何をやりたかったかというと、BingMap等のイベントハンドラをC#で書きたかっただけなのです。実際には、ピン等を追加したりするためにJS関数を細切れに作って、C#から呼び出すことになるんだけどね・・・

カテゴリー: asp.net core, Blazor, C#, dotnetcore, 技術系 | 1件のコメント

blazor wasm版の公開

blazor wasm版を公開してみた。
こちらは、blazor Server Side版と異なり、dotnet publishで作成されたフォルダをそのまま、Webサイトにコピーするだけだ。

ただし、Web Assembly(.wasm)のMimeタイプをWebサーバに登録する必要がある。

とりあえず、コピーするフォルダだが、以下となる。

<アプリケーションルート>/bin/Release/<対象フレームワーク>/publish/<アプリケーション名>/dist

このフォルダーの中身を全て、HTTPサーバの公開フォルダにコピーする。

なお、公開する際に気を付けなければいけないのは、wwwroot/index.html中の<basse>タグの扱いだ。デフォルトでは、<base href=”/”>となっていて、HTTPサーバのドキュメントルートを使用する設定になっている。コンテンツの配置先が、サブフォルダの場合、このままでは、ルーティングできないため、エラーとなってしまう。その場合は、<base>タグの値をサブフォルダ込みに変更しよう。

また、HTTPDの設定だが、Apache HTTPDの場合、以下のような設定追加が必要。

    # Mime Typeの追加
    AddType application/wasm .wasm
    AddType application/octet-stream .dll
    # 圧縮の設定(必須ではないが、MSのサイトには例として載っている)
    <IfModule mod_deflate.c>
        AddOutputFilterByType DEFLATE text/css
        AddOutputFilterByType DEFLATE application/javascript
        AddOutputFilterByType DEFLATE text/html
        AddOutputFilterByType DEFLATE application/octet-stream
        AddOutputFilterByType DEFLATE application/wasm
        <IfModule mod_setenvif.c>
            BrowserMatch ^Mozilla/4 gzip-only-text/html
            BrowserMatch ^Mozilla/4.0[678] no-gzip
            BrowserMatch bMSIE !no-gzip !gzip-only-text/html
        </IfModule>
    </IfModule>

以上で、blazor wasm版をHTTPD経由でアクセスする事が可能となる。
ちなみに、今回公開したのは、下記URL。
http://blazor.ohwaki.jp/canvas

以上、blazor Server Side版より簡単に公開可能。

カテゴリー: asp.net core, Blazor, dotnetcore, 技術系 | コメントする

VSCode Remote-SSHでリモートファイル編集

最近、Linux VPS上に(趣味で)でC#コードやHTMLを書く事が多い。

最初はvim等を使っていたが、もう少しいい方法がないものかと探していたら、Windowsクライアントで使用している、VSCodeからSSH経由でリモートファイルの編集が可能な、Remote-SSHという拡張機能を見つけた。

前提条件として、リモート側にVSCodeがインストールされていることと、クライアントからSSH接続が可能なこと。

まず、ローカル側のVSCodeにRemote-SSH拡張機能をインストール。

後は、メニューの[表示]-[コマンドパレット](Ctrl-Shift-p)で、コマンドパレットを開き、Connect to Host…を選ぶと、接続先を聞いてくるので、<リモートのユーザ名>@<ホスト名あるいはIP>と言う形で入力すると、新しいVSCodeウィンドウが開き、リモートユーザのパスワードを尋ねてくるので、パスワードを入力すればリモートとの接続が完了し、リモートファイルやリモートディレクトリの編集が可能となる。

なお、接続する、「リモートユーザ@ホスト名」は保存することが可能。

リモートのVSCodeに拡張機能を入れておけばコンパイルやデバッグも可能となる。

カテゴリー: 技術系 | コメントする

blazor server sideアプリをCentOS7+Apacheで公開してみた

以前にも書いたとおり、dotnet core 3からblazor server sideアプリが正式サポートされるようになった。残念ながら、wasm版は3.1からのサポートとなる。(βでは動作確認済み)

で、blazorというかaps.net coreのアプリを実環境に公開してみたくなったので、色々調べてみた。

まず、このブログが動いている、VPSはCentOS6なので、dotnet core 3は動作しない。仕方ないので、CentOS7のVPSを別途契約。

そのVPS上にdotnet core 3 sdkを導入後、簡単なblazor server sideアプリを作成。
dotnet runで開発モードにて動作確認後、下記コマンドでリリース版を作成。

dotnet publish --configuration Release

これで、bin/Release/<target framework>/publishフォルダにアプリケーションがビルドされる。ビルドされたフォルダ中に、<プロジェクト名>.dllが作成されるので、下記コマンドで動作する事を確認する。

dotnet <プロジェクト名>.dll

何も設定せずに動かしてみると、http://localhost:5000およびhttps://localhost:5001でListenしている。待受けアドレスやポートを変更するには、同一フォルダ中のappsetting.jsonに下記セクションを加えるのが簡単な方法だ。

  "Kestrel" : {
    "EndPoints" : {
        "Http" : {
          "Url" : "http://・・・:<待受けポート番号>"
        }
    }
  },

これを外部に公開するのだが、今回はapache httpdのvirtual host機能と、proxyおよびURL書換機能を利用して公開することにした。(一番簡単だと思う)

Kestrelの待受けURLをhttp://localhost:5000とした場合、以下のように設定したconfファイルを/etc/httpd/conf.dに置いてhttpdをリスタートしよう。

# URLで宛先切替
# 一般ホームページ用
<VirtualHost *:80>
        DocumentRoot /var/www/html
        ServerName www.hoge.jp
</VirtualHost>
# asp.net coreアプリ用
# URLの書換はblazor server sideアプリがSignalRを使用するために必要
# 最初、これが無かったので、ページは表示されるけど、イベントが
# ハンドリングされなかった・・・
<VirtualHost *:80>
        ServerName aspcore.hoge.jp
        ProxyPass / http://localhost:5000/
        ProxyPassReverse / http://localhost:5000/
        RewriteEngine on
        RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
        RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
        RewriteRule /(.*) ws://127.0.0.1:5000/$1 [P]
</VirtualHost>

とりあえず、この状態で、dotnet <プロジェクト名>.dllでアプリを実行、外部からアクセスしてみると、ちゃんと動作。
設定ファイルのコメントにも書いてあるけど、最初ProxyPassとProsyReversePassだけ設定して動かしたら、ページ自体は表示されたけど、イベント処理がNG。書換ルール追加を忘れないように(汗)

とりあえず、疎通はうまくいったので、アプリをサービス化しよう。
方法は https://docs.microsoft.com/ja-jp/aspnet/core/host-and-deploy/linux-apache?view=aspnetcore-3.0 などに書かれているように、 /etc/systemd/system にサービス定義ファイルを作成して、サービスを開始してあげればOK。

[Unit]
Description=サービスの説明

[Service]
WorkingDirectory=<作業ディレクトリ>
ExecStart=/usr/bin/dotnet <dllのフルパス>
Restart=always
# Restart service after 10 seconds if the dotnet service crashes:
RestartSec=10
KillSignal=SIGINT
SyslogIdentifier=<Syslogに書き出すときのprefix>
User=apache
Environment=ASPNETCORE_ENVIRONMENT=Production 

[Install]
WantedBy=multi-user.target

ちなみに、上記リンクのdotnetパスは/usr/local/binとなっているが、普通にdotnet core sdkをインストールすると、/usr/binにdotnetコマンドが置かれるようだ。
サービス定義後、下記コマンドでサービスを有効化して、起動、状態確認を行う。

# systemctl enable <サービスファイル名>
# systemctl start <サービスファイル名>
# systemctl status <サービスファイル名>
● <サービスファイル名> - <サービス説明>
   Loaded: loaded (/etc/systemd/system/<サービスファイル名>; enabled; vendor preset: disabled)
   Active: active (running) since ・・・ ago
 Main PID: 9999 (dotnet)
   CGroup: /system.slice/<サービスファイル名>
           mq7906 /usr/bin/dotnet <DLLフルパス>

これで、一応公開完了。
実際には結構色々なところで躓いているので、備忘録的に投稿してみた。

ちなみに、公開したページは以下のリンクから参照可能。
http://dnetapp.ohwaki.jp/gradation

カテゴリー: asp.net core, Blazor, C#, dotnetcore, 技術系 | コメントする

asp.net core 3.1 preview 2 – blazor wasm app

dotnet core 3.1 previewでWeb Assemblyのみで動作する、Blazor WebAssembly Appが開発できるようになった。

dotnet core 3.0まではBlazor Server Appつまり、サーバーサイドで、.netの処理を行い、クライアント(ブラウザ)と通信を行って、結果を表示する方式のものしか開発できなかったのだが、Blazor WebAssembly Appでは、サーバーにアクセスするのは、ページロード時のみで、ページが読み込まれた後は全てクライアント側のWebAssembly中で処理が行われる。

Server AppとWebAssembly Appのソースは基本的に互換性があるようだ。(ただし、.netライブラリによってはサポートされないものもある)

試しに、Server Appのrazorページをコピーしてみたら、キチンと動作した。

Server Appと比べてbuildに時間がかかるのと、生成されるWebAssemblyのサイズが大きいためか、最初のページローディングには少々時間がかかる点が気になるが、一度ローディングしてしまえば、クライアント側で全て処理するので、処理している間にWebサーバーが落ちてしまっても問題無い。(実際にロード後にサーバーを落としてみたが、問題無く動作した。)

結構面白い技術だね。

カテゴリー: asp.net core, Blazor, C#, dotnetcore, 技術系 | 1件のコメント

ASP.NET Core,Blazorのレイアウト

以前、Blazorの記事を書いたが、dotnet core 3.0が正式にリリースされたので、Blazorに関しても色々といじくり回している。

Blazor等ASP.NET Coreのアプリをテンプレートから作成すると、Navigationメニュー付きの画面になってしまうが、これを変更するには、デフォルトのテンプレートを編集するか、別のテンプレートを作成して、ページ内でレイアウトテンプレートを指定する。

テンプレートはASP.NET Coreの場合とBlazorの場合ではレイアウトファイル名やフォルダが異なる。

ASP.NET Coreアプリの場合
・場所
<プロジェクトルート>\Pages\Shared
・ファイル名
_Layout.cshtml

Blazorの場合
・場所
<プロジェクトルート>\Shared
・ファイル名
MainLayout.razor

これらのファイルを直接変更すると、ページソースを変更しなくてもレイアウトを変更できる。

ちなみに、ページ毎に別のレイアウトを作成したい場合は、上記のフォルダにレイアウトファイルを作成して、ページ記述(.cshtmlや.razor)中に@layoutで指定する事が可能。
例えば、ASP.NET Coreアプリで\Pages\Shared\MyLayout.cshtmlを作成して、それをページに適用したい場合は、ページ中に@Layout=”MyLayout”とすれば良い。

カテゴリー: asp.net core, Blazor, C#, dotnetcore, 技術系 | 1件のコメント

dotnetcore

最近、dotnetcoreで遊んでいる。
最初はBlazorを試すためだけにインストールしたのだが、元々、dotnetcoreでの開発をしたことが無かったので、色々試してみた。

基本的には、dotnetコマンドで全て行う。
まず、プロジェクトの作成。

dotnet new プロジェクトの種類 -o プロジェクト名

上記で指定したプロジェクト名のフォルダが作成され、その下に必要なライブラリ等が格納される。
nugetのパッケージをプロジェクトにインストールするなら、下記コマンドで、OK。

dotnet add プロジェクト名 package パッケージ名

プロジェクトフォルダ中には、プロジェクト種別によってスケルトンプログラムが作成されているので、これを編集しても良いし、不要なモノを削除したり、新規にファイルを作成してもよい。プログラムの編集が終了したら、プロジェクトフォルダ直下で、下記コマンドを実行すると、プログラムがコンパイル後、起動される。(コンパイルエラーの場合はエラーメッセージと修正して同じコマンドを打つようメッセージが表示される。)

dot net run

以上、簡単だが、dotnetcoreを使用した開発方法の紹介。

カテゴリー: C#, dotnetcore, 技術系 | コメントする

Blazor

dotnet core 3.0のプレビュー版で、Blazorが使えるようになったので試してみる。
BlazorとはRazor記法とC#コードからWeb Assembly(専用Binayコードを実行する仕組み)を使用したWebアプリを生成するもの。

作成したアプリは、Web Assemblyをサポートするブラウザ上で実行可能である。IEを除いたメジャーなブラウザのほぼ全てで動作する。

簡単なコードを見てみよう。以下は、名前を入力して、ボタンをクリックすると、「ようこそ、[名前]さん。」と表示されるアプリ。RazorとC#を使用して作成している。なお、これらは全てクライアント(ブラウザ)上で動作する。

input type=”text”タグの値をC#上のyourNameと@bindで結びつけているため、ここに入力された値はボタンのクリックイベントが発生した時点でyourName変数に代入される。
ボタンのアクションには@onclickでC#のメソッドを指定している。(ここでは特に処理を子なっていないが・・・)
その下のif文で、入力があった場合は、メッセージを出力するようなコードとなっている。

@code {・・・}の部分はC#でロジックを書き込むところ。このページで使用するインスタンス変数や、イベントハンドラなどをコーディングする。

以下が、実行結果(Edgeで試した)

初期状態
名前を入力して、ボタンをクリック

簡単な例だが、javascriptを使用せずに、C#だけで書けるのはありがたい。なお、.NET Frameworkのライブラリも(どの程度かは分からないが)使用可能。
少なくとも、System.Net.Http.HttpClientは使用できた。
つまり、HTTPサーバと通信して、値を貰うようなアプリも作成できる。

HttpClientを使用した例

結構使えそうなので、正式版が出るのが待ち遠しい。

カテゴリー: Blazor, C#, 技術系 | 1件のコメント

Javaのvarを使った変数型推論宣言

JDK10から使えるようになったvarによる型推論変数宣言(言い方がこれで良いのかどうか分からない)だけど、JDK10からなそうのか試していないが、JDK12ではチョット厭らしい事が出来てしまうようだ。
本来なら、以下のような構文はエラーとして欲しいと思うんだけど・・・

int num = Integer.parseInt(args[0]);
var x = switch(num) {
case 0 -> “Zero”;
case 1->1;
default -> “Many”;
}; // 結果が整数又は文字列

xの型が、実行時まで決まらないというのは如何な物だろうか?バグの温床となりそうな気がするのだが・・・
(JavascriptのvarやVBのdimのみ(variant型)と同じイメージだよね?)

なお、C#では同様の構文はコンパイルエラーとなる。同じ事をやりたければ、dynamicを使用する必要がある。

カテゴリー: java, 技術系 | 2件のコメント

Swift

Apple嫌いだから、無視してたんだけど、まぁ、どんな言語か位は見てみようかと・・・

とりあえず、Windows on Linux(Ubuntu)で動かしてみたが、REPLが動いてくれない。

仕方ないので、普通にソースを喰わせて実行してみた。

以下、感想等。

  1. Swifにはクラスは存在する。継承も可能。
  2. 恐ろしいことに、配列は値型!参照(ポインタ)では無い。
  3. 変数,定数は基本、nil(null)の代入が禁止されている。
  4. nil許容型はunboxingしないとコンパイルエラーになる。面倒。
  5. 引数は基本名前付きで呼び出し。面倒。

iXXX用のアプリ作る気ないし、まぁ、ほぼ使うことは無いだろう。

swiftサンプル

swiftサンプル

 

カテゴリー: その他言語, 技術系 | コメントする