2012-03-20 7 views
2

セキュリティ/検証ログをASP.NET MVC 3アプリケーションに追加しようとしています。取りかかっている。ASP.NET MVC 3:リクエストパラメータにアクセスするActionFilterを、アクションメソッドのシグネチャに合わせて変更する前に作成できますか?

public class RegexValidateAttribute : ActionFilterAttribute 
{ 
    private static readonly ILog logger = 
     LogManager.GetLogger(typeof(RegexValidateAttribute).FullName); 

    public string ParameterName { get; set; } 
    public string Expression { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    { 
     string parameterValue = Convert.ToString(
      filterContext.ActionParameters[ ParameterName ]); 
     if (parameterValue != null) 
     { 
      if (!Regex.IsMatch(parameterValue, Expression)) 
      { 
       logger.Error("INPUT_VALIDATION_EXCEPTION [ Parameter " 
           + ParameterName + " did not match the regex: '" 
           + parameterValue + "' :: '" + Expression + "']"); 
      } 
     } 
    } 
} 

私のコントローラはこれに似て定義されています:私は何をしたいのは、これに似たアクションフィルタで私のアクションメソッドの一部を飾るためにある

public class MyController : Controller 
{   
    [RegexValidate(ParameterName = "id", Expression = @"^\d+$")] 
    public PartialViewResult MyMethod(int id = 0) 
    { 
     <Action Proccessing> 
    } 
} 

「問題」というIアクションメソッドの入力パラメータがintと定義されているため、数値以外の値を渡すと、選択するアクションメソッドを決定するプロセスでパラメータ値が0に変更されます。もちろん、これは私のActionFilterが実行する機会がある前に発生するので、元の無効な値を記録する機会はありません。

これはパラメータをstringとして変更することで解決できますが、多くのコードを書き直してから、アクションメソッドに文字列を変換するための変換ロジックを追加する必要がありますint。

したがって、変更された値の代わりにActionFilterで元の値を取得する方法や、値が変更される前にActionFilterを実行する方法はありますか?

更新: AuthorizationFilterを使用しての以下のダーリンの提案@に基づいて、私は次のようなコードで自分の目標を達成することができました:あなたはActionFilterAttributeから派生する場合

public class RegexValidateAttribute : AuthorizeAttribute 
{ 
    private static readonly ILog logger = 
     LogManager.GetLogger(typeof(RegexValidateAttribute).FullName); 

    public string ParameterName { get; set; } 
    public string Expression { get; set; } 
    public string ReplacementValue { get; set; } 

    public override void OnAuthorization(AuthorizationContext filterContext) 
    { 
     string parameterValue = Convert.ToString(
      filterContext.RouteData.Values[ ParameterName ]); 
     if (parameterValue != null) 
     { 
      if (!Regex.IsMatch(parameterValue, Expression)) 
      { 
       logger.Error("INPUT_VALIDATION_EXCEPTION [ Parameter " 
           + ParameterName + " did not match the regex: '" 
           + parameterValue + "' :: '" + Expression + "']"); 
       filterContext.RouteData.Values[ ParameterName ] = ReplacementValue; 
      } 
     } 
    } 
} 
+0

あなたはルート自体にその制約を入れていない理由は? – MikeSW

+0

@MikeSWあなたはそれが何を意味するか分かりません。あなたが共有できる例がありますか? – Matt

+0

基本ルーティングhttp://msdn.microsoft.com/en-us/library/cc668201.aspx#adding_constraints_to_routesコードはWebフォームのためのものですが、mvcの類似した例はたくさんあります。 – MikeSW

答えて

5

、モデルバインダーは、を実行しますの前にOnActionExecutingメソッドがあります。モデルバインダーが実行されるとクラッシュします。モデルバインダーの前にメソッドを実行する場合は、IAuthorizationFilter インターフェースを実装するか、すでにそのインターフェースを実装しているAuthorizeAttributeから派生させる必要があります。

別の可能性はidが数値でない場合は、コントローラのアクションが起動されないように、あなたのルートに制約を追加することです:

routes.MapRoute(
    "Default", 
    "{controller}/{action}/{id}", 
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }, 
    new { id = @"^\d+$" } 
); 
+0

私はそれを試してみましょう – Matt

関連する問題