// 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.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Mvc.ModelBinding; using Microsoft.AspNetCore.Mvc.ViewFeatures; using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal; using Microsoft.Extensions.DependencyInjection; using Newtonsoft.Json; namespace Microsoft.AspNetCore.Mvc { /// /// A base class for an MVC controller with view support. /// public abstract class Controller : ControllerBase, IActionFilter, IAsyncActionFilter, IDisposable { private ITempDataDictionary _tempData; private DynamicViewData _viewBag; private ViewDataDictionary _viewData; /// /// Gets or sets used by and . /// /// /// By default, this property is activated when activates /// controllers. However, when controllers are directly instantiated in user code, this property is /// initialized with . /// [ViewDataDictionary] public ViewDataDictionary ViewData { get { if (_viewData == null) { // This should run only for the controller unit test scenarios _viewData = new ViewDataDictionary(new EmptyModelMetadataProvider(), ControllerContext.ModelState); } return _viewData; } set { if (value == null) { throw new ArgumentException(Resources.ArgumentCannotBeNullOrEmpty, nameof(ViewData)); } _viewData = value; } } /// /// Gets or sets used by . /// public ITempDataDictionary TempData { get { if (_tempData == null) { var factory = HttpContext?.RequestServices?.GetRequiredService(); _tempData = factory?.GetTempData(HttpContext); } return _tempData; } set { if (value == null) { throw new ArgumentNullException(nameof(value)); } _tempData = value; } } /// /// Gets the dynamic view bag. /// public dynamic ViewBag { get { if (_viewBag == null) { _viewBag = new DynamicViewData(() => ViewData); } return _viewBag; } } /// /// 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: ViewData.Model); } /// /// 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) { ViewData.Model = model; return new ViewResult() { ViewName = viewName, ViewData = ViewData, TempData = TempData }; } /// /// 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: ViewData.Model); } /// /// 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) { ViewData.Model = model; return new PartialViewResult() { ViewName = viewName, ViewData = ViewData, TempData = TempData }; } /// /// Creates a by specifying the name of a view component to render. /// /// /// The view component name. Can be a view component /// or /// . /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(string componentName) { return ViewComponent(componentName, arguments: null); } /// /// Creates a by specifying the of a view component to /// render. /// /// The view component . /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(Type componentType) { return ViewComponent(componentType, arguments: null); } /// /// Creates a by specifying the name of a view component to render. /// /// /// The view component name. Can be a view component /// or /// . /// /// An with properties representing arguments to be passed to the invoked view component /// method. Alternatively, an instance /// containing the invocation arguments. /// /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(string componentName, object arguments) { return new ViewComponentResult { ViewComponentName = componentName, Arguments = arguments, ViewData = ViewData, TempData = TempData }; } /// /// Creates a by specifying the of a view component to /// render. /// /// The view component . /// /// An with properties representing arguments to be passed to the invoked view component /// method. Alternatively, an instance /// containing the invocation arguments. /// /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(Type componentType, object arguments) { return new ViewComponentResult { ViewComponentType = componentType, Arguments = arguments, ViewData = ViewData, TempData = TempData }; } /// /// 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 serializes the specified object /// to JSON. /// /// The object to serialize. /// The to be used by /// the formatter. /// The created that serializes the specified /// as JSON format for the response. /// Callers should cache an instance of to avoid /// recreating cached data with each call. [NonAction] public virtual JsonResult Json(object data, JsonSerializerSettings serializerSettings) { if (serializerSettings == null) { throw new ArgumentNullException(nameof(serializerSettings)); } return new JsonResult(data, serializerSettings); } /// /// Called before the action method is invoked. /// /// The action executing context. [NonAction] public virtual void OnActionExecuting(ActionExecutingContext context) { } /// /// Called after the action method is invoked. /// /// The action executed context. [NonAction] public virtual void OnActionExecuted(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( ActionExecutingContext context, ActionExecutionDelegate next) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (next == null) { throw new ArgumentNullException(nameof(next)); } OnActionExecuting(context); if (context.Result == null) { OnActionExecuted(await next()); } } /// public void Dispose() => Dispose(disposing: true); /// /// Releases all resources currently used by this instance. /// /// true if this method is being invoked by the method, /// otherwise false. protected virtual void Dispose(bool disposing) { } } }