ActionResult implements IActionResult, and all our default implementations now use ActionResult

All controller methods return the specific ActionResult type
This commit is contained in:
Yishai Galatzer 2014-04-25 14:12:36 -07:00
parent f5ba63ea1e
commit a5afd3eb42
21 changed files with 90 additions and 114 deletions

View File

@ -8,7 +8,7 @@ namespace MvcSample.Web.Areas.Travel.Controllers
{ {
public IActionResult Index() public IActionResult Index()
{ {
return Result.Content("This is the Travel/Home/Index action."); return Content("This is the Travel/Home/Index action.");
} }
} }
} }

View File

@ -21,7 +21,7 @@ namespace MvcSample.Web
[AllowAnonymous] [AllowAnonymous]
[AgeEnhancer] [AgeEnhancer]
[Delay(500)] [Delay(500)]
public IActionResult Index(int age, string userName) public ActionResult Index(int age, string userName)
{ {
if (!string.IsNullOrEmpty(userName)) if (!string.IsNullOrEmpty(userName))
{ {
@ -33,26 +33,26 @@ namespace MvcSample.Web
return View("MyView", _user); return View("MyView", _user);
} }
public IActionResult Blocked(int age, string userName) public ActionResult Blocked(int age, string userName)
{ {
return Index(age, userName); return Index(age, userName);
} }
[Authorize("Permission", "CanViewPage")] [Authorize("Permission", "CanViewPage")]
public IActionResult NotGrantedClaim(int age, string userName) public ActionResult NotGrantedClaim(int age, string userName)
{ {
return Index(age, userName); return Index(age, userName);
} }
[FakeUser] [FakeUser]
[Authorize("Permission", "CanViewPage", "CanViewAnything")] [Authorize("Permission", "CanViewPage", "CanViewAnything")]
public IActionResult AllGranted(int age, string userName) public ActionResult AllGranted(int age, string userName)
{ {
return Index(age, userName); return Index(age, userName);
} }
[ErrorMessages, AllowAnonymous] [ErrorMessages, AllowAnonymous]
public IActionResult Crash(string message) public ActionResult Crash(string message)
{ {
throw new Exception(message); throw new Exception(message);
} }

View File

@ -30,7 +30,7 @@ namespace MvcSample.Web.RandomNameSpace
return "Hello World: my namespace is " + this.GetType().Namespace; return "Hello World: my namespace is " + this.GetType().Namespace;
} }
public IActionResult Something() public ActionResult Something()
{ {
return new ContentResult 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() public void Raw()
@ -48,7 +48,7 @@ namespace MvcSample.Web.RandomNameSpace
Context.Response.WriteAsync("Hello World raw"); Context.Response.WriteAsync("Hello World raw");
} }
public IActionResult UserJson() public ActionResult UserJson()
{ {
var jsonResult = Result.Json(_user); var jsonResult = Result.Json(_user);
jsonResult.Indent = false; jsonResult.Indent = false;

View File

@ -11,12 +11,12 @@ namespace MvcSample.Web
private static readonly IEnumerable<SelectListItem> _addresses = CreateAddresses(); private static readonly IEnumerable<SelectListItem> _addresses = CreateAddresses();
private static readonly IEnumerable<SelectListItem> _ages = CreateAges(); private static readonly IEnumerable<SelectListItem> _ages = CreateAges();
public IActionResult Index() public ActionResult Index()
{ {
return View("MyView", User()); return View("MyView", User());
} }
public IActionResult ValidationSummary() public ActionResult ValidationSummary()
{ {
ModelState.AddModelError("something", "Something happened, show up in validation summary."); ModelState.AddModelError("something", "Something happened, show up in validation summary.");
@ -26,7 +26,7 @@ namespace MvcSample.Web
/// <summary> /// <summary>
/// Action that shows metadata when model is <c>null</c>. /// Action that shows metadata when model is <c>null</c>.
/// </summary> /// </summary>
public IActionResult Create() public ActionResult Create()
{ {
ViewBag.Address = _addresses; ViewBag.Address = _addresses;
ViewBag.Ages = _ages; ViewBag.Ages = _ages;
@ -37,7 +37,7 @@ namespace MvcSample.Web
/// <summary> /// <summary>
/// Action that shows metadata when model is non-<c>null</c>. /// Action that shows metadata when model is non-<c>null</c>.
/// </summary> /// </summary>
public IActionResult Edit(User user) public ActionResult Edit(User user)
{ {
ViewBag.Address = _addresses; ViewBag.Address = _addresses;
ViewBag.Age = _ages; ViewBag.Age = _ages;
@ -49,7 +49,7 @@ namespace MvcSample.Web
/// <summary> /// <summary>
/// Action that exercises query\form based model binding. /// Action that exercises query\form based model binding.
/// </summary> /// </summary>
public IActionResult SaveUser(User user) public ActionResult SaveUser(User user)
{ {
return View("MyView", user); return View("MyView", user);
} }
@ -57,12 +57,12 @@ namespace MvcSample.Web
/// <summary> /// <summary>
/// Action that exercises input formatter /// Action that exercises input formatter
/// </summary> /// </summary>
public IActionResult Post([FromBody]User user) public ActionResult Post([FromBody]User user)
{ {
return View("MyView", user); return View("MyView", user);
} }
public IActionResult Something() public ActionResult Something()
{ {
return new ContentResult 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() public void Raw()
@ -104,7 +104,7 @@ namespace MvcSample.Web
/// <summary> /// <summary>
/// Action that exercises default view names. /// Action that exercises default view names.
/// </summary> /// </summary>
public IActionResult MyView() public ActionResult MyView()
{ {
return View(User()); return View(User());
} }

View File

@ -6,7 +6,7 @@ namespace MvcSample.Web
{ {
public class LinkController : Controller public class LinkController : Controller
{ {
public IActionResult Details() public ActionResult Details()
{ {
return View(); return View();
} }

View File

@ -12,19 +12,20 @@ namespace MvcSample.Web
_result = result; _result = result;
} }
// All results implement IActionResult so it can be safely returned.
public IActionResult Get() 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);
} }
} }
} }

View File

@ -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)
{
}
}
}

View File

@ -15,39 +15,32 @@ namespace Microsoft.AspNet.Mvc
_viewEngine = viewEngine; _viewEngine = viewEngine;
} }
public IActionResult Content(string value) public ContentResult Content(string value, string contentType, Encoding contentEncoding)
{ {
return new ContentResult var result = new ContentResult
{
Content = value
};
}
public IActionResult Content(string value, string contentType)
{
return new ContentResult
{ {
Content = value, Content = value,
ContentType = contentType
}; };
}
public IActionResult Content(string value, string contentType, Encoding contentEncoding) if (contentType != null)
{
return new ContentResult
{ {
Content = value, result.Content = contentType;
ContentType = contentType, }
ContentEncoding = contentEncoding
}; if (contentEncoding != null)
{
result.ContentEncoding = contentEncoding;
}
return result;
} }
public IJsonResult Json(object value) public JsonResult Json(object value)
{ {
return new JsonResult(value); return new JsonResult(value);
} }
public IActionResult View(string view, ViewDataDictionary viewData) public ViewResult View(string view, ViewDataDictionary viewData)
{ {
return new ViewResult(_serviceProvider, _viewEngine) return new ViewResult(_serviceProvider, _viewEngine)
{ {

View File

@ -5,7 +5,7 @@ using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class ContentResult : IActionResult public class ContentResult : ActionResult
{ {
public string Content { get; set; } public string Content { get; set; }
@ -13,13 +13,8 @@ namespace Microsoft.AspNet.Mvc
public string ContentType { get; set; } 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; HttpResponse response = context.HttpContext.Response;
if (!String.IsNullOrEmpty(ContentType)) if (!String.IsNullOrEmpty(ContentType))

View File

@ -2,7 +2,7 @@
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class EmptyResult : IActionResult public class EmptyResult : ActionResult
{ {
private static readonly EmptyResult _singleton = new EmptyResult(); private static readonly EmptyResult _singleton = new EmptyResult();
@ -11,11 +11,9 @@ namespace Microsoft.AspNet.Mvc
get { return _singleton; } get { return _singleton; }
} }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync(ActionContext context)
{ {
context.HttpContext.Response.StatusCode = 204; context.HttpContext.Response.StatusCode = 204;
} }
#pragma warning restore 1998
} }
} }

View File

@ -2,7 +2,7 @@
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class HttpStatusCodeResult : IActionResult public class HttpStatusCodeResult : ActionResult
{ {
private int _statusCode; private int _statusCode;
@ -11,11 +11,9 @@ namespace Microsoft.AspNet.Mvc
_statusCode = statusCode; _statusCode = statusCode;
} }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync(ActionContext context)
{ {
context.HttpContext.Response.StatusCode = _statusCode; context.HttpContext.Response.StatusCode = _statusCode;
} }
#pragma warning restore 1998
} }
} }

View File

@ -1,10 +0,0 @@
using System.Text;
namespace Microsoft.AspNet.Mvc
{
public interface IJsonResult : IActionResult
{
Encoding Encoding { get; set; }
bool Indent { get; set; }
}
}

View File

@ -7,7 +7,7 @@ using Newtonsoft.Json;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class JsonResult : IJsonResult public class JsonResult : ActionResult
{ {
private readonly object _returnValue; private readonly object _returnValue;
@ -59,8 +59,7 @@ namespace Microsoft.AspNet.Mvc
} }
} }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync(ActionContext context)
{ {
HttpResponse response = context.HttpContext.Response; HttpResponse response = context.HttpContext.Response;
@ -77,6 +76,5 @@ namespace Microsoft.AspNet.Mvc
formatter.WriteObject(writer, _returnValue); formatter.WriteObject(writer, _returnValue);
} }
} }
#pragma warning restore 1998
} }
} }

View File

@ -5,15 +5,10 @@ using Microsoft.AspNet.Abstractions;
namespace Microsoft.AspNet.Mvc 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; HttpResponse response = context.HttpContext.Response;
#if NET45 #if NET45
@ -21,8 +16,6 @@ namespace Microsoft.AspNet.Mvc
#else #else
response.StatusCode = 204; response.StatusCode = 204;
#endif #endif
await Task.FromResult(false);
} }
} }
} }

View File

@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class RedirectResult : IActionResult public class RedirectResult : ActionResult
{ {
public RedirectResult(string url) public RedirectResult(string url)
: this(url, permanent: false) : this(url, permanent: false)
@ -27,14 +27,12 @@ namespace Microsoft.AspNet.Mvc
public string Url { get; private set; } public string Url { get; private set; }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync([NotNull] ActionContext context)
{ {
// It is redirected directly to the input URL. // It is redirected directly to the input URL.
// We would use the context to construct the full URL, // We would use the context to construct the full URL,
// only when relative URLs are supported. (Issue - WEBFX-202) // only when relative URLs are supported. (Issue - WEBFX-202)
context.HttpContext.Response.Redirect(Url, Permanent); context.HttpContext.Response.Redirect(Url, Permanent);
} }
#pragma warning restore 1998
} }
} }

View File

@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class RedirectToActionResult : IActionResult public class RedirectToActionResult : ActionResult
{ {
public RedirectToActionResult([NotNull] IUrlHelper urlHelper, string actionName, public RedirectToActionResult([NotNull] IUrlHelper urlHelper, string actionName,
string controllerName, IDictionary<string, object> routeValues) string controllerName, IDictionary<string, object> routeValues)
@ -33,8 +33,7 @@ namespace Microsoft.AspNet.Mvc
public bool Permanent { get; private set; } public bool Permanent { get; private set; }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync([NotNull] ActionContext context)
{ {
var destinationUrl = UrlHelper.Action(ActionName, ControllerName, RouteValues); var destinationUrl = UrlHelper.Action(ActionName, ControllerName, RouteValues);
@ -45,6 +44,5 @@ namespace Microsoft.AspNet.Mvc
context.HttpContext.Response.Redirect(destinationUrl, Permanent); context.HttpContext.Response.Redirect(destinationUrl, Permanent);
} }
#pragma warning restore 1998
} }
} }

View File

@ -5,7 +5,7 @@ using Microsoft.AspNet.Mvc.Core;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class RedirectToRouteResult : IActionResult public class RedirectToRouteResult : ActionResult
{ {
public RedirectToRouteResult([NotNull] IUrlHelper urlHelper, IDictionary<string, object> routeValues) public RedirectToRouteResult([NotNull] IUrlHelper urlHelper, IDictionary<string, object> routeValues)
: this(urlHelper, routeValues, permanent: false) : this(urlHelper, routeValues, permanent: false)
@ -26,8 +26,7 @@ namespace Microsoft.AspNet.Mvc
public bool Permanent { get; private set; } public bool Permanent { get; private set; }
#pragma warning disable 1998 public override void ExecuteResult([NotNull] ActionContext context)
public async Task ExecuteResultAsync([NotNull] ActionContext context)
{ {
var destinationUrl = UrlHelper.RouteUrl(RouteValues); var destinationUrl = UrlHelper.RouteUrl(RouteValues);
@ -38,6 +37,5 @@ namespace Microsoft.AspNet.Mvc
context.HttpContext.Response.Redirect(destinationUrl, Permanent); context.HttpContext.Response.Redirect(destinationUrl, Permanent);
} }
#pragma warning restore 1998
} }
} }

View File

@ -9,12 +9,12 @@ using Microsoft.AspNet.Mvc.Rendering;
namespace Microsoft.AspNet.Mvc namespace Microsoft.AspNet.Mvc
{ {
public class ViewResult : IActionResult public class ViewResult : ActionResult
{ {
private readonly IServiceProvider _serviceProvider; private readonly IServiceProvider _serviceProvider;
private readonly IViewEngine _viewEngine; private readonly IViewEngine _viewEngine;
public ViewResult(IServiceProvider serviceProvider, IViewEngine viewEngine) public ViewResult([NotNull] IServiceProvider serviceProvider, [NotNull] IViewEngine viewEngine)
{ {
_serviceProvider = serviceProvider; _serviceProvider = serviceProvider;
_viewEngine = viewEngine; _viewEngine = viewEngine;
@ -24,7 +24,7 @@ namespace Microsoft.AspNet.Mvc
public ViewDataDictionary ViewData { get; set; } 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 viewName = ViewName ?? context.ActionDescriptor.Name;
var view = FindView(context.RouteValues, viewName); var view = FindView(context.RouteValues, viewName);

View File

@ -53,23 +53,23 @@ namespace Microsoft.AspNet.Mvc
} }
} }
public IActionResult View() public ViewResult View()
{ {
return View(view: null); return View(view: null);
} }
public IActionResult View(string view) public ViewResult View(string view)
{ {
return View(view, model: null); return View(view, model: null);
} }
// TODO #110: May need <TModel> here and in the overload below. // TODO #110: May need <TModel> here and in the overload below.
public IActionResult View(object model) public ViewResult View(object model)
{ {
return View(view: null, model: 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. // Do not override ViewData.Model unless passed a non-null value.
if (model != null) if (model != null)
@ -80,22 +80,22 @@ namespace Microsoft.AspNet.Mvc
return Result.View(view, ViewData); return Result.View(view, ViewData);
} }
public IActionResult Content(string content) public ContentResult Content(string content)
{ {
return Content(content, contentType: null); 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); 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); return Result.Content(content, contentType, contentEncoding);
} }
public IJsonResult Json(object value) public JsonResult Json(object value)
{ {
return Result.Json(value); return Result.Json(value);
} }

View File

@ -5,10 +5,8 @@ namespace Microsoft.AspNet.Mvc
{ {
public interface IActionResultHelper public interface IActionResultHelper
{ {
IActionResult Content(string value); ContentResult Content(string value, string contentType, Encoding contentEncoding);
IActionResult Content(string value, string contentType); JsonResult Json(object value);
IActionResult Content(string value, string contentType, Encoding contentEncoding); ViewResult View(string view, ViewDataDictionary viewData);
IJsonResult Json(object value);
IActionResult View(string view, ViewDataDictionary viewData);
} }
} }

View File

@ -30,12 +30,12 @@
<Compile Include="ActionInvokerProviderContext.cs" /> <Compile Include="ActionInvokerProviderContext.cs" />
<Compile Include="ActionMethodSelectorAttribute.cs" /> <Compile Include="ActionMethodSelectorAttribute.cs" />
<Compile Include="ActionNameAttribute.cs" /> <Compile Include="ActionNameAttribute.cs" />
<Compile Include="ActionResult.cs" />
<Compile Include="ActionResultFactory.cs" /> <Compile Include="ActionResultFactory.cs" />
<Compile Include="ActionResultHelper.cs" /> <Compile Include="ActionResultHelper.cs" />
<Compile Include="ActionResults\ContentResult.cs" /> <Compile Include="ActionResults\ContentResult.cs" />
<Compile Include="ActionResults\EmptyResult.cs" /> <Compile Include="ActionResults\EmptyResult.cs" />
<Compile Include="ActionResults\HttpStatusCodeResult.cs" /> <Compile Include="ActionResults\HttpStatusCodeResult.cs" />
<Compile Include="ActionResults\IJsonResult.cs" />
<Compile Include="ActionResults\JsonResult.cs" /> <Compile Include="ActionResults\JsonResult.cs" />
<Compile Include="ActionResults\NoContentResult.cs" /> <Compile Include="ActionResults\NoContentResult.cs" />
<Compile Include="ActionResults\RedirectResult.cs" /> <Compile Include="ActionResults\RedirectResult.cs" />