ASP.NET MVC 5 でビューから文字列を作成する

ASP.NET MVC 5 でビューが描画する HTML を、そのままレスポンスとして返すんじゃなくて、 いったん文字列で変数に格納したかったのでやってみた。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;

namespace RenderViewSample.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            return View();
        }

        public ActionResult String()
        {
            var html = RenderViewAsString("Index");
            return Content(html, "text/html", System.Text.Encoding.UTF8);
        }

        private string RenderViewAsString(string viewName, object model = null, string masterName = "_Layout")
        {
            ViewData.Model = model;
            using (var writer = new System.IO.StringWriter())
            {
                var viewResult = ViewEngineCollection.FindView(ControllerContext, viewName, masterName);
                var viewContext = new ViewContext(ControllerContext, viewResult.View, ViewData, TempData, writer);
                viewResult.View.Render(viewContext, writer);
                viewResult.ViewEngine.ReleaseView(ControllerContext, viewResult.View);
                return writer.GetStringBuilder().ToString();
            }
        }
    }
}

フレームワーク側で提供して欲しいけど、需要ないんだろうか。ないんだろうな。

いっかく食堂

警固にある『いっかく食堂』の『限定いっかく和牛ハンバーグ』が、 どうしても気になったので週末行ってみた。 カフェみたいな綺麗な店で、いい意味で定食屋っぽくない。

f:id:griefworker:20150207112731j:plain

お目当の『限定いっかく和牛ハンバーグ&唐揚げ』定食がこちら。

f:id:griefworker:20150207114338j:plain

ハンバーグをアップでドン。

f:id:griefworker:20150207114347j:plain

ハンバーグが表面こんがり焼き目が付いていて香ばしい。 中はふわっとしていて柔らかかった。 ブラックペッパーがピリッと効いていて良いアクセント。 唐揚げもさくさくジューシーで、超自分好み。

ハンバーグ旨かったけど、それ以上に唐揚げを気に入ってしまった。 次は唐揚げ定食もいいかもしれない。迷うな。

関連ランキング:ハンバーグ | 薬院大通駅赤坂駅桜坂駅

まるたんや

奮発して、『極みや』系列店で赤坂にある『まるたんや』に行ってみた。 ここはずっと行きたいと思っていて、ようやく念願かなった。

f:id:griefworker:20150131193203j:plain

ドリンクはそんなに種類多くないけど、定番は揃っている感じ。 自分は甘いお酒しか飲めないので、カルピスチューハイで乾杯。

f:id:griefworker:20150131180646j:plain

お通しでちびちびやる。

f:id:griefworker:20150131180732j:plain

健康のためにまずはカリカリゴボウの豆腐サラダから。 このサラダめっちゃ旨い。 周りの客の多くが注文してた気がする。

f:id:griefworker:20150131181001j:plain

厚切り熟成上タン。 熟成肉はじめて食べた。これが牛タンかと思うくらい柔らかくてジューシー。

f:id:griefworker:20150131181204j:plain

どうしても豚バラが食べたかったので、つい注文してしまった。 豚バラは脂が甘くて好き。

f:id:griefworker:20150131181143j:plain

オクラをバラ肉で巻いたヤツ。 焼いたオクラもイケル。

f:id:griefworker:20150131181208j:plain

伊万里牛ステーキつくね。 中はレアなので、焼き石で自分好みに焼いていただく。 非常に肉々しい。 味付けはシンプルで、肉の旨みが際立っていた。

f:id:griefworker:20150131182503j:plain

タンシチュー。 タンが箸で簡単にほどけるほどに柔らかい。

f:id:griefworker:20150131183354j:plain

パケットがセットなので、デミグラスソースを残さず食べることができる。

f:id:griefworker:20150131183400j:plain

名物・中落ちカルビ。 濃いめの味付け。サンチュで巻いて食べるとちょうどいい。 ご飯が欲しくなるね。

f:id:griefworker:20150131185046j:plain

シメに石焼ガーリックチャーハン。 これ食べた後は人に会えないな、ってくらいにガーリック強いけど、旨かった。

f:id:griefworker:20150131191107j:plain

正直食べ過ぎた。 コース料理以外で、一度の食事でこんなに注文したのは始めてかもしれない。 店を出た直後は腹がはち切れそうだった。 どれも旨かったし、 メニューの中から気になるものを片っ端から食べたので、 思い残すことはない。 満足、満足。

関連ランキング:串焼き | 赤坂駅西鉄福岡駅(天神)天神駅

Rails 4.2 に移行していて decimal 型の属性のバリデーションで嵌った

例えば、decimal 型の weight という属性を持つ Item クラスがあるとする。

class Item < ActiveRecord::Base
  validates :weight, inclusion: { in: [0.2, 0.4, 0.8, 1.0, 1.2, 1.4, 1.6, 1.8, 2.0] }
end

Rails 4.1.2 までは下記のようなバリデーションが成功していたのに、 4.2.0 に上げたら失敗するようになった。

item = Item.new(weight: 1.2)
item.valid? #=> false
item.weight #=> #<BigDecimal:7f0319279bd8,'0.1199999999 9999999555 9107901499 3738383E1',45(54)>

環境は次の通り。

decimal 型の属性は BigDecimal で保持するみたいで、 初期値として渡した Float の値を BigDecimal に変換した結果、誤差が発生してしまっていた。

BigDecimal は文字列から作成できるので

item = Item.new(weight: "1.2")
item.valid? #=> true
item.weight #=> #<BigDecimal:7f031937dbd8,'0.12E1',18(18)>

という風に文字列でセットして回避。

rspec-mocks の and_raise で嵌った

rspec-mocks を使って

allow_any_instance_of(User).to receive(:save!).and_raise(ActiveRecord::RecordNotSaved)

という風にモデルの保存に失敗するテストを書いていたけど、 Rails 4.2 に更新したら実際に save! を呼び出すところで ArgumentError が発生するようになって嵌った。

ちなみに gem のバージョンは次の通り。

pry-bybug でステップ実行しつつ調べたら原因判明。 rspec-mocks では、and_raise で指定した例外クラスをスローするとき、 例外クラスの exception メソッドを使ってインスタンスを生成していた。

で、and_raise の引数でメッセージを渡さなかった場合は、引数なしの exception が呼ばれるんだけど、 ActiveRecord::RecordNotFound の exception は引数が必須。 だから ArgumentError が発生してしまっていた。

ひとまず

allow_any_instance_of(User).to receive(:save!).and_raise(ActiveRecord::RecordNotSaved, "error")

という風にメッセージを渡すことで回避に成功。

Vagrant の port forwarding を設定してもゲスト OS 側の Rails 4.2 の開発サーバーに接続できなくて嵌った

Rails 4.2 へのアップグレード作業中、下記のトラブルに遭遇。

  1. Vagrant でホストの 3000 番ポートをゲストの 3000 番ポートに port forwarding している
  2. ゲスト側で rails server でサーバー起動
  3. ホスト側の Web ブラウザで localhost:3000 にアクセス
  4. サーバーに接続できない\(^o^)/

rails server 実行時に出力されるメッセージを見ると、 Rails 4.1.2 まで開発サーバーは 0.0.0.0 で待ち受けていたけど、 Rails 4.2 では 127.0.0.1 で待ち受けるように変わっていた。

bin/rails server -b 0.0.0.0

という風に、バインドする IP アドレスを指定することで、以前と同じように Web ブラウザで表示できることを確認。

ASP.NET MVC 5 実践プログラミング

ASP.NET MVC を体系的に勉強するなら書籍が一番だと思い本書を購入。 期待通りの良書だった。

ASP.NET MVC はリリースされてから今まで、ほとんど使ったことがなかった。 Web アプリケーションフレームワークで使うのはもっぱら Rails

今回初めて ASP.NET MVC を試したわけなんだけど、正直なところ、ここまで進化していたのかと驚いた。 例えば Rails ではリクエストのパラメータをフィルタするために strong parameters があるけど、 ASP.NET MVC にはモデルバインダがあり、フィルタと型変換までやってくれる。 認証には標準で ASP.NET Identity がある。 モデル層は提供していないけど、Entity Framework や Dapper などから好きなのを選べばいい。

Web アプリケーションフレームワークとして ASP.NET MVCRails に勝るとも劣らない。 フレームワークを中心としたエコシステムの面では、Rails の方がまだ大きいと感じているが。 パッケージマネージャーの NuGet が普及したし、 ASP.NET 5 (ASP.NET MVC は 6 なのでまぎらわしい)で Rack みたいな共通インタフェースも導入される。 さらに .NET Core のクロスプラットフォーム化も後押しになり、 エコシステムはこれから一気に成長しそうだ。

ASP.NET MVC5実践プログラミング

ASP.NET MVC5実践プログラミング