2015-04-17 2 views
4

У меня есть действие контроллера, которое имеет атрибут, в котором, если ModelState имеет ошибки, он устанавливает их как в методе OnResultExecuting.Изменение фильтраContext.Result в OnResultExecuting

Я установил значение в MyAction. Я изменяю его в атрибуте в OnResultExecuting, но в OnResultExecuted, который находится в контроллере, результатом является тот, который у контроллера не тот, который был установлен в атрибуте.

Так что мой вопрос в том, почему значение в OnResultExecuted остается неизменным и как я могу прекратить это делать?

public class MyController:Controller 
{ 
    [ValidateDatedObject(SkipActionExecution = true, LeaveJustModelState = true)] 
    public JsonResult MyAction(ViewModel viewModel) 
    { 
     return new JsonResult { Data = new { Success = false }}; // Setting the initial value 
    } 
    protected override void OnResultExecuted(ResultExecutedContext filterContext) 
    { 
     base.OnResultExecuted(filterContext);//filterContext.Result here is the on from the controller instead of the one from the attribute 
    } 
} 

public class ValidateDatedObject : ModelValidationFilter 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     base.OnResultExecuting(filterContext); 
    }//filterContext.Result here is the one from the attribute 
} 

public abstract class ModelValidationFilter : ActionFilterAttribute 
{ 
    private JsonResult getModelStateAsJsonResult(ModelStateDictionary modelState) 
    { 
     return new JsonResult { Data = new { modelState = SerializeErrors(modelState) } }; 
    } 

    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     filterContext.Result = getModelStateAsJsonResult(filterContext.Controller.ViewData.ModelState); //Setting filterContext.Result here 
    } 
} 

ответ

3

Это потому, что в OnResultExecuting вы заменяете текущий результат с новым экземпляром. Это изменит результат в ResultExecutingContext, но оставит общий результат без изменений.

Вы, однако, может изменить результат, вместо того, чтобы заменить его

public abstract class ModelValidationFilter : ActionFilterAttribute 
{ 
    public override void OnResultExecuting(ResultExecutingContext filterContext) 
    { 
     //Modify the values in the current filterContext.Result instead of replacing it with a new instance 
     var jsonResult = filterContext.Result as JsonResult; 
     if(jsonResult == null) return; 
     //possibly replace Data only under certain conditions 
     jsonResult.Data = new { modelState = SerializeErrors(modelState) }; 
    } 
} 

Причиной этого является то, как ResultFilters выполняются MVC. Вы можете проверить реализацию ControllerActionInvoker.InvokeActionResultFilterRecursive. Это код, вызывающий OnResultExecuting на каждом фильтре, выполняющий действие, а затем вызывающий OnResultExecuted в обратном порядке.

Если вы посмотрите внимательно, вы заметите, что ResultExecutedContext создан со ссылкой на исходный объект actionResult, а не с ссылкой на ResultExecutingContext.Result. (Если вы не установили ResultExecutingContext.Cancel=true, который остановит обработку дополнительных фильтров и вернет любой результат, который он имеет в тот момент, но это также означает, что контроллер OnResultExecute не будет выполнен)

Таким образом, в этом коде есть допущение, что ResultFilters могут изменять значения свойств в ResultExecutingContext.Result, но не полностью заменить его новым экземпляром.

+0

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

+0

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

+0

Большое вам спасибо. Смешно, что он реализован именно так. Он должен быть реализован так, чтобы он принял окончательный объект filterCotnext.result, как и другие атрибуты фильтра. –

 Смежные вопросы

  • Нет связанных вопросов^_^