From a5afd3eb42796d99669e2f32c845a103bd0d6240 Mon Sep 17 00:00:00 2001 From: Yishai Galatzer Date: Fri, 25 Apr 2014 14:12:36 -0700 Subject: [PATCH] ActionResult implements IActionResult, and all our default implementations now use ActionResult All controller methods return the specific ActionResult type --- .../Travel/Controllers/HomeController.cs | 2 +- samples/MvcSample.Web/FiltersController.cs | 10 +++--- samples/MvcSample.Web/Home2Controller.cs | 8 ++--- samples/MvcSample.Web/HomeController.cs | 20 +++++------ samples/MvcSample.Web/LinkController.cs | 2 +- samples/MvcSample.Web/OverloadController.cs | 11 +++--- src/Microsoft.AspNet.Mvc.Core/ActionResult.cs | 18 ++++++++++ .../ActionResultHelper.cs | 35 ++++++++----------- .../ActionResults/ContentResult.cs | 9 ++--- .../ActionResults/EmptyResult.cs | 6 ++-- .../ActionResults/HttpStatusCodeResult.cs | 6 ++-- .../ActionResults/IJsonResult.cs | 10 ------ .../ActionResults/JsonResult.cs | 6 ++-- .../ActionResults/NoContentResult.cs | 11 ++---- .../ActionResults/RedirectResult.cs | 6 ++-- .../ActionResults/RedirectToActionResult.cs | 6 ++-- .../ActionResults/RedirectToRouteResult.cs | 6 ++-- .../ActionResults/ViewResult.cs | 6 ++-- src/Microsoft.AspNet.Mvc.Core/Controller.cs | 16 ++++----- .../IActionResultHelper.cs | 8 ++--- .../Microsoft.AspNet.Mvc.Core.kproj | 2 +- 21 files changed, 90 insertions(+), 114 deletions(-) create mode 100644 src/Microsoft.AspNet.Mvc.Core/ActionResult.cs delete mode 100644 src/Microsoft.AspNet.Mvc.Core/ActionResults/IJsonResult.cs diff --git a/samples/MvcSample.Web/Areas/Travel/Controllers/HomeController.cs b/samples/MvcSample.Web/Areas/Travel/Controllers/HomeController.cs index 5dd329b4f6..d5d09c598b 100644 --- a/samples/MvcSample.Web/Areas/Travel/Controllers/HomeController.cs +++ b/samples/MvcSample.Web/Areas/Travel/Controllers/HomeController.cs @@ -8,7 +8,7 @@ namespace MvcSample.Web.Areas.Travel.Controllers { public IActionResult Index() { - return Result.Content("This is the Travel/Home/Index action."); + return Content("This is the Travel/Home/Index action."); } } } \ No newline at end of file diff --git a/samples/MvcSample.Web/FiltersController.cs b/samples/MvcSample.Web/FiltersController.cs index ddb654b7dd..748ff9e59d 100644 --- a/samples/MvcSample.Web/FiltersController.cs +++ b/samples/MvcSample.Web/FiltersController.cs @@ -21,7 +21,7 @@ namespace MvcSample.Web [AllowAnonymous] [AgeEnhancer] [Delay(500)] - public IActionResult Index(int age, string userName) + public ActionResult Index(int age, string userName) { if (!string.IsNullOrEmpty(userName)) { @@ -33,26 +33,26 @@ namespace MvcSample.Web return View("MyView", _user); } - public IActionResult Blocked(int age, string userName) + public ActionResult Blocked(int age, string userName) { return Index(age, userName); } [Authorize("Permission", "CanViewPage")] - public IActionResult NotGrantedClaim(int age, string userName) + public ActionResult NotGrantedClaim(int age, string userName) { return Index(age, userName); } [FakeUser] [Authorize("Permission", "CanViewPage", "CanViewAnything")] - public IActionResult AllGranted(int age, string userName) + public ActionResult AllGranted(int age, string userName) { return Index(age, userName); } [ErrorMessages, AllowAnonymous] - public IActionResult Crash(string message) + public ActionResult Crash(string message) { throw new Exception(message); } diff --git a/samples/MvcSample.Web/Home2Controller.cs b/samples/MvcSample.Web/Home2Controller.cs index a485abf830..06394cafe8 100644 --- a/samples/MvcSample.Web/Home2Controller.cs +++ b/samples/MvcSample.Web/Home2Controller.cs @@ -30,7 +30,7 @@ namespace MvcSample.Web.RandomNameSpace return "Hello World: my namespace is " + this.GetType().Namespace; } - public IActionResult Something() + public ActionResult Something() { return new ContentResult { @@ -38,9 +38,9 @@ namespace MvcSample.Web.RandomNameSpace }; } - public IActionResult Hello() + public ActionResult Hello() { - return Result.Content("Hello World"); + return Result.Content("Hello World", null, null); } public void Raw() @@ -48,7 +48,7 @@ namespace MvcSample.Web.RandomNameSpace Context.Response.WriteAsync("Hello World raw"); } - public IActionResult UserJson() + public ActionResult UserJson() { var jsonResult = Result.Json(_user); jsonResult.Indent = false; diff --git a/samples/MvcSample.Web/HomeController.cs b/samples/MvcSample.Web/HomeController.cs index f7ff8977b1..4ecaecd733 100644 --- a/samples/MvcSample.Web/HomeController.cs +++ b/samples/MvcSample.Web/HomeController.cs @@ -11,12 +11,12 @@ namespace MvcSample.Web private static readonly IEnumerable _addresses = CreateAddresses(); private static readonly IEnumerable _ages = CreateAges(); - public IActionResult Index() + public ActionResult Index() { return View("MyView", User()); } - public IActionResult ValidationSummary() + public ActionResult ValidationSummary() { ModelState.AddModelError("something", "Something happened, show up in validation summary."); @@ -26,7 +26,7 @@ namespace MvcSample.Web /// /// Action that shows metadata when model is null. /// - public IActionResult Create() + public ActionResult Create() { ViewBag.Address = _addresses; ViewBag.Ages = _ages; @@ -37,7 +37,7 @@ namespace MvcSample.Web /// /// Action that shows metadata when model is non-null. /// - public IActionResult Edit(User user) + public ActionResult Edit(User user) { ViewBag.Address = _addresses; ViewBag.Age = _ages; @@ -49,7 +49,7 @@ namespace MvcSample.Web /// /// Action that exercises query\form based model binding. /// - public IActionResult SaveUser(User user) + public ActionResult SaveUser(User user) { return View("MyView", user); } @@ -57,12 +57,12 @@ namespace MvcSample.Web /// /// Action that exercises input formatter /// - public IActionResult Post([FromBody]User user) + public ActionResult Post([FromBody]User user) { return View("MyView", user); } - public IActionResult Something() + public ActionResult Something() { return new ContentResult { @@ -70,9 +70,9 @@ namespace MvcSample.Web }; } - public IActionResult Hello() + public ActionResult Hello() { - return Result.Content("Hello World"); + return Content("Hello World"); } public void Raw() @@ -104,7 +104,7 @@ namespace MvcSample.Web /// /// Action that exercises default view names. /// - public IActionResult MyView() + public ActionResult MyView() { return View(User()); } diff --git a/samples/MvcSample.Web/LinkController.cs b/samples/MvcSample.Web/LinkController.cs index a8c1227086..a423af189d 100644 --- a/samples/MvcSample.Web/LinkController.cs +++ b/samples/MvcSample.Web/LinkController.cs @@ -6,7 +6,7 @@ namespace MvcSample.Web { public class LinkController : Controller { - public IActionResult Details() + public ActionResult Details() { return View(); } diff --git a/samples/MvcSample.Web/OverloadController.cs b/samples/MvcSample.Web/OverloadController.cs index 97838a7e87..44388232ca 100644 --- a/samples/MvcSample.Web/OverloadController.cs +++ b/samples/MvcSample.Web/OverloadController.cs @@ -12,19 +12,20 @@ namespace MvcSample.Web _result = result; } + // All results implement IActionResult so it can be safely returned. public IActionResult Get() { - return _result.Content("Get()"); + return _result.Content("Get()", null, null); } - public IActionResult Get(int id) + public ActionResult Get(int id) { - return _result.Content("Get(id)"); + return _result.Content("Get(id)", null, null); } - public IActionResult Get(int id, string name) + public ActionResult Get(int id, string name) { - return _result.Content("Get(id, name)"); + return _result.Content("Get(id, name)", null, null); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResult.cs new file mode 100644 index 0000000000..8cddf65679 --- /dev/null +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResult.cs @@ -0,0 +1,18 @@ +using System; +using System.Threading.Tasks; + +namespace Microsoft.AspNet.Mvc +{ + public abstract class ActionResult : IActionResult + { + public virtual Task ExecuteResultAsync(ActionContext context) + { + ExecuteResult(context); + return Task.FromResult(true); + } + + public virtual void ExecuteResult(ActionContext context) + { + } + } +} \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResultHelper.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResultHelper.cs index 3099dc07b3..38b375c344 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResultHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResultHelper.cs @@ -15,39 +15,32 @@ namespace Microsoft.AspNet.Mvc _viewEngine = viewEngine; } - public IActionResult Content(string value) + public ContentResult Content(string value, string contentType, Encoding contentEncoding) { - return new ContentResult - { - Content = value - }; - } - - public IActionResult Content(string value, string contentType) - { - return new ContentResult + var result = new ContentResult { Content = value, - ContentType = contentType }; - } - public IActionResult Content(string value, string contentType, Encoding contentEncoding) - { - return new ContentResult + if (contentType != null) { - Content = value, - ContentType = contentType, - ContentEncoding = contentEncoding - }; + result.Content = contentType; + } + + if (contentEncoding != null) + { + result.ContentEncoding = contentEncoding; + } + + return result; } - public IJsonResult Json(object value) + public JsonResult Json(object value) { return new JsonResult(value); } - public IActionResult View(string view, ViewDataDictionary viewData) + public ViewResult View(string view, ViewDataDictionary viewData) { return new ViewResult(_serviceProvider, _viewEngine) { diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ContentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ContentResult.cs index dda593864f..1b86d02878 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ContentResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ContentResult.cs @@ -5,7 +5,7 @@ using Microsoft.AspNet.Abstractions; namespace Microsoft.AspNet.Mvc { - public class ContentResult : IActionResult + public class ContentResult : ActionResult { public string Content { get; set; } @@ -13,13 +13,8 @@ namespace Microsoft.AspNet.Mvc public string ContentType { get; set; } - public async Task ExecuteResultAsync(ActionContext context) + public override async Task ExecuteResultAsync([NotNull] ActionContext context) { - if (context == null) - { - throw new ArgumentNullException("context"); - } - HttpResponse response = context.HttpContext.Response; if (!String.IsNullOrEmpty(ContentType)) diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/EmptyResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/EmptyResult.cs index faccb2c60d..86250feef2 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/EmptyResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/EmptyResult.cs @@ -2,7 +2,7 @@ namespace Microsoft.AspNet.Mvc { - public class EmptyResult : IActionResult + public class EmptyResult : ActionResult { private static readonly EmptyResult _singleton = new EmptyResult(); @@ -11,11 +11,9 @@ namespace Microsoft.AspNet.Mvc get { return _singleton; } } - #pragma warning disable 1998 - public async Task ExecuteResultAsync(ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { context.HttpContext.Response.StatusCode = 204; } - #pragma warning restore 1998 } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/HttpStatusCodeResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/HttpStatusCodeResult.cs index 84a88fc104..6c85a9b879 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/HttpStatusCodeResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/HttpStatusCodeResult.cs @@ -2,7 +2,7 @@ namespace Microsoft.AspNet.Mvc { - public class HttpStatusCodeResult : IActionResult + public class HttpStatusCodeResult : ActionResult { private int _statusCode; @@ -11,11 +11,9 @@ namespace Microsoft.AspNet.Mvc _statusCode = statusCode; } - #pragma warning disable 1998 - public async Task ExecuteResultAsync(ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { context.HttpContext.Response.StatusCode = _statusCode; } - #pragma warning restore 1998 } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/IJsonResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/IJsonResult.cs deleted file mode 100644 index a76a05a13d..0000000000 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/IJsonResult.cs +++ /dev/null @@ -1,10 +0,0 @@ -using System.Text; - -namespace Microsoft.AspNet.Mvc -{ - public interface IJsonResult : IActionResult - { - Encoding Encoding { get; set; } - bool Indent { get; set; } - } -} diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs index 8bc1fc5bfc..5cea8777f6 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/JsonResult.cs @@ -7,7 +7,7 @@ using Newtonsoft.Json; namespace Microsoft.AspNet.Mvc { - public class JsonResult : IJsonResult + public class JsonResult : ActionResult { private readonly object _returnValue; @@ -59,8 +59,7 @@ namespace Microsoft.AspNet.Mvc } } - #pragma warning disable 1998 - public async Task ExecuteResultAsync(ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { HttpResponse response = context.HttpContext.Response; @@ -77,6 +76,5 @@ namespace Microsoft.AspNet.Mvc formatter.WriteObject(writer, _returnValue); } } - #pragma warning restore 1998 } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/NoContentResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/NoContentResult.cs index e97ee8a1d5..3a4bfddd4b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/NoContentResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/NoContentResult.cs @@ -5,15 +5,10 @@ using Microsoft.AspNet.Abstractions; namespace Microsoft.AspNet.Mvc { - public class NoContentResult : IActionResult + public class NoContentResult : ActionResult { - public async Task ExecuteResultAsync(ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { - if (context == null) - { - throw new ArgumentNullException("context"); - } - HttpResponse response = context.HttpContext.Response; #if NET45 @@ -21,8 +16,6 @@ namespace Microsoft.AspNet.Mvc #else response.StatusCode = 204; #endif - - await Task.FromResult(false); } } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs index 042d03985c..57bc4e2a43 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectResult.cs @@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core; namespace Microsoft.AspNet.Mvc { - public class RedirectResult : IActionResult + public class RedirectResult : ActionResult { public RedirectResult(string url) : this(url, permanent: false) @@ -27,14 +27,12 @@ namespace Microsoft.AspNet.Mvc public string Url { get; private set; } - #pragma warning disable 1998 - public async Task ExecuteResultAsync([NotNull] ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { // It is redirected directly to the input URL. // We would use the context to construct the full URL, // only when relative URLs are supported. (Issue - WEBFX-202) context.HttpContext.Response.Redirect(Url, Permanent); } - #pragma warning restore 1998 } } \ No newline at end of file diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToActionResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToActionResult.cs index 72f7670f9a..a3e1e72df5 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToActionResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToActionResult.cs @@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core; namespace Microsoft.AspNet.Mvc { - public class RedirectToActionResult : IActionResult + public class RedirectToActionResult : ActionResult { public RedirectToActionResult([NotNull] IUrlHelper urlHelper, string actionName, string controllerName, IDictionary routeValues) @@ -33,8 +33,7 @@ namespace Microsoft.AspNet.Mvc public bool Permanent { get; private set; } - #pragma warning disable 1998 - public async Task ExecuteResultAsync([NotNull] ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { var destinationUrl = UrlHelper.Action(ActionName, ControllerName, RouteValues); @@ -45,6 +44,5 @@ namespace Microsoft.AspNet.Mvc context.HttpContext.Response.Redirect(destinationUrl, Permanent); } - #pragma warning restore 1998 } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToRouteResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToRouteResult.cs index 885bb08e9a..bb4aa9627b 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToRouteResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/RedirectToRouteResult.cs @@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core; namespace Microsoft.AspNet.Mvc { - public class RedirectToRouteResult : IActionResult + public class RedirectToRouteResult : ActionResult { public RedirectToRouteResult([NotNull] IUrlHelper urlHelper, IDictionary routeValues) : this(urlHelper, routeValues, permanent: false) @@ -26,8 +26,7 @@ namespace Microsoft.AspNet.Mvc public bool Permanent { get; private set; } - #pragma warning disable 1998 - public async Task ExecuteResultAsync([NotNull] ActionContext context) + public override void ExecuteResult([NotNull] ActionContext context) { var destinationUrl = UrlHelper.RouteUrl(RouteValues); @@ -38,6 +37,5 @@ namespace Microsoft.AspNet.Mvc context.HttpContext.Response.Redirect(destinationUrl, Permanent); } - #pragma warning restore 1998 } } diff --git a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs index 08e8f933cb..844dd8fad9 100644 --- a/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs +++ b/src/Microsoft.AspNet.Mvc.Core/ActionResults/ViewResult.cs @@ -9,12 +9,12 @@ using Microsoft.AspNet.Mvc.Rendering; namespace Microsoft.AspNet.Mvc { - public class ViewResult : IActionResult + public class ViewResult : ActionResult { private readonly IServiceProvider _serviceProvider; private readonly IViewEngine _viewEngine; - public ViewResult(IServiceProvider serviceProvider, IViewEngine viewEngine) + public ViewResult([NotNull] IServiceProvider serviceProvider, [NotNull] IViewEngine viewEngine) { _serviceProvider = serviceProvider; _viewEngine = viewEngine; @@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc public ViewDataDictionary ViewData { get; set; } - public async Task ExecuteResultAsync([NotNull] ActionContext context) + public override async Task ExecuteResultAsync([NotNull] ActionContext context) { var viewName = ViewName ?? context.ActionDescriptor.Name; var view = FindView(context.RouteValues, viewName); diff --git a/src/Microsoft.AspNet.Mvc.Core/Controller.cs b/src/Microsoft.AspNet.Mvc.Core/Controller.cs index 9040abb6e1..750188c621 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Controller.cs +++ b/src/Microsoft.AspNet.Mvc.Core/Controller.cs @@ -53,23 +53,23 @@ namespace Microsoft.AspNet.Mvc } } - public IActionResult View() + public ViewResult View() { return View(view: null); } - public IActionResult View(string view) + public ViewResult View(string view) { return View(view, model: null); } // TODO #110: May need here and in the overload below. - public IActionResult View(object model) + public ViewResult View(object model) { return View(view: null, model: model); } - public IActionResult View(string view, object model) + public ViewResult View(string view, object model) { // Do not override ViewData.Model unless passed a non-null value. if (model != null) @@ -80,22 +80,22 @@ namespace Microsoft.AspNet.Mvc return Result.View(view, ViewData); } - public IActionResult Content(string content) + public ContentResult Content(string content) { return Content(content, contentType: null); } - public IActionResult Content(string content, string contentType) + public ContentResult Content(string content, string contentType) { return Content(content, contentType, contentEncoding: null); } - public IActionResult Content(string content, string contentType, Encoding contentEncoding) + public ContentResult Content(string content, string contentType, Encoding contentEncoding) { return Result.Content(content, contentType, contentEncoding); } - public IJsonResult Json(object value) + public JsonResult Json(object value) { return Result.Json(value); } diff --git a/src/Microsoft.AspNet.Mvc.Core/IActionResultHelper.cs b/src/Microsoft.AspNet.Mvc.Core/IActionResultHelper.cs index 5785a789c0..55b3292863 100644 --- a/src/Microsoft.AspNet.Mvc.Core/IActionResultHelper.cs +++ b/src/Microsoft.AspNet.Mvc.Core/IActionResultHelper.cs @@ -5,10 +5,8 @@ namespace Microsoft.AspNet.Mvc { public interface IActionResultHelper { - IActionResult Content(string value); - IActionResult Content(string value, string contentType); - IActionResult Content(string value, string contentType, Encoding contentEncoding); - IJsonResult Json(object value); - IActionResult View(string view, ViewDataDictionary viewData); + ContentResult Content(string value, string contentType, Encoding contentEncoding); + JsonResult Json(object value); + ViewResult View(string view, ViewDataDictionary viewData); } } diff --git a/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj b/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj index 37d06786c7..b2197b43ab 100644 --- a/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj +++ b/src/Microsoft.AspNet.Mvc.Core/Microsoft.AspNet.Mvc.Core.kproj @@ -30,12 +30,12 @@ + -