From 4d905a4110484185173be3de24b59e3b28dd6416 Mon Sep 17 00:00:00 2001 From: Ryan Nowak Date: Mon, 15 May 2017 13:01:42 -0700 Subject: [PATCH] Make our executor methods virtual Fixes #5874 - we are marking these methods virtual just in case someone wants to customize the executors. These are in the 'public internal' namespace but can't really be replaced because they aren't sufficiently virtual. --- .../Internal/ContentResultExecutor.cs | 2 +- .../Internal/FileContentResultExecutor.cs | 25 +++++++++++++++++-- .../Internal/FileResultExecutorBase.cs | 12 ++++++++- .../Internal/FileStreamResultExecutor.cs | 25 +++++++++++++++++-- .../Internal/LocalRedirectResultExecutor.cs | 12 ++++++++- .../Internal/PhysicalFileResultExecutor.cs | 24 ++++++++++++++++-- .../Internal/RedirectResultExecutor.cs | 12 ++++++++- .../RedirectToActionResultExecutor.cs | 12 ++++++++- .../Internal/RedirectToPageResultExecutor.cs | 12 ++++++++- .../Internal/VirtualFileResultExecutor.cs | 24 ++++++++++++++++-- .../Internal/JsonResultExecutor.cs | 2 +- .../Infrastructure/PageResultExecutor.cs | 11 ++++++++ .../Internal/PartialViewResultExecutor.cs | 2 -- .../Internal/ViewComponentResultExecutor.cs | 12 ++++++++- 14 files changed, 169 insertions(+), 18 deletions(-) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ContentResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ContentResultExecutor.cs index c7f149f983..c296700859 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/ContentResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/ContentResultExecutor.cs @@ -20,7 +20,7 @@ namespace Microsoft.AspNetCore.Mvc.Internal _httpResponseStreamWriterFactory = httpResponseStreamWriterFactory; } - public async Task ExecuteAsync(ActionContext context, ContentResult result) + public virtual async Task ExecuteAsync(ActionContext context, ContentResult result) { if (context == null) { diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileContentResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileContentResultExecutor.cs index a2e68dd6f0..5fd8d05654 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileContentResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileContentResultExecutor.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -13,14 +14,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal { } - public Task ExecuteAsync(ActionContext context, FileContentResult result) + public virtual Task ExecuteAsync(ActionContext context, FileContentResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + SetHeadersAndLog(context, result); return WriteFileAsync(context, result); } - private static Task WriteFileAsync(ActionContext context, FileContentResult result) + protected virtual Task WriteFileAsync(ActionContext context, FileContentResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var response = context.HttpContext.Response; return response.Body.WriteAsync(result.FileContents, offset: 0, count: result.FileContents.Length); diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileResultExecutorBase.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileResultExecutorBase.cs index dd046cf234..c6b2e3f148 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileResultExecutorBase.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileResultExecutorBase.cs @@ -16,8 +16,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal protected ILogger Logger { get; } - protected void SetHeadersAndLog(ActionContext context, FileResult result) + protected virtual void SetHeadersAndLog(ActionContext context, FileResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + SetContentType(context, result); SetContentDispositionHeader(context, result); Logger.FileResultExecuting(result.FileDownloadName); diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileStreamResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileStreamResultExecutor.cs index f6785180b1..76bbde3594 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileStreamResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/FileStreamResultExecutor.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Threading.Tasks; using Microsoft.Extensions.Logging; @@ -16,14 +17,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal { } - public Task ExecuteAsync(ActionContext context, FileStreamResult result) + public virtual Task ExecuteAsync(ActionContext context, FileStreamResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + SetHeadersAndLog(context, result); return WriteFileAsync(context, result); } - private static async Task WriteFileAsync(ActionContext context, FileStreamResult result) + protected virtual async Task WriteFileAsync(ActionContext context, FileStreamResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var response = context.HttpContext.Response; var outputStream = response.Body; diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs index 94a0978293..c0fcdb4154 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/LocalRedirectResultExecutor.cs @@ -31,8 +31,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal _urlHelperFactory = urlHelperFactory; } - public void Execute(ActionContext context, LocalRedirectResult result) + public virtual void Execute(ActionContext context, LocalRedirectResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context); // IsLocalUrl is called to handle Urls starting with '~/'. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/PhysicalFileResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/PhysicalFileResultExecutor.cs index c131eefbda..c835790048 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/PhysicalFileResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/PhysicalFileResultExecutor.cs @@ -20,14 +20,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal { } - public Task ExecuteAsync(ActionContext context, PhysicalFileResult result) + public virtual Task ExecuteAsync(ActionContext context, PhysicalFileResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + SetHeadersAndLog(context, result); return WriteFileAsync(context, result); } - private async Task WriteFileAsync(ActionContext context, PhysicalFileResult result) + protected virtual async Task WriteFileAsync(ActionContext context, PhysicalFileResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var response = context.HttpContext.Response; if (!Path.IsPathRooted(result.FileName)) diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs index 4e8d47d45c..503ce41ef1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectResultExecutor.cs @@ -30,8 +30,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal _urlHelperFactory = urlHelperFactory; } - public void Execute(ActionContext context, RedirectResult result) + public virtual void Execute(ActionContext context, RedirectResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context); // IsLocalUrl is called to handle URLs starting with '~/'. diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs index d6ed3e3aef..9ffef08c41 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToActionResultExecutor.cs @@ -31,8 +31,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal _urlHelperFactory = urlHelperFactory; } - public void Execute(ActionContext context, RedirectToActionResult result) + public virtual void Execute(ActionContext context, RedirectToActionResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context); var destinationUrl = urlHelper.Action( diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs index 88b482d5a2..b6c309c6f1 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/RedirectToPageResultExecutor.cs @@ -31,8 +31,18 @@ namespace Microsoft.AspNetCore.Mvc.Internal _urlHelperFactory = urlHelperFactory; } - public void Execute(ActionContext context, RedirectToPageResult result) + public virtual void Execute(ActionContext context, RedirectToPageResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var urlHelper = result.UrlHelper ?? _urlHelperFactory.GetUrlHelper(context); var destinationUrl = urlHelper.Page( result.PageName, diff --git a/src/Microsoft.AspNetCore.Mvc.Core/Internal/VirtualFileResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Core/Internal/VirtualFileResultExecutor.cs index 4b33ec0a98..770a933b9b 100644 --- a/src/Microsoft.AspNetCore.Mvc.Core/Internal/VirtualFileResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Core/Internal/VirtualFileResultExecutor.cs @@ -29,14 +29,34 @@ namespace Microsoft.AspNetCore.Mvc.Internal _hostingEnvironment = hostingEnvironment; } - public Task ExecuteAsync(ActionContext context, VirtualFileResult result) + public virtual Task ExecuteAsync(ActionContext context, VirtualFileResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + SetHeadersAndLog(context, result); return WriteFileAsync(context, result); } - private async Task WriteFileAsync(ActionContext context, VirtualFileResult result) + protected virtual async Task WriteFileAsync(ActionContext context, VirtualFileResult result) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + var response = context.HttpContext.Response; var fileProvider = GetFileProvider(result); diff --git a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs index f64082e9a5..e6322571ff 100644 --- a/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.Formatters.Json/Internal/JsonResultExecutor.cs @@ -85,7 +85,7 @@ namespace Microsoft.AspNetCore.Mvc.Formatters.Json.Internal /// The . /// The . /// A which will complete when writing has completed. - public Task ExecuteAsync(ActionContext context, JsonResult result) + public virtual Task ExecuteAsync(ActionContext context, JsonResult result) { if (context == null) { diff --git a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs index 39ef13ceeb..629a2b1f3e 100644 --- a/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.RazorPages/Infrastructure/PageResultExecutor.cs @@ -1,6 +1,7 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +using System; using System.Diagnostics; using System.Text.Encodings.Web; using System.Threading.Tasks; @@ -49,6 +50,16 @@ namespace Microsoft.AspNetCore.Mvc.RazorPages.Infrastructure /// public virtual Task ExecuteAsync(PageContext pageContext, PageResult result) { + if (pageContext == null) + { + throw new ArgumentNullException(nameof(pageContext)); + } + + if (result == null) + { + throw new ArgumentNullException(nameof(result)); + } + if (result.Model != null) { pageContext.ViewData.Model = result.Model; diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PartialViewResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PartialViewResultExecutor.cs index cd8b476835..369d4d84e9 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PartialViewResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/PartialViewResultExecutor.cs @@ -6,11 +6,9 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using Microsoft.AspNetCore.Mvc.Controllers; using Microsoft.AspNetCore.Mvc.Internal; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ViewEngines; -using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; diff --git a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/ViewComponentResultExecutor.cs b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/ViewComponentResultExecutor.cs index d9b5992400..8715d407b3 100644 --- a/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/ViewComponentResultExecutor.cs +++ b/src/Microsoft.AspNetCore.Mvc.ViewFeatures/Internal/ViewComponentResultExecutor.cs @@ -63,8 +63,18 @@ namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal _tempDataDictionaryFactory = tempDataDictionaryFactory; } - public async Task ExecuteAsync(ActionContext context, ViewComponentResult viewComponentResult) + public virtual async Task ExecuteAsync(ActionContext context, ViewComponentResult viewComponentResult) { + if (context == null) + { + throw new ArgumentNullException(nameof(context)); + } + + if (viewComponentResult == null) + { + throw new ArgumentNullException(nameof(viewComponentResult)); + } + var response = context.HttpContext.Response; var viewData = viewComponentResult.ViewData;