WebMatrix 2:RESTful?な Web アプリケーション (2)
執筆日時:
WebMatrix 2:RESTful?な Web アプリケーション - だるろぐ の続き。とりあえず、
- /Posts/ -> GET:List
- /Posts/:id -> GET:Show
- /Posts/New -> GET:New, POST:Create
- /Posts/Edit/:id -> GET:Edit, POST:Update
- /Posts/Remove/:id -> GET:Remove, POST:DELETE
って感じにマッピングされるように頑張ってみた。
# ~/Posts.cshtml@{ Layout = "_SiteLayout.cshtml"; }
@try{ switch (UrlData[0].ToUpper()) { case "": // <- / へアクセスするととりあえず UrlData[0] には string.empty が入るっぽい case "LIST": if (!IsPost) // GET { @List() } else // POST { throw new ApplicationException(); } break;
case "NEW": case "CREATE": // <- ビューを書き換えるのがめんどいので if (!IsPost) // GET { @New(UrlData[1]) } else // POST { Create(); } break;
case "EDIT": case "UPDATE": if (!IsPost) // GET { @Edit(UrlData[1]) } else // POST { Update(UrlData[1].AsInt()); } break;
case "REMOVE": case "DELETE": if (!IsPost) // GET { @Remove(UrlData[1]) } else // POST { Delete(UrlData[1].AsInt()); } break;
default: if (!IsPost) // GET { @Show(UrlData[0]) } else // POST { throw new ApplicationException(); } break; } } catch (Exception e) { <p><span class="badge error">Error</span> @e.Message</p> }
@functions { dynamic FindPostByIdOrTitle(string param) { int id = 0; dynamic post;
using (var db = Database.Open("db")) { if (int.TryParse(param, out id)) { var query = "SELECT * FROM Post WHERE Id=@0"; post = db.QuerySingle(query, id); } else { var query = "SELECT * FROM Post WHERE Title=@0"; post = db.QuerySingle(query, param); } }
if (post == null) throw new HttpException(404, string.Format( @"Post ""{0}"" is not found.", param) );
return post; }
HelperResult List() { var query = "SELECT * FROM Post ORDER BY CreatedAt DESC";
using (var db = Database.Open("db")) { var posts = db.Query(query); Page.Title = "Archives"; return RenderPage("~/Views/Posts/_ListPosts.cshtml", posts); } }
HelperResult Show(string param) { var post = FindPostByIdOrTitle(param); Page.Title = post.Title; return RenderPage("~/Views/Posts/_ShowPost.cshtml", post); }
HelperResult New(string param) { Page.Title = "New Post:" + param != string.Empty ? param : "Untitled"; return RenderPage("~/Views/Posts/_NewPost.cshtml"); }
HelperResult Edit(string param) { var post = FindPostByIdOrTitle(param); Page.Title = "Edit: " + post.Title; return RenderPage("~/Views/Posts/_EditPost.cshtml", post); }
HelperResult Remove(string param) { var post = FindPostByIdOrTitle(param); Page.Title = "Remove: " + post.Title; return RenderPage("~/Views/Posts/_RemovePost.cshtml", post); }
void Create() { var query = "INSERT INTO Post (Title, Body, CreatedAt, UpdatedAt)"
- "VALUES(@0, @1, @2, @3)"; var title = Request["Title"]; var body = Request["body"]; var now = DateTime.Now;
using (var db = Database.Open("db")) { db.Query(query, title, body, now, now); var key = db.QueryValue("SELECT @@IDENTITY"); Response.Redirect("~/Posts/" + key.ToString()); } }
void Update(int id) { var query = "UPDATE Post SET Title=@0, Body=@1, UpdatedAt=@2 WHERE Id=@3"; var title = Request["Title"]; var body = Request["body"]; var now = DateTime.Now;
using (var db = Database.Open("db")) { db.Query(query, title, body, now, id); Response.Redirect("~/Posts/" + id.ToString()); } }
void Delete(int id) { var query = "DELETE FROM Post WHERE Id=@0";
using (var db = Database.Open("db")) { db.Query(query, id); Response.Redirect("~/Posts/"); } } }
あんまり気に入らない。なんか当初の目標とズレてきたし。
でも、よく考えたら、Web Form で GET/POST しかリクエストできないとしても、JavaScript だったらできるわけだよね。そんな Web Form の仕様に合わせなくてもいいんじゃね?
そんなことを考えていたら、こんなナイスなページを見つけた。
HTML5より前のHTMLでは、フォームで利用できるHTTPメソッドはGETとPOSTだけである。そのため、PUTやDELETEを使う場合には、JavaScriptが必要になる(JavaScriptでのHTTPリクエストを参照)。一部のケータイのブラウザのように、JavaScriptをサポートしていないブラウザでは、PUTやDELETEはPOSTで代用しなければならない。PUTやDELETEをPOSTで代用する方法には、以下の2つがあるが、フォームで利用できるのは、パラメータ_methodを利用する方法だけである。
あーこれだ! Rails でもやっていたやつだよね?
というわけで、これベースでまた書き直しする。そのあとは、Twitter/Facebook 認証を追加することにしたいと思ってる。