2009年10月12日月曜日

カスタムActionFilter その1

ASP.NET MVCにはActionFilterという属性がある。これはController全体かまたは個々のActionに対して設定できるようになっている属性で、出力内容を指定の期間キャッシュするOutputCacheAttributeなどがある。今回はこれを使って便利なActionFilterを作ってみようと思う。

ASP.NET MVCのフレームワークにはすでにAuthorizeAttributeという認証していないユーザーのリクエストは無視するActionFilterがある。これはこれで役に立つ機能なのだが、リクエストをまったく無視されてもユーザーフレンドリーとは呼べないので、もっと便利に、認証していないユーザーのリクエストはログインを促すように変更したいと思う。

-RequiredAuthAttribute.cs-
[AttributeUsage(AttributeTargets.All, 
  AllowMultiple = true)]
public class RequiredAuthAttribute : ActionFilterAttribute
{
  public string Route{ get; set; }
  public string Action { get; set; }

public RequiredAuthAttribute()
{
  Route = "Account";
  Action = "Login";
}

private string RedirectUrl()
{
  if (Action.CompareTo("") != 0)
    return "/" + Route + "/" + Action;
  return "/" + Route;
}

public override void OnActionExecuting(
  ActionExecutingContext filterContext)
{
  if (filterContext == null)
  {
    throw new ArgumentNullException(
  "filterContext is null in the RequiredAuth attribute");
  }

  if (!filterContext.HttpContext.User.Identity.IsAuthenticated)
  {
    string loginUrl = RedirectUrl();
    filterContext.HttpContext
     .Response.Redirect(loginUrl, true);
  }
}
}

ActionFilterAttributeを継承したRequiredAuthAttributeクラスのOnActionExecutingで、認証されていないリクエストの場合はリクエスト先のURLを変更している。ここでは/Account/Login/に転送している。

実際の使用方法は下記の通りだ。

-ClipController.cs-
[RequiredAuth]
[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Comment(int clipId, string commentText)
{
  // code here...
}

上記の例はCommentというActionに対するFilterになる。ActionFilterはController全体に対しても付与できる。

以上で既存のコード部分に手を加えるでなく、簡単に認証が必要なActionを実装することができた。このほかにもRoleベースのフィルタリングなども可能なので、ネタが続くだけ紹介していきたいと思う。

0 件のコメント:

コメントを投稿