ASP.NET MVC: コントローラ未定義のパスへのアクセス時に404を返す

 Homeコントローラ内のIActionResultの末尾に下記を追加。
[Route("{*path}")]

public IActionResult NotFound(string path)
{
Response.StatusCode = 404;
return View("NotFound");
}

 返すべきものがあるなら上記の場所に達するまでのIActionResultのどれかに引っかかっている。引っかからずに末尾に来たということは、そのパスに該当するものは未定義なので404を返しておけということになるだろう。Viewは自作のものがある場合のコード。

 いつかのASP.NET MVCはController.HandleUnknownActionというメソッドをオーバーライドすればよかったらしいが、この記事を書いている時点での.NET Coreのベータで動かしているものでは該当メソッドが見つからなかった。
comment: 0

MongoDB: セッションのトークンを管理してもらう

 MongoDBには、期限切れとなったドキュメントを自動で削除してくれる機能がある。このブログではDBにMongoDBを使っており、期限切れのセッショントークンはこの機能を利用して削除している。

 sessionというコレクションにトークンデータを保存する。保存されるドキュメントのデータとしてトークン文字列token、作成日時createdAtがあるとする。このコレクションにドキュメントが保存された場合に、一定時間後にドキュメントを削除したい。下記のようにインデックスを作る。
db.session.createIndex( { "createdAt": 1 }, { expireAfterSeconds: XXX } )

 これでXXX秒後にコレクションsession内のドキュメントは自動で削除される。ただし期限が切れて直ちに消えるわけではない。バックグラウンドタスクが60秒ごとに走っているので、このタスクの対象になったタイミングで処理される。

https://docs.mongodb.com/manual/core/index-ttl/
comment: 0

ASP.NET MVC: MVCをする(モデルとコントローラ)

 MVCフレームワークをまじめに使うのは、このブログのASP.NET MVCが初めてだった。それまではPythonでDjangoをスルーしてGAE、FlaskやTornadoを使ってた。
 なんでMVCかってのは、メンテナブルなものにしたかったからである。かつてPythonで書いていたとき、MVCもなんも知らずにまず動かそうとコードを書いていた。そのせいでいわゆるコントローラが妙な肥大化をしたものを書いていた。

 MVCの自分なりの理解。WebでMVCはこうだろ的な記事を読んでいて、ファットコントローラはMVCの本来じゃないという指摘を見た。グサッと来た。
 ちょうどGAEのサンプルに、モデルに静的メソッドを書いてコントローラを軽量にまとめているものを参考にし始めた時期だった。そういう方法をとることで、コントローラに散在したDBデータ取得ロジックが、きれいに特定の箇所にまとめられた。そんな体験をしていたタイミングでMVCがどんなものかというのを読んだので、そのままそれを学びたいと思った。
 コントローラを太らすMVCもあるらしい。個人的にはそれをやるとコントローラ毎にDBへのアクセスを書いてしまいがちになり、DBアクセスのメンテナンスが面倒になってくる。そこでじゃあDBアクセスのロジックをどこに持ってくるのが妥当かと考えると、とってきたいデータのモデルを持つクラスに静的メソッドとして加えるのが一番しっくりくる。というわけでファットモデルがいい。

 コントローラの一例が下記のコード。このブログの各記事ページのためのコントローラ。
[Route("Article/{id:int}")]

public IActionResult Article(int id)
{
var entry = Entry.GetEntry(id);
if (entry != null)
{
ViewBag.entry = entry;
return View();
}
else
{
Response.StatusCode = 404;
return View("NotFound");
}
}

 パスから記事のIDを取得。記事があればその時点で持ってる情報をビューに渡す。あとはビュー側でモデルをごにょごにょして情報を取得しつつ、それを表示してもらう。IDに該当する記事がなければ404ページのビューへ。
 ビューからモデルを見るので、モデルはDBデータの各種取得方法が静的メソッドになったクラスになっており、それなり肥大化している。
 これでいいんかなと思いつつ考えたりいろいろ読んでいる。それでも以前のファットコントローラなものからすると、だいぶメンテナンスしやすい仕組みだと感じる。
comment: 0

ASP.NET MVC: HTTPSリダイレクトとHSTS設定

 ASP.NET MVCを使ったWebアプリでの、セキュリティ処置をしておく。処置は全ページでのHTTPSへのリダイレクトと、HSTS(ブラウザにHTTPSアクセスを強制するもの)の設定。

 web.configを開いて適切な場所に下記を追加。
 
<system.webServer>


<rewrite>
<rules>
<rule name="HTTP to HTTPS redirect" stopProcessing="true">
<match url="(.*)" />
<conditions>
<add input="{HTTPS}" pattern="off" ignoreCase="true" />
</conditions>
<action type="Redirect" url="https://{HTTP_HOST}/{R:1}"
redirectType="Permanent" />
</rule>
</rules>
<outboundRules>
<rule name="Add Strict-Transport-Security when HTTPS" enabled="true">
<match serverVariable="RESPONSE_Strict_Transport_Security"
pattern=".*" />
<conditions>
<add input="{HTTPS}" pattern="on" ignoreCase="true" />
</conditions>
<action type="Rewrite" value="max-age=31536000" />
</rule>
</outboundRules>
</rewrite>

<handlers>


http://www.hanselman.com/blog/HowToEnableHTTPStrictTransportSecurityHSTSInIIS7.aspx
 上記の場所にあったコードをいただいた。HSTSをHTTPSアクセスにしか返さないようにしているが、これは仕様上の正しい実装になっているらしい。HSTS仕様を確認したところ、確かに、HSTS設定されたヘッダはセキュアな通信で返送してねと書かれていた。
comment: 0

C#, ASP.NET MVC: Cookieの設定

 ASP.NET MVCでCookieを設定する。オプションは文字通りオプションなのであってもなくても。ただし今回はセッションIDを入れてるので、そんな場合はオプションでsecureにするのはほぼ必須だろう。

var cookieOption = new CookieOptions()

{
Secure = true
};
Response.Cookies.Append("_sid", token, cookieOption);
comment: 0