WebMatrix 2:RESTful?な Web アプリケーション

執筆日時:

f:id:daruyanagi:20130106043226p:plain

たとえば、

  • ~/Posts/ …… ページリストの表示
  • ~/Posts/:id …… 個別ページの表示

というのをやってみたいとき。

  • ~/Posts/Default.cshtml

を作成して、

  • UrlData.Count() == 0 ……ページリストの表示
  • UrlData.Count() == 1 ……個別ページの表示

という処理を書けばいいよね(WebMatrix のルーティング - だるろぐ)。

WebMatrix 2 / Razor:switch と RenderPage() - だるろぐ

これはウソだ。申し訳ない。まぁ、別に正しいことを書いているブログではないので、いいと言えばいいんだけど。正しくは、

を作成するだね。ほかにもウソがあるのだけど、それはまた別のエントリーでフォローするから!

――なにはともあれ。

この ~/Posts.cshtml をガリガリ書いていけば、いわゆる RESTful な Web アプリケーションが書けるのではないかと思いついた。RESTful の厳密な定義は知らないけど、だいたい

みたいな感じだよね。だったら、下のような感じで書けばいいんじゃないか(本質に関係ない部分は削ってる)。

@try{
switch (Request.HttpMethod.ToUpper())
{
case "GET":
switch (UrlData.Count)
{
case 0: // GET Posts/ 
@List()
break;
case 1:
switch (UrlData[0].ToUpper())
{
case "NEW": // GET Posts/New
@New()
break;
                        default:    // GET Posts/1, Posts/Title
@Show(UrlData[0])
break;
}
break;
case 2:
switch (UrlData[0].ToUpper())
{
case "EDIT":    // GET Posts/Edit/1
@Edit(UrlData[1])
break;
case "REMOVE":  // GET Posts/Delete/1
@Remove(UrlData[1])
break;
}
break;
}
break;
case "POST":
Create();
break;
case "PUT":
Update(UrlData[0].AsInt());
break;
case "DELETE":
Delete(UrlData[0].AsInt());
break;
}
}
catch (Exception e)
{
<p><span class="badge error">Error</span> @e.Message</p>
}

@List() や @New() の部分は、@functions で定義してる。

@functions
{
HelperResult List()
{
var query = "SELECT * FROM Post ORDER BY CreatedAt DESC";

using (var db = Database.Open("db")) { var posts = db.Query(query); return RenderPage("~/Views/Posts/_ListPosts.cshtml", posts); } } }

HelperResult を返す関数にして @ をつけて呼べば、ちゃんと部分ビューがレンダリングされる。POST/PUT/DELETE のところで使う関数は、どうせ Response.Redirect() するから void でいいし、@Delete() なんて書く必要もない。

で。

Create() は動くのだけど、なぜか Update() と Delete() だけが動かない。ちゃんとビューで method も指定したのになぁ……

#Delete() → RenderPage()  ~/Views/Posts/_RemovePost.cshtml"

@{
var model = PageData.First().Value;
}

<form method="delete" action="~/Posts/@model.Id">
<div>
<label>Title</label>
<input type="text" name="Title" value="@model.Title" disabled />
</div>
<div>
<label>Body</label>
<textarea name="Body" disabled>@model.Body</textarea>
</div>
<div>
<input type="submit" />
</div>
</form>

なぜかこれを Submit すると GET での呼び出しになってしまう。よく知らんけど、ブラウザーは GET と POST しかサポートしていないらしい*1。あと、サーバー側にも設定がいるのかな。

とりあえず、GET と POST しか使えない。道理で、IsPost() なんていうのがお役に立つ訳だわ。なんで IsGet()、IsPut()、IsDelete() しかないのかなって思ってた。こういうのって、たぶん Web 開発者にとっては基本的な知識なんだろうな。やっぱりなにごとも経験しないとだめだねぇ。

というわけで、GET と POST だけ使っていろいろ書き直したのだけど、それはまた今度。一足先に感想を言えば、こういうのは「ASP.NET MVC」使った方が賢い(ぉ

*1:そういえば、Rails でも _method="delete" みたいな感じにして、ここら辺の問題を回避していた気がする