Monoならではの問題と対応方法
はじめに
Mono 好きです!
初めて Mono を試したとき、Windowsで発行した ASP.NET MVC アプリが Linuxで動いたのは、魔法かと思っちゃいました。
そんなステキな Mono ですが、やっぱりちょっとだけ気をつけることがあります。
モノズキな方へのTip集。
筆者の環境は下記のとおりになっています。
- Visual Studio 2015
- .NET Framework 4.5.1
- ASP.NET MVC 5
- Mono 4.6.2
- XSP 4.2.2
- fast-cgi-mono-server 4.2.2 (0.4.0.0)
- Debian 8.6
- Nginx 1.6.2
Machine Key
フォーム認証や暗号化のために必要な Machine Key。
普通(Windows IIS) は、Web.config に明記していなければ自動的に生成されるらしいんだけど、Mono じゃダメです。
サービスを再起動する度に値が変わってしまうため、System.Web.Security.MachineKey.Protect などでの暗号した値を decodeするときに例外を吐いてしまいます。
なのでWeb.configに明記します。
Generate ASP.NET Machine Keys
↑のサイトで、Generate Keyボタンを押下して、生成された文字列を、<System.Web>空間内にコピペすればOKです。
<machineKey validationKey="E4C13FB44CF8CBCD126896B77B0A38D05D7290A47ADB1D248500A624D4A07607D096402371E15D8F981D8071986B72FEBDE40248A63DA764F48F7996F24C7871" decryptionKey="AB4996AF83FEB94C5018CC7FD003F3909C553DCEAA5FEE4AC7C6432DE3DFD701" validation="SHA1" decryption="AES">
Client Validation
Model のアノテーション設定から Validation を行ってくれる便利なアレ。
NuGet から、パッケージをちゃんと入れて、Web.config の ClientValidationEnabled も true にして、IIS環境ではちゃんと動きましたーー
でも、Monoでは、Client Validation のための HTML タグを吐いてくれない・・・そんなとき。
<input data-val="true" data-val-required="メールアドレス は入力必須項目です。" id="MailAddress" name="MailAddress" type="text" value="" />
<input data-val="true" data-val-required="パスワード は入力必須項目です。" id="Passwd" name="Passwd" type="password" value="" />
ほんとうなら、↑こんなHTMLを出力してくれるハズが、
↓のようなプレーンがタグになっちゃう。
<input id="MailAddress" name="MailAddress" type="text" value="" />
<input id="Passwd" name="Passwd" type="password" value="" />
これの解決方法は、次項にて。
1発目のリクエストで例外発生
サービスを再起動したり、プログラムを入れ替えたりした後の、最初のリクエストを行うと、System.UnauthorizedAccessException を吐くことがあります。
(F5押下してリロードすると、動きだす)
これは、Mono 用に一時ディレクトリを作ってやれば、解決します。
ディレクトリの名前は、例外メッセージに表示されています。
このディレクトリを、所有者をサービスを実行しているユーザにして作ってやればOKです。
Mono をパッケージからインストールしたときは、/etc/mono/registry
ソースから入れたときは、/usr/local/etc/mono/registry
fast-cgiを使っているなら、fast-cgi の実行ユーザ
Apache + mod_mono なら、Apache の実行ユーザ
また、Webサーバのエラーログを見てみると、
"実行ユーザのホーム ディレクトリ/.mono" がdenidだぞ・・・
とあるので、こちらのディレクトリも同じように作成しておきます。
こちらの設定を行うと、前項の「Client Validation」の問題も解決します
ちゃんと validation のダグが生成されていました!
Knockout の ViewModel を JSON にシリアライズするとき
Knockout を使った Formデータを POSTした時に Internal error: key is null, empty or not a string.
てな例外が出たら、JSONをうまくデシリアライズできないのが原因のようです。
Windows環境では、問題なく動くのに、Mono だとダメなときがあります。
どうやら、ko.mapping を使って ViewModel 化したものを、ko.toJSON でシリアライズすると、余計なプロパティ(__ko_mapping__)が付いたままになり、これが付くと、Mono 上ではモデルバインダーが例外を吐いてしまうようです。
ko.mappingを使ったものは、必ず「ko.mapping.toJSON」でシリアライズするように、気をつける必要があります。
ClosedXMLでのExcelが破損?
サーバサイドで Excelファイルを生成する処理があったので、最初は ClosedXMLを使ってました。
ところが、Mono 環境で実行すると、生成したExcelファイルを開くときに、↓のエラーが出てしまいます。
毎回、最初の問いに「はい」とすれば、Excelが開くんだけど、どうやらこれは xlsx 形式の Zip 圧縮で微妙な差異があるらしいのが原因みたいです。
※WindowsBase.dll を参照に入れたり、Web.config でアセンブリを明示してもダメでした。
仕方ないので、ClosedXML の利用を諦め、EPPlusというパッケージを試してみたら、問題なく開くことが出来ました。
EPPlus は、OpenXML SDK を使わずに Open Office XML を生成するので、単純な表なら十分だし、実効速度も速いです。
NLog.Web 設定で aspnet 変数を書くと例外
NLog の拡張ライブラリ「NLog.Web」を入れると、設定ファイルの記述だけで ASP.NET の環境変数をログに出力できます。
<!-- layout のところで、リクエストURLをログに出力しています -->
<target name="accessLog"
xsi:type="File"
layout="${longdate} ${aspnet-request:serverVariable=Url} - ${message} ${exception:format=tostring}"
fileName="${logDirectory}/access.log"
archiveEvery="Day"
archiveFileName="${logDirectory}/access.{#}.log"
archiveNumbering="Date"
archiveDateFormat="yyyyMMdd"
encoding="utf-8"
maxArchiveFiles="30" />
でもこれを Mono で実行すると
Non-web exception. Exception origin (name of application or object): System.Web.Mvc.
てな例外が出てしまいます。
仕方ないので、出力したい情報(リクエストURL)は、ログ内容文字列に含めることにしました。
Author And Source
この問題について(Monoならではの問題と対応方法), 我々は、より多くの情報をここで見つけました https://qiita.com/kirishu/items/989a8b1a62a7fb9c2ac9著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .