// Copyright (c) Microsoft Open Technologies, Inc. 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.IO; using System.Security.Principal; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.Core; using Microsoft.Framework.DependencyInjection; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Routing; namespace Microsoft.AspNet.Mvc { public class Controller : IActionFilter, IAsyncActionFilter, IOrderedFilter, IDisposable { private DynamicViewData _viewBag; private IViewEngine _viewEngine; public IServiceProvider Resolver { get { return ActionContext?.HttpContext?.RequestServices; } } public HttpContext Context { get { return ActionContext?.HttpContext; } } public HttpRequest Request { get { return ActionContext?.HttpContext?.Request; } } public HttpResponse Response { get { return ActionContext?.HttpContext?.Response; } } public RouteData RouteData { get { return ActionContext?.RouteData; } } public IViewEngine ViewEngine { get { if (_viewEngine == null) { _viewEngine = ActionContext?. HttpContext?. RequestServices.GetRequiredService(); } return _viewEngine; } set { _viewEngine = value; } } public ModelStateDictionary ModelState { get { return ViewData?.ModelState; } } [Activate] public ActionContext ActionContext { get; set; } [Activate] public IUrlHelper Url { get; set; } [Activate] public IActionBindingContextProvider BindingContextProvider { get; set; } public IPrincipal User { get { return Context?.User; } } [Activate] public ViewDataDictionary ViewData { get; set; } public dynamic ViewBag { get { if (_viewBag == null) { _viewBag = new DynamicViewData(() => ViewData); } return _viewBag; } } int IOrderedFilter.Order { get { // Controller-filter methods run closest the action by default. return int.MaxValue; } } /// /// Creates a object that renders a view to the response. /// /// The created object for the response. [NonAction] public virtual ViewResult View() { return View(viewName: null); } /// /// Creates a object by specifying a . /// /// The name of the view that is rendered to the response. /// The created object for the response. [NonAction] public virtual ViewResult View(string viewName) { return View(viewName, model: null); } /// /// Creates a object by specifying a /// to be rendered by the view. /// /// The model that is rendered by the view. /// The created object for the response. [NonAction] public virtual ViewResult View(object model) { return View(viewName: null, model: model); } /// /// Creates a object by specifying a /// and the to be rendered by the view. /// /// The name of the view that is rendered to the response. /// The model that is rendered by the view. /// The created object for the response. [NonAction] public virtual ViewResult View(string viewName, object model) { // Do not override ViewData.Model unless passed a non-null value. if (model != null) { ViewData.Model = model; } return new ViewResult() { ViewName = viewName, ViewData = ViewData, ViewEngine = _viewEngine, }; } /// /// Creates a object that renders a partial view to the response. /// /// The created object for the response. [NonAction] public virtual PartialViewResult PartialView() { return PartialView(viewName: null); } /// /// Creates a object by specifying a . /// /// The name of the view that is rendered to the response. /// The created object for the response. [NonAction] public virtual PartialViewResult PartialView(string viewName) { return PartialView(viewName, model: null); } /// /// Creates a object by specifying a /// to be rendered by the partial view. /// /// The model that is rendered by the partial view. /// The created object for the response. [NonAction] public virtual PartialViewResult PartialView(object model) { return PartialView(viewName: null, model: model); } /// /// Creates a object by specifying a /// and the to be rendered by the partial view. /// /// The name of the partial view that is rendered to the response. /// The model that is rendered by the partial view. /// The created object for the response. [NonAction] public virtual PartialViewResult PartialView(string viewName, object model) { // Do not override ViewData.Model unless passed a non-null value. if (model != null) { ViewData.Model = model; } return new PartialViewResult() { ViewName = viewName, ViewData = ViewData, }; } /// /// Creates a object by specifying a string. /// /// The content to write to the response. /// The created object for the response. [NonAction] public virtual ContentResult Content(string content) { return Content(content, contentType: null); } /// /// Creates a object by specifying a string /// and a content type. /// /// The content to write to the response. /// The content type (MIME type). /// The created object for the response. [NonAction] public virtual ContentResult Content(string content, string contentType) { return Content(content, contentType, contentEncoding: null); } /// /// Creates a object by specifying a string, /// a , and . /// /// The content to write to the response. /// The content type (MIME type). /// The content encoding. /// The created object for the response. [NonAction] public virtual ContentResult Content(string content, string contentType, Encoding contentEncoding) { var result = new ContentResult { Content = content, }; if (contentType != null) { result.ContentType = contentType; } if (contentEncoding != null) { result.ContentEncoding = contentEncoding; } return result; } /// /// Creates a object that serializes the specified object /// to JSON. /// /// The object to serialize. /// The created that serializes the specified /// to JSON format for the response. [NonAction] public virtual JsonResult Json(object data) { return new JsonResult(data); } /// /// Creates a object that redirects to the specified . /// /// The URL to redirect to. /// The created for the response. [NonAction] public virtual RedirectResult Redirect(string url) { if (string.IsNullOrEmpty(url)) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "url"); } return new RedirectResult(url); } /// /// Creates a object with set to true /// using the specified . /// /// The URL to redirect to. /// The created for the response. [NonAction] public virtual RedirectResult RedirectPermanent(string url) { if (string.IsNullOrEmpty(url)) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, "url"); } return new RedirectResult(url, permanent: true); } /// /// Redirects to the specified action using the . /// /// The name of the action. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToAction(string actionName) { return RedirectToAction(actionName, routeValues: null); } /// /// Redirects to the specified action using the /// and . /// /// The name of the action. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToAction(string actionName, object routeValues) { return RedirectToAction(actionName, controllerName: null, routeValues: routeValues); } /// /// Redirects to the specified action using the /// and the . /// /// The name of the action. /// The name of the controller. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToAction(string actionName, string controllerName) { return RedirectToAction(actionName, controllerName, routeValues: null); } /// /// Redirects to the specified action using the specified , /// , and . /// /// The name of the action. /// The name of the controller. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToAction(string actionName, string controllerName, object routeValues) { return new RedirectToActionResult(Url, actionName, controllerName, TypeHelper.ObjectToDictionary(routeValues)); } /// /// Redirects to the specified action with set to true /// using the specified . /// /// The name of the action. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToActionPermanent(string actionName) { return RedirectToActionPermanent(actionName, routeValues: null); } /// /// Redirects to the specified action with set to true /// using the specified and . /// /// The name of the action. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, object routeValues) { return RedirectToActionPermanent(actionName, controllerName: null, routeValues: routeValues); } /// /// Redirects to the specified action with set to true /// using the specified and . /// /// The name of the action. /// The name of the controller. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName) { return RedirectToActionPermanent(actionName, controllerName, routeValues: null); } /// /// Redirects to the specified action with set to true /// using the specified , , /// and . /// /// The name of the action. /// The name of the controller. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToActionResult RedirectToActionPermanent(string actionName, string controllerName, object routeValues) { return new RedirectToActionResult(Url, actionName, controllerName, TypeHelper.ObjectToDictionary(routeValues), permanent: true); } /// /// Redirects to the specified route using the specified . /// /// The name of the route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoute(string routeName) { return RedirectToRoute(routeName, routeValues: null); } /// /// Redirects to the specified route using the specified . /// /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoute(object routeValues) { return RedirectToRoute(routeName: null, routeValues: routeValues); } /// /// Redirects to the specified route using the specified /// and . /// /// The name of the route. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) { return new RedirectToRouteResult(Url, routeName, routeValues); } /// /// Redirects to the specified route with set to true /// using the specified . /// /// The name of the route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName) { return RedirectToRoutePermanent(routeName, routeValues: null); } /// /// Redirects to the specified route with set to true /// using the specified . /// /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoutePermanent(object routeValues) { return RedirectToRoutePermanent(routeName: null, routeValues: routeValues); } /// /// Redirects to the specified route with set to true /// using the specified and . /// /// The name of the route. /// The parameters for a route. /// The created for the response. [NonAction] public virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, object routeValues) { return new RedirectToRouteResult(Url, routeName, routeValues, permanent: true); } /// /// Returns a file with the specified as content and the /// specified as the Content-Type. /// /// The file contents. /// The Content-Type of the file. /// The created for the response. [NonAction] public virtual FileContentResult File(byte[] fileContents, string contentType) { return File(fileContents, contentType, fileDownloadName: null); } /// /// Returns a file with the specified as content, the /// specified as the Content-Type and the /// specified as the suggested file name. /// /// The file contents. /// The Content-Type of the file. /// The suggested file name. /// The created for the response. [NonAction] public virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName) { return new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName }; } /// /// Returns a file in the specified with the /// specified as the Content-Type. /// /// The with the contents of the file. /// The Content-Type of the file. /// The created for the response. [NonAction] public virtual FileStreamResult File(Stream fileStream, string contentType) { return File(fileStream, contentType, fileDownloadName: null); } /// /// Returns a file in the specified with the /// specified as the Content-Type and the /// specified as the suggested file name. /// /// The with the contents of the file. /// The Content-Type of the file. /// The suggested file name. /// The created for the response. [NonAction] public virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName) { return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; } /// /// Returns the file specified by with the /// specified as the Content-Type. /// /// The with the contents of the file. /// The Content-Type of the file. /// The created for the response. [NonAction] public virtual FilePathResult File(string fileName, string contentType) { return File(fileName, contentType, fileDownloadName: null); } /// /// Returns the file specified by with the /// specified as the Content-Type and the /// specified as the suggested file name. /// /// The with the contents of the file. /// The Content-Type of the file. /// The suggested file name. /// The created for the response. [NonAction] public virtual FilePathResult File(string fileName, string contentType, string fileDownloadName) { return new FilePathResult(fileName, contentType) { FileDownloadName = fileDownloadName }; } /// /// Creates an that produces a Not Found (404) response. /// /// The created for the response. [NonAction] public virtual HttpNotFoundResult HttpNotFound() { return new HttpNotFoundResult(); } /// /// Called before the action method is invoked. /// /// The action executing context. [NonAction] public virtual void OnActionExecuting([NotNull] ActionExecutingContext context) { } /// /// Called after the action method is invoked. /// /// The action executed context. [NonAction] public virtual void OnActionExecuted([NotNull] ActionExecutedContext context) { } /// /// Called before the action method is invoked. /// /// The action executing context. /// The to execute. Invoke this delegate in the body /// of to continue execution of the action. /// A instance. [NonAction] public virtual async Task OnActionExecutionAsync( [NotNull] ActionExecutingContext context, [NotNull] ActionExecutionDelegate next) { OnActionExecuting(context); if (context.Result == null) { OnActionExecuted(await next()); } } /// /// Updates the specified model instance using values from the controller's current value provider. /// /// The type of the model object. /// The model instance to update. /// true if the update is successful; otherwise, false. [NonAction] public virtual Task TryUpdateModelAsync([NotNull] TModel model) where TModel : class { return TryUpdateModelAsync(model, prefix: typeof(TModel).Name); } /// /// Updates the specified model instance using values from the controller's current value provider /// and a prefix. /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the value provider. /// true if the update is successful; otherwise, false. [NonAction] public virtual async Task TryUpdateModelAsync([NotNull] TModel model, [NotNull] string prefix) where TModel : class { if (BindingContextProvider == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull("BindingContextProvider", GetType().FullName); throw new InvalidOperationException(message); } var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext); return await TryUpdateModelAsync(model, prefix, bindingContext.ValueProvider); } /// /// Updates the specified model instance using the value provider and a prefix. /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the value provider. /// The value provider used for looking up values. /// true if the update is successful; otherwise, false. [NonAction] public virtual async Task TryUpdateModelAsync([NotNull] TModel model, [NotNull] string prefix, [NotNull] IValueProvider valueProvider) where TModel : class { if (BindingContextProvider == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull("BindingContextProvider", GetType().FullName); throw new InvalidOperationException(message); } var bindingContext = await BindingContextProvider.GetActionBindingContextAsync(ActionContext); return await ModelBindingHelper.TryUpdateModelAsync(model, prefix, ActionContext.HttpContext, ModelState, bindingContext.MetadataProvider, bindingContext.ModelBinder, valueProvider, bindingContext.ValidatorProvider); } [NonAction] public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } protected virtual void Dispose(bool disposing) { } } }