読者です 読者をやめる 読者になる 読者になる

Deploy to Azure Button + Sql database + Nancy でアプリを作った時に悩んだこと

Azure C# Nancy FluentMigrator

IoT勉強会の発表用にDeploy to Azure Button + SQL database + Nancyのアプリを作ってみたのですが、いくつか悩んだところがあったためまとめておきます。

 

Nancyまわり

DBの日本語の値をreturnすると文字化けする

Nancyで日本語を表示しようとした時に、

  • JSONで返した時は文字化けしない
  • returnでDBの日本語の値をそのまま返すと文字化けする

ということがありました。

 
対応としては、ResponseオブジェクトのContentTypeプロパティにcharset=utf8とcharsetを指定してあげれば、日本語表示がされるようになりました。
NancyOwinAzure-sample/HomeModule.cs at master · thinkAmi-sandbox/NancyOwinAzure-sample

 

エラー内容を表示する

通常運用ではエラー内容は非表示のままで良いのですが、いろいろと試してみる時にはエラー内容を表示したくなりました。

 
調べてみたところ、StaticConfiguration.DisableErrorTracesプロパティをfalseにすれば良いことが分かりました。
c# - How to get real error messages in Nancy on Mono? - Stack Overflow

しかし、そのプロパティの指定をどこですればよいか分からなかったので、上記のコメントにあったBootstrapperをキーワードに探したところ、以下にそれらしき情報がありました。
Configuring Nancy to use views in a separate assembly | The Blog of Colin Angus Mackay

 
方法としては、

  • DefaultNancyBootstrapperクラスを継承
  • ApplicationStartupメソッドをオーバーライドし、その中でDisableErrorTraces = falseを設定

ということが分かりました。

ただ、それをどこで呼ぶのかが分かりませんでしたので、作成してプロジェクトの直下にとりあえず置いてみたところ、エラー内容が表示されるようになりました。
NancyOwinAzure-sample/AzureBootstrapper.cs at master · thinkAmi-sandbox/NancyOwinAzure-sample

 

Azure Websitesまわり

コードで使う接続文字列について

今回はDapperを使ってSql databaseへ接続していますが、Azure Websitesで使う接続文字列はどこから取得すればよいのか分かりませんでした。そこで調べてみると、以下の記事がありました。
Windows Azure Web Sites: How Application Strings and Connection Strings Work | Microsoft Azure Blog

 
そのため、コードの中からSql databaseの接続文字列を扱うには、

using (var cn = new SqlConnection(Environment.GetEnvironmentVariable("SQLAZURECONNSTR_NancyOwinAzure").ToString()))

NancyOwinAzure-sample/DapperClass.cs at master · thinkAmi-sandbox/NancyOwinAzure-sample

のようにすれば良いことが分かりました。SQLAZURECONNSTR_の部分は接頭辞であり、上記の記事にいろいろとまとまっています。

あとは、Deploy to Azureで使うazuredeploy.jsonファイルに接続文字列名(上記の例なら、NancyOwinAzureを設定すれば動作しました。

 
なお、上記の記事の「Retrieving Key-Value Pairs in ASP.NET」という項目があり、Web.configファイルに記載するという例も紹介されていました。そのため、以下のコードを用意して試してみました。

Get["/connection/webconfig"] = _ =>
{
    var result = "";
    foreach (ConnectionStringSettings cs in ConfigurationManager.ConnectionStrings)
    {
        result += ("[Name]" + cs.Name + "[Provider]" + cs.ProviderName + "[ConnectionString]" + cs.ConnectionString + " , ");
    }

    return result;
};

NancyOwinAzure-sample/HomeModule.cs at master · thinkAmi-sandbox/NancyOwinAzure-sample

接続文字列のName, ProviderName, ConnectionStringの各プロパティの取得方法は以下を参考にしました。
接続文字列と構成ファイル - MSDN

 
結果を見ると、以下のエントリが追加されているようでした。

  • LocalSqlServer
  • LocalMySqlServer
  • NancyOwinAzure

 

AzureでFluentMigratorを使うには

DBのマイグレーションをFluentMigratorで行うことを考えましたが、最初のうちはどこで実行できるのかが分かりませんでした。

  • azuredeploy.jsonにデプロイ後フックがないか?
  • Azure PowerShellでやる方法
  • startup task ?

などをいろいろと探しましたが、結局はKuduのデバッグコンソールを使うのが一番楽そうでした。

 
Kuduのデバッグコンソールは、

https://<AppName>.scm.azurewebsites.net/DebugConsole

にあるので、あとはローカルと同じように以下のコマンドをコピペして実行しました。

 
なお、接続文字列は環境変数(今回の例であれば、SQLAZURECONNSTR_NancyOwinAzure)の値を使いますが、環境変数"%SQLAZURECONNSTR_NancyOwinAzure%"のようにダブルコーテーションで囲まないとエラーになりました。

"D:\home\site\repository\packages\FluentMigrator.Tools.1.3.0.0\tools\AnyCPU\40\Migrate.exe" /conn "%SQLAZURECONNSTR_NancyOwinAzure%" /provider sqlserver2012 /assembly "D:\home\site\repository\AspNetHosting\bin\AspNetHosting.dll" /verbose true

 
また、これを書いている時に.deploymentファイルを使う方法を知り、試してみたのが前回のエントリです。
.deploymentファイルを使って、Deploy to Azure Buttonを使用した際に、FluetnMigratorを自動実行する #glnagano #azure_shinano - メモ的な思考的な

 

Sql databaseをデプロイしすぎるとエラー

基本的なところなのかもしれませんが...。

Deploy to Azureボタンを使って、がんがんデプロイしていったところ、

Cannot move or create server. Subscription '****' will exceed server quota.

というエラーが発生しました。

仕方ないので、SQLのデータベースを削除後に再度デプロイしてみたものの、またエラーとなりました。

 
Azure管理画面をよく見ると「サーバー」というリンクがあったので、そこをクリックして削除してみたところ再度デプロイできるようになりました。

f:id:thinkAmi:20141127060446p:plain

 

Sql databaseのSql Administrator Passwordを適当に入力したらエラー

手を抜いてユーザーアカウントに数文字足してみたところ、エラーになりました。

Password validation failed. The password does not meet policy requirements because it is not complex enough.

パスワードポリシーにひっかかっていたようです。
Password Policy - MSDN

 

azuredeploy.jsonの書き方まわり

requestedServiceObjectiveIdの値について

手元でazuredeploy.jsonを書くにあたり、公式からもリンクされているJabbRのリポジトリを参考にしましたが、requestedServiceObjectiveIdには固定値っぽい値がありました。
JabbR/azuredeploy.json at 4ee4737f8d2e006bd491f02616522644743ec2fd · Tuesdaysgreen/JabbR · GitHub

この値はどこから持ってくるのだろうと調べてみたところ、それっぽいものが以下にまとまっていました。
Create Database - MSDN

しかし、今回のWebについては「Not recommended. See Web and Business Edition Sunset FAQ.」とだけの記載で、そのものの値がありませんでした。仕方ないので、JabbRのリポジトリの値をそのまま使いました。

 

Sql databaseのサイズを15MBにしたらエラー

Sql databaseのサイズは以下で指定しています。
NancyOwinAzure-sample/azuredeploy.json at master · thinkAmi-sandbox/NancyOwinAzure-sample

無料で扱えるサイズにしておこうと考え、15MB(設定値は、15728640)で試してみたところ、

The edition 'Web' does not support the database max size '15 MB'.

と、デプロイ時にエラーが発生しました。

そのため、20MB(20971520)にしてみたところ、問題なくデプロイができるようになりました。

 

typeが「sourcecontrols」である部分を削除したらエラー

通常はやらないと思いますが...。

何気なく、JabbRのリポジトリに記載のあったsourcecontrolsの部分を削除してみました。
JabbR/azuredeploy.json at 4ee4737f8d2e006bd491f02616522644743ec2fd · Tuesdaysgreen/JabbR · GitHub

すると、デプロイ時に

Could not find any git deployments

のエラーが発生し、デプロイができなくなりました。成功した時のデプロイログと比較すると、Setting up Source Controlがなくてエラーになっていました。

そこで、再度その部分を戻したところ、デプロイできるようになりました。

 

Azure Powershellまわり

今回は使わなかったのですが、FluentMigratorを使おうとした時にいろいろと試していたため、ついでに残しておきます。

 

何もせず、Get-AzureResourceを使おうとしたら、エラー

こんな感じで表示されました。

PS C:\Users\hoge> Get-AzureResource Get-AzureResource : 用語 'Get-AzureResource' は、コマンドレット、関数、スクリプト ファイル、または操作可能なプログラム の名前として認識されません。名前が正しく記述されていることを確認し、パスが含まれている場合はそのパスが正しいことを確認 してから、再試行してください。

原因は、Azure Powershellのインストールを指定なかったためです。以下を参考に、インストールしました。
How to install and configure Azure PowerShell

 

Azureコマンドレットが使えない

インストールが終わり、Add-AzureAccount を使用しても、Azureコマンドレットが使えませんでした。

そこで、以下を参考に、Switch-AzureMode -Name AzureResourceManager を実行してAzureModeを切り替えたところ、実行できるようになりました。
Azure Resource Manager « ブチザッキ