2015-04-17 31 views
4

我有一個控制器操作,應用了一個屬性,如果ModelState有錯誤,它將它們設置爲OnResultExecuting方法中的JsonResult更改filterContext.Result in 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最終對象。 –

相關問題