ASP.NET MVC 3: можете ли вы создать ActionFilter, который обращается к параметрам запроса ДО того, как они будут изменены, чтобы соответствовать сигнатуре метода действия - PullRequest
2 голосов
/ 20 марта 2012

Я пытаюсь добавить немного журнала безопасности / проверки в приложение ASP.NET MVC 3, над которым я работаю. Я хотел бы украсить некоторые из моих методов действия фильтром действия, подобным следующему:

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>
    }
}

Проблема, с которой я столкнулся, заключается в том, что, поскольку входной параметр метода действия определен как int, если кто-то передает нечисловое значение, значение параметра изменяется на 0 в процессе определения какой метод действий выбрать. Конечно, это происходит ДО того, как мой ActionFilter сможет выполнить, и поэтому у меня нет возможности записать исходное недопустимое значение.

Я знаю, что это можно решить, изменив параметр, который должен быть определен как string, но это потребует от меня переделки большого количества кода, а затем добавления логики преобразования в метод действия для преобразования из строки в инт.

Итак, есть ли способ получить исходное значение в ActionFilter вместо измененного значения или запустить ActionFilter до изменения значения?

Обновление: Основываясь на предложении @ Дарина ниже об использовании AuthorizationFilter, я смог достичь своей цели с помощью кода, подобного следующему:

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;
            }
        }
    }
}

1 Ответ

5 голосов
/ 20 марта 2012

Когда вы наследуете от ActionFilterAttribute , связыватель модели запускается до вашего OnActionExecuting метода. И когда модель связующего работает, он падает. Если вы хотите, чтобы ваш метод работал до связывателя модели, вы должны реализовать IAuthorizationFilter интерфейс или производный от AuthorizeAttribute, который уже реализует этот интерфейс.

Другая возможность - добавить ограничения к вашим маршрутам, чтобы не вызывать действие контроллера, если идентификатор не числовой:

routes.MapRoute(
    "Default",
    "{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional },
    new { id = @"^\d+$" }
);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...