アーカイブ

投稿者アーカイブ

Antaris/RazorEngine は Windows 環境以外サポートしていない?

LinuxのDockerコンテナで動かしたら、こんな例外が発生しました。

RazorEngine.Templating.TemplateCompilationException : Errors while compiling a Template.
Please try the following to solve the situation:
* If the problem is about missing/invalid references or multiple defines either try to load
the missing references manually (in the compiling appdomain!) or
Specify your references manually by providing your own IReferenceResolver implementation.
See https://antaris.github.io/RazorEngine/ReferenceResolver.html for details.
Currently all references have to be available as files!
* If you get ‘class’ does not contain a definition for ‘member’:
try another modelType (for example ‘null’ to make the model dynamic).
NOTE: You CANNOT use typeof(dynamic) to make the model dynamic!
Or try to use static instead of anonymous/dynamic types.
More details about the error:
– warning: (6, 4) Unnecessary using directive.
– warning: (5, 4) Unnecessary using directive.
– warning: (9, 4) Unnecessary using directive.
– warning: (7, 4) Unnecessary using directive.
– warning: (8, 4) Unnecessary using directive.
– error: (0, 0) Unexpected error writing debug information — ‘COM Interop is not supported on this platform.’
Temporary files of the compilation can be found in (please delete the folder): /tmp/RazorEngine_xbytpgsp.sjz
The template we tried to compile is:

ん?

Unexpected error writing debug information — ‘COM Interop is not supported on this platform.’

RazorEngine の issue を見ると出てますね。
https://github.com/Antaris/RazorEngine/issues/539

とりあえず他のテキストテンプレートエンジンを探します。
しかし、どこにCOMの相互運用なんて使うんだろう。

広告
カテゴリー:ASP.NET, Docker

NSwagを使って、OpenIdConnectのリクエストを投げる

Docs の内容のそのまま実装すると、バージョンが微妙に古いらしく警告が出るのと、認証が必要なAPIの定義方法が書いていなかったのでメモです。

はじめに

ASP.NET WebApi のコントローラー定義をもとに OpenAPI 形式のドキュメントを出力してくれる拡張としては、Swashbuckle が有名ですが、NSwag という拡張もあります。

Microsoft Docs NSwag と ASP.NET Core の概要
https://docs.microsoft.com/ja-jp/aspnet/core/tutorials/getting-started-with-nswag?view=aspnetcore-2.2

<

h3>認証の概要

<

h3>
WebAPI を呼び出すSPAがこんな感じで OpenId Connect のサーバーにトークンを要求しているとして、

http://localhost:5000/auth/connect/authorize?client_id=test.app&redirect_uri=http%3A%2F%2Flocalhost%3A5012%2Fcallback.html&response_type=id_token%20token&scope=openid%20profile%test.api&state=4d76e302ed5742afaff207b1aee6710e&nonce=ead99dbe46d442d18c72f3691f2766ca

ここでは http://localhost:5000 が認証サーバーで、http://localhost:5012 が認証を受けるリソースサーバー(本来はSPAがこれに当たるけれど、今回はSwaggerがSPAの代わりに認証を受けるのでWebApi サーバーとイコール)になります。

SPA を想定しているので、レスポンスタイプは implicit(id_token token) を指定しています。
また、WebAPI は test.api というリソースとして定義しているので、scope に test.api を含めています。

SPA は認証サーバーから返ってきた IDトークン を HTTPヘッダー に乗せるいつものやつですね。

<

h3>パッケージの参照

<

h3>
WebAPI側は次の2つのパッケージを参照します。

dotnet add package IdentityServer4.AccessTokenValidation --version 2.7.0
dotnet add package NSwag.AspNetCore --version 12.0.14

<

h3>JWTの検証設定

<

h3>
JWT の検証は Startup.cs の ConfigureServices メソッドで下記のように定義されているとします。

services.AddAuthentication("Bearer")
    .AddIdentityServerAuthentication(options =>
    {
        options.Authority = "http://localhost:5000";
        options.RequireHttpsMetadata = false;
        options.ApiName = "test.api";
        options.ApiSecret = "test.api.secret";
    });

<

h3>NSwagの設定

<

h3>
NSwag も JWT の検証と同じように Startup.cs の ConfigureServices メソッドで下記のように設定します。
注意点としては、Scope に WebApi のリソース名を入れてあげるのと、クライアントで指定したレスポンスタイプに応じた Flow を設定することですかね。

services.AddOpenApiDocument(config =>
{
    config.OperationProcessors.Add(new OperationSecurityScopeProcessor("oauth2"));
    config.DocumentProcessors.Add(new SecurityDefinitionAppender("oauth2",
        new SwaggerSecurityScheme
        {
            Type = SwaggerSecuritySchemeType.OAuth2,
            Flow = SwaggerOAuth2Flow.Implicit,
            AuthorizationUrl = $"http://localhost:5000/connect/authorize",
            Scopes = new Dictionary
            {
                { "test.api", "test.api" },
                { "openid", "openid"},
                { "profile", "profile"},
            }
        }));
});

ConfigureServices で設定が終わっているので、Configure メソッドで追加の定義をします。
クライアントで要求したClientIdと同じものをセットするようにします。
微妙に非推奨なI/Fが多くて困りました。

app.UseSwagger(); 
app.UseSwaggerUi3(settings =>
{
    settings.OAuth2Client = new OAuth2ClientSettings
    {
        AppName = "DemoApi",
        ClientId = "test.spa"
    };
});
カテゴリー:ASP.NET

Visual Studioでdockerコンテナのデバック中にError: 。というエラーでデバックが開始できない。

もう少し情報を出してほしいですよね。。。

0>C:\Program Files (x86)\Microsoft Visual Studio\2017\Enterprise\MSBuild\Sdks\Microsoft.Docker.Sdk\build\Microsoft.VisualStudio.Docker.Compose.targets(310,5): Error: 。
トラブルシューティング情報の詳細については、http://aka.ms/DockerToolsTroubleshooting をご覧ください

一応このトラブルシュートに飛ばされます。
ここで挙げられているUserProfile以下のファイルをリネームなどを行ったけれど解決せず。
https://docs.microsoft.com/ja-jp/visualstudio/containers/vs-azure-tools-docker-troubleshooting-docker-errors?view=vs-2017

単品で docker-compose build をすると、正常に終わり、up も問題なくできて動く。
Visual Studioからデバックした時だけの問題っぽい。
今回の docker-compose にはソリューション内で作ったASP.NET Coreのコンテンが5つと、MySQL, Redis用のコンテナの7つからできているんだけれど、どこのコンテナが悪いかわからないので、とりあえずすべてコメントした上で、一つづつコメントを解除していく。

結局、前回話題にした alpineコンテナ をベースにしているDockerファイルが残っていたのが原因でした。

カテゴリー:ASP.NET, Docker

Docker(もしくはdocker-compose) build時に、apk add が失敗する場合は、少し待つかDockerを再起動するか、DockerのDNS設定をFixed 8.8.8.8固定にする。

2019年2月11日 1件のコメント

Docker buildしたら、こんなエラーが出た。

Step 2/17 : RUN apk add –no-cache –virtual .gyp python make g++ && apk –no-cache add avahi-dev
—> Running in ae00cbf46192
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.8/main/x86_64/APKINDEX.tar.gz: temporary error (try again later)
fetch http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz
WARNING: Ignoring http://dl-cdn.alpinelinux.org/alpine/v3.8/community/x86_64/APKINDEX.tar.gz: temporary error (try again later)
ERROR: unsatisfiable constraints:

apk でインストールしようとしているパッケージが見つからないらしい。
試しに chrome で上記のURLからパッケージをダウンロードすると、普通にダウンロードできる。

検索すると docker-alpine の issue が引っかかる。
https://github.com/gliderlabs/docker-alpine/issues/279

ミラーが落ちてるから少し待てとか、DNSのキャッシュがとか話が出てくる。
少し待ってから改めてビルドしても同じ現象になるので、Dockerのサービスを再起動したら先に進んだ。

カテゴリー:Docker

Windows で git から clone したファイルをもとに docker build したコンテナを実行すると docker run したときに no such file or directory になる場合は、git の改行コード自動変換機能を確認する。

タイトルのままだけれど、git から clone したソースコード一式を docker build して docker run するとこんなメッセージが表示される。
standard_init_linux.go:207: exec user process caused “no such file or directory”

コンテナの中に入っても対象のファイルはあるのに、、、

docker の issue をみると、git の自動改行コード変換が問題では?とのこと
https://github.com/docker/labs/issues/215

git config --global core.eol lf
git config --global core.autocrlf input

なおった

カテゴリー:Docker, Git

microsoft/dotnet:2.1-aspnetcore-runtime-alpine を基にしたコンテナを、Visual Studio でデバックしようとすると、/bin/bash が無いといわれデバックできない。

そのままですが、Visual Studioではdocker-composeプロジェクトのデバック開始時に、下記のようなコマンドを実行して、そのVisual Studioのセッションですでに起動しているコンテナ内のdotnetプロセスをすべて殺しに行きます。

docker exec -i b13437825d3e /bin/bash -c "if PID=$(pidof -x dotnet); then kill $PID; fi"

で、そのときに/bin/bash を使っているので、コンテナサイズの削減を目的にalpineとかにしていると、/bin/bashが無いよとか言われてデバックの開始に失敗します。

alpine に対する対応は始まっているらしく、Visual Studio 2019では対応が行われるようですが、2017を使っている間は、alpineベースのイメージを作る場合はDockerのビルドステージを分けるとかで対応する必要がありそうです。
https://developercommunity.visualstudio.com/content/problem/256756/new-container-tools-in-158-cant-debug-alpine-docke.html

どうしても alpine を使いたい人は、コンテナ起動時に apt add すれば良いので Dockerfile をこうすれば行ける。。。嫌だけれど

FROM base AS final
WORKDIR /app
RUN apt update && apt add bash
COPY --from=publish /app .
ENTRYPOINT ["dotnet", "xxxxxxxx.dll"]

— 追記
TimeZone設定とかも欲しいし、baseで設定したほうが良い気がしてきた。

FROM microsoft/dotnet:2.1-aspnetcore-runtime AS base
ENV TZ=Asia/Tokyo
RUN apt update && apt add bash
WORKDIR /app
EXPOSE 80
カテゴリー:ASP.NET, Docker

asp.net core で src フォルダー直下をソリューションディレクトリにしてはいけない

src配下にソリューションディレクトリがあると深くなりすぎるので、こんな感じのリポジトリの構成にしたところ

+-- リポジトリーのルート
  +-- README.md
  +-- src
    +-- xxxx.sln
    +-- docker-compose.yml
    +-- Project1
    +-- Project2

docker-compose up したときに作られる network や volume が src-xxxx となってしまって、他のプロジェクトとコンフリクトした、、、
docker-compose up するときにプロジェクト名を設定してから上げれば良いんだけれど毎回だと辛い、ちょっと深くなるけれどソリューションフォルダーは作ったほうが良さそう

カテゴリー:ASP.NET, Docker