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 のクロスプラットフォーム化も後押しになり、 エコシステムはこれから一気に成長しそうだ。

とり田 博多本店

水炊きで人気の『とり田』のから揚げや親子丼がランチで食べられる 『とり田 博多本店』に行ってみた。

f:id:griefworker:20150111141016j:plain

水炊きはちょっと手が出せないお値段だけど、から揚げ定食や親子丼は880円(税抜)とお手ごろ。 その2つのうちどちらを食べるか迷ったけど、揚げ物が食べたい気分だったので、 今回はから揚げ定食を選択。

最初に出てくる水炊きのスープは上品な美味さで、 水炊きも食べたいとつい思ってしまった。

f:id:griefworker:20150111141535j:plain

から揚げは、もも肉と、むね肉と、あと色々。 いろんな部位の鶏肉のから揚げが一度に食べれるし、 予想していたよりも量が多くて、満足度高め。

f:id:griefworker:20150111141914j:plain

f:id:griefworker:20150111141921j:plain

関連ランキング:水炊き | 中洲川端駅呉服町駅天神駅

ASP.NET MVC で PDF を作成

ASP.NET MVC でチャートを表示するには、 System.Web.Helpers にある Chart クラスを使えばいいことが分かった。

ASP.NET MVC でチャートを表示 - present

ここからさらに、チャートを含んだドキュメントを PDF でダウンロードできるようにしたい。 これを実現するには、iTextSharp を使うのが良さそうだ。 iTextSharp では、PDF に画像を埋め込むのはそう難しくない。

using iTextSharp;
using iTextSharp.text;
using iTextSharp.text.pdf;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Web;
using System.Web.Helpers;
using System.Web.Mvc;

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

        public ActionResult Pdf()
        {
            var pdf = CreatePdf();
            return File(pdf, "application/pdf", "PdfSample.pdf");
        }

        // PDF(バイナリ)を作成
        private byte[] CreatePdf()
        {
            using(var document = new Document(PageSize.A4, 20, 20, 20, 20))
            using(var stream = new MemoryStream())
            using (var writer = PdfWriter.GetInstance(document, stream))
            {
                document.Open();

                // テキストを PDF に書き込む
                document.Add(new Paragraph("PDF Sample"));

                // レーダーチャート画像を PDF に埋め込む
                var chart = CreateRadarChart();
                var image = Image.GetInstance(chart);
                document.Add(image);

                document.Close();

                return stream.ToArray();
            }
        }

        // レーダーチャート画像を作成
        private byte[] CreateRadarChart()
        {
            var chart = new Chart(
                width: 400,
                height: 400,
                theme: ChartTheme.Blue
            );
            chart.AddTitle("チャートサンプル");
            chart.AddSeries(
                name: "能力",
                chartType: "Radar",
                xValue: new[] {
                    "ミート",
                    "パワー",
                    "走力",
                    "肩力",
                    "守備力"
                },
                yValues: new[] {
                    "90",
                    "60",
                    "80",
                    "80",
                    "90"
                }
            );
            return chart.GetBytes();
        }
    }
}

Web ブラウザでアクションを呼び出すと、レーダーチャートが埋め込まれた PDF をダウンロードできる。

f:id:griefworker:20150113200216p:plain

嬉野旅行 2 日目

2日目は 6 時に起きて、貸切じゃない方の露天風呂に行ってきた。 他の客だれもいなくて貸切だったから写真撮っておけばよかったな。

露天風呂の後は朝食。

f:id:griefworker:20150111070916j:plain

トロ鯵。朝から結構なボリューム。

f:id:griefworker:20150111071134j:plain

これが温泉湯豆腐。 煮込むと温泉の成分が作用して、豆腐がトロトロになる。 ごま醤油とごまダレ、どちらで食べても旨かった。

f:id:griefworker:20150111072203j:plain

デザートはヨーグルト。いかにも朝食っぽい。

f:id:griefworker:20150111074449j:plain

朝食食べた後は、もう一度部屋の風呂に入りつつ、 チェックアウト時間までまったり。

チェックアウトしてから高速バスの時間までは 40 分くらいしかなかったので、 嬉野観光はバスセンター近くの豊玉姫神社だけ行ってみた。 御神体の白なまずは写真撮るとバチがあたりそうな気がしたので、本殿の写真だけ。

f:id:griefworker:20150111110151j:plain

嬉野温泉、何度か行ったことあるけど、泊まったのは今回が初めて。 ホテルの部屋はコンパクトだったけど綺麗だったし、5 種類のお風呂に入れたし、 かなり満喫できた。

嬉野旅行 1 日目

食べ歩きだけでなく旅行も好きで、 毎年最低でも1回は旅行に行っている。 今年も早々、佐賀県嬉野温泉に行ってきた。 近場なので1泊2日の小旅行。

嬉野バスセンターで高速バスを降りてから、10分ほど歩いたら宿泊するホテル『萬象閣 敷島』入り口に到着。 全体を撮りたかったけど、いい撮影ポイントが無かった。

f:id:griefworker:20150110144722j:plain

受付しつつ、抹茶と敷島プリンをいただく。 敷島プリンは上に抹茶ソース、底に黒蜜が入っていて、 和風で旨かった。

f:id:griefworker:20150110150050j:plain

受付が終わってプリン食べ終わったら、部屋に案内された。 和モダンな部屋でオシャレ。

f:id:griefworker:20150110151009j:plain

部屋に露天風呂が付いている。蛇口ひねると温泉が出てくるので、 湯加減調整しながら自分で溜めるタイプ。

f:id:griefworker:20150110151116j:plain

フロントで貸切露天風呂の空き状況を確認し、16 時にさっそく貸切露天風呂へ。 まずは5番湯。 冬でも風情あっていい。 これが秋なら紅葉が綺麗なんだろうな。

f:id:griefworker:20150110155947j:plain

貸切露天風呂から上がったら、早めの夕食。

刺身は結構厚めに切ってあって食べ応えあった。

f:id:griefworker:20150110180010j:plain

佐賀有田が有名な呉豆腐。汲み湯葉も入っていた。

f:id:griefworker:20150110181409j:plain

八寸は右端の柿チーズが甘くて好き。

f:id:griefworker:20150110184458j:plain

そしてこれが佐賀牛

f:id:griefworker:20150110180032j:plain

ホームページで予約したので、佐賀県産和牛(佐賀牛ではない)も付いてきた。

f:id:griefworker:20150110181452j:plain

こんな風に自分で焼く。 結構しっかり焼いたつもりでもミディアムレア。 脂が甘くてジューシーだった。

f:id:griefworker:20150110182203j:plain

土瓶蒸しでほっと一息。

f:id:griefworker:20150110184512j:plain

伊勢海老吉野煮は弾力がブリブリと凄かった。

f:id:griefworker:20150110190039j:plain

フカヒレと、〆のお茶づけ。 初めてフカヒレ食べたけど、不思議な食感。

f:id:griefworker:20150110191146j:plain

デザートのパンナコッタが来たころには、もうお腹いっぱいではち切れそうだった。

f:id:griefworker:20150110193506j:plain

夕食で腹がパンパンになったから少し部屋で休憩し、 2度目の貸切露天風呂へ。 今度はかまくら湯。 秘密基地みたいで男心がくすぐられた。

f:id:griefworker:20150110200008j:plain

この後、大浴場と部屋の露天風呂にも入ったので、合計 4 回お風呂に入ったことになる。

さすがに疲れたので、夜はフロントで借りた『アナ雪』の DVD を部屋で見つつまったり。

f:id:griefworker:20150110203257j:plain

アナ雪いつか見ようと思っていたけど、まさか旅行先のホテルで見ることになるとは思わなかったな。

ASP.NET MVC でチャートを表示

ASP.NET MVC でレーダーチャートを表示する方法を調べたところ、 System.Web.Helpers にある Chart クラスを使うのが手っ取り早そうだった。

System.Web.Helpers は ASP.NET MVC 5 のプロジェクトを新規作成すると、 既にアセンブリ参照に含まれているから、 すぐに使えて嬉しい。

試しにレーダーチャートを出力してみる。

まず、コントローラーでレーダーチャートの画像ファイルを作成し、パスをビューに渡す。

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

namespace ChartSample.Controllers
{
    public class HomeController : Controller
    {
        public ActionResult Index()
        {
            var path = "sample.jpg";
            if (System.IO.File.Exists(Server.MapPath(path)))
            {
                System.IO.File.Delete(Server.MapPath(path));
            }

            var chart = new Chart(width: 400, height: 400, theme: ChartTheme.Blue);
            chart.AddTitle("レーダーチャート");
            chart.AddSeries(
                name: "サンプル1",
                chartType: "Radar",
                xValue: new[] { "ミート", "パワー", "走力", "肩力", "守備力" },
                yValues: new[] { "90", "80", "80", "90", "80" }
            );
            chart.AddSeries(
                name: "サンプル2",
                chartType: "Radar",
                xValue: new[] { "ミート", "パワー", "走力", "肩力", "守備力" },
                yValues: new[] { "70", "100", "60", "60", "60" }
            );
            chart.Save(path: Server.MapPath(path));

            ViewBag.ChartPath = path;

            return View();
        }
    }
}

ビューでは img タグを使って、レーダーチャートの画像ファイルを表示。

@{
    ViewBag.Title = "Home Page";
}

<div class="row">
    <div class="col-md-12">
        <img src="@ViewBag.ChartPath"/>
    </div>
</div>

こんな感じのレーダーチャートが表示される。

f:id:griefworker:20150108203032j:plain

見た目は上々。 あとはどこまでカスタマイズできるかだな。

PostgreSQL で Dapper を使う

.NET Server Framework がリリースされたら、Mac OS XLinux で動く .NET アプリケーションを作ることもありそう。そうなるとデータベースは PostgreSQL かなぁ。My SQLMariaDB も捨てがたい。

どちらにしても、ORM には Dapper か Entity Framework を使うと思うので、まずは PostgreSQL と Dapper の組み合わせを試してみる。

新規コンソールアプリケーションプロジェクトに NuGet で

  • Npgsql
  • Dapper

を追加し、Npgsql と Dapper を使ったサンプルを書いてみた。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Transactions;
using Dapper;
using Npgsql;

namespace DapperSample
{
    public class Bookmark
    {
        public int Id { get; set; }
        public string Title { get; set; }
        public string Comment { get; set; }
        public string Url { get; set; }
    }

    class Program
    {
        static void Main(string[] args)
        {
            // 接続文字列を作成
            var builder = new NpgsqlConnectionStringBuilder()
            {
                Host = "localhost",
                Port = 5432,
                Database = "postgres",
                UserName = "postgres",
                Password = "postgres",
            };

            // TransactionScope を使って自動ロールバックする
            using (var ts = new TransactionScope())
            using (var connection = new NpgsqlConnection(builder))
            {
                connection.Open();

                // テーブル作成
                connection.Execute(
                    @"create table Bookmarks (
                          Id      serial primary key,
                          Title   varchar(100),
                          Comment text,
                          Url     varchar(250)
                      )"
                );

                // データ挿入
                connection.Execute(
                    @"insert into Bookmarks (
                          Title,
                          Comment,
                          Url
                      )
                      values (
                          'present',
                          '技術ブログ',
                          'http://tnakamura.hatenablog.com'
                      )"
                );

                // データ取得
                var bookmarks = connection.Query<Bookmark>(@"select * from Bookmarks");
                foreach (var b in bookmarks)
                {
                    Console.WriteLine(b.Id.ToString());
                    Console.WriteLine(b.Title);
                    Console.WriteLine(b.Comment);
                    Console.WriteLine(b.Url);
                    Console.WriteLine();
                }

                // テーブル削除
                connection.Execute("drop table Bookmarks");
            }

            Console.WriteLine("Enter で終了");
            Console.ReadLine();
        }
    }
}

f:id:griefworker:20150106095634p:plain

PostgreSQL でも Dapper 使えそうだ。