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 認証を追加することにしたいと思ってる。