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を利用する方法だけである。
http://wiki.unfindable.net/webbook2/index.php/Web%e3%83%9a%e3%83%bc%e3%82%b8%e3%81%8b%e3%82%89%e3%81%aePUT%e3%81%a8DELETE
あーこれだ! Rails でもやっていたやつだよね?
というわけで、これベースでまた書き直しする。そのあとは、Twitter/Facebook 認証を追加することにしたいと思ってる。