// 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.IO; using System.Linq.Expressions; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNet.Http; using Microsoft.AspNet.Mvc.Filters; using Microsoft.AspNet.Mvc.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Routing; using Microsoft.Framework.DependencyInjection; using Microsoft.Framework.Internal; using Microsoft.Net.Http.Headers; using Newtonsoft.Json; namespace Microsoft.AspNet.Mvc { /// /// Base class for an MVC controller. /// public abstract class Controller : IActionFilter, IAsyncActionFilter, IDisposable { private ActionContext _actionContext; private IModelMetadataProvider _metadataProvider; private IObjectModelValidator _objectValidator; private ITempDataDictionary _tempData; private IUrlHelper _url; private DynamicViewData _viewBag; private ViewDataDictionary _viewData; /// /// Gets the request-specific . /// public IServiceProvider Resolver { get { return ActionContext?.HttpContext?.RequestServices; } } /// /// Gets the for the executing action. /// public HttpContext HttpContext { get { return ActionContext?.HttpContext; } } /// /// Gets the for the executing action. /// public HttpRequest Request { get { return ActionContext?.HttpContext?.Request; } } /// /// Gets the for the executing action. /// public HttpResponse Response { get { return ActionContext?.HttpContext?.Response; } } /// /// Gets the for the executing action. /// public RouteData RouteData { get { return ActionContext?.RouteData; } } /// /// Gets the that contains the state of the model and of model-binding validation. /// public ModelStateDictionary ModelState { get { return ViewData?.ModelState; } } /// /// Gets or sets the object. /// /// /// activates this property while activating controllers. /// If user code directly instantiates a controller, the getter returns an empty /// . /// [ActionContext] public ActionContext ActionContext { get { // This should run only for the controller unit test scenarios _actionContext = _actionContext ?? new ActionContext(); return _actionContext; } set { if (value == null) { throw new ArgumentNullException(nameof(value)); } _actionContext = value; } } /// /// Gets or sets the . /// [ActionBindingContext] public ActionBindingContext BindingContext { get; set; } /// /// Gets or sets the . /// public IModelMetadataProvider MetadataProvider { get { if (_metadataProvider == null) { _metadataProvider = Resolver?.GetRequiredService(); } return _metadataProvider; } set { if (value == null) { throw new ArgumentNullException(nameof(value)); } _metadataProvider = value; } } /// /// Gets or sets the . /// public IUrlHelper Url { get { if (_url == null) { _url = Resolver?.GetRequiredService(); } return _url; } set { if (value == null) { throw new ArgumentNullException(nameof(value)); } _url = value; } } /// /// Gets or sets the . /// public IObjectModelValidator ObjectValidator { get { if (_objectValidator == null) { _objectValidator = Resolver?.GetRequiredService(); } return _objectValidator; } set { if (value == null) { throw new ArgumentNullException(nameof(value)); } _objectValidator = value; } } /// /// Gets or sets the for user associated with the executing action. /// public ClaimsPrincipal User { get { return HttpContext?.User; } } /// /// 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(), ActionContext?.ModelState ?? new ModelStateDictionary()); } 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) { _tempData = Resolver?.GetRequiredService(); } 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: 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, 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: 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, 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 arguments to pass to the view component. /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(string componentName, params 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 . /// The arguments to pass to the view component. /// The created object for the response. [NonAction] public virtual ViewComponentResult ViewComponent(Type componentType, params object[] arguments) { return new ViewComponentResult() { ViewComponentType = componentType, Arguments = arguments, ViewData = ViewData, TempData = TempData }; } /// /// 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, (MediaTypeHeaderValue)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) { return Content(content, new MediaTypeHeaderValue(contentType) { Encoding = contentEncoding }); } /// /// Creates a object by specifying a /// string and a . /// /// 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, MediaTypeHeaderValue contentType) { var result = new ContentResult { Content = content, ContentType = contentType }; 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) { var disposableValue = data as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } 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)); } var disposableValue = data as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new JsonResult(data, serializerSettings); } /// /// Creates a object that produces an empty OK (200) response. /// /// The created for the response. [NonAction] public virtual HttpOkResult Ok() { return new HttpOkResult(); } /// /// Creates an object that produces an OK (200) response. /// /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual HttpOkObjectResult Ok(object value) { var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new HttpOkObjectResult(value); } /// /// 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, nameof(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, nameof(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(actionName, controllerName, PropertyHelper.ObjectToDictionary(routeValues)) { UrlHelper = Url, }; } /// /// 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( actionName, controllerName, PropertyHelper.ObjectToDictionary(routeValues), permanent: true) { UrlHelper = Url, }; } /// /// 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(routeName, routeValues) { UrlHelper = Url, }; } /// /// 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(routeName, routeValues, permanent: true) { UrlHelper = Url, }; } /// /// 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) { if (fileStream != null) { Response.RegisterForDispose(fileStream); } return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; } /// /// Returns the file specified by with the /// specified as the Content-Type. /// /// The virtual path of the file to be returned. /// The Content-Type of the file. /// The created for the response. [NonAction] public virtual VirtualFileResult File(string virtualPath, string contentType) { return File(virtualPath, contentType, fileDownloadName: null); } /// /// Returns the file specified by with the /// specified as the Content-Type and the /// specified as the suggested file name. /// /// The virtual path of the file to be returned. /// The Content-Type of the file. /// The suggested file name. /// The created for the response. [NonAction] public virtual VirtualFileResult File(string virtualPath, string contentType, string fileDownloadName) { return new VirtualFileResult(virtualPath, contentType) { FileDownloadName = fileDownloadName }; } /// /// Returns the file specified by with the /// specified as the Content-Type. /// /// The physical path of the file to be returned. /// The Content-Type of the file. /// The created for the response. [NonAction] public virtual PhysicalFileResult PhysicalFile(string physicalPath, string contentType) { return PhysicalFile(physicalPath, contentType, fileDownloadName: null); } /// /// Returns the file specified by with the /// specified as the Content-Type and the /// specified as the suggested file name. /// /// The physical path of the file to be returned. /// The Content-Type of the file. /// The suggested file name. /// The created for the response. [NonAction] public virtual PhysicalFileResult PhysicalFile( string physicalPath, string contentType, string fileDownloadName) { return new PhysicalFileResult(physicalPath, contentType) { FileDownloadName = fileDownloadName }; } /// /// Creates an that produces an Unauthorized (401) response. /// /// The created for the response. [NonAction] public virtual HttpUnauthorizedResult HttpUnauthorized() { return new HttpUnauthorizedResult(); } /// /// Creates an that produces a Not Found (404) response. /// /// The created for the response. [NonAction] public virtual HttpNotFoundResult HttpNotFound() { return new HttpNotFoundResult(); } /// /// Creates an that produces a Not Found (404) response. /// /// The created for the response. [NonAction] public virtual HttpNotFoundObjectResult HttpNotFound(object value) { var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new HttpNotFoundObjectResult(value); } /// /// Creates an that produces a Bad Request (400) response. /// /// The created for the response. [NonAction] public virtual BadRequestResult HttpBadRequest() { return new BadRequestResult(); } /// /// Creates an that produces a Bad Request (400) response. /// /// The created for the response. [NonAction] public virtual BadRequestObjectResult HttpBadRequest(object error) { var disposableValue = error as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new BadRequestObjectResult(error); } /// /// Creates an that produces a Bad Request (400) response. /// /// The created for the response. [NonAction] public virtual BadRequestObjectResult HttpBadRequest(ModelStateDictionary modelState) { if (modelState == null) { throw new ArgumentNullException(nameof(modelState)); } return new BadRequestObjectResult(modelState); } /// /// Creates a object that produces a Created (201) response. /// /// The URI at which the content has been created. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedResult Created(string uri, object value) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new CreatedResult(uri, value); } /// /// Creates a object that produces a Created (201) response. /// /// The URI at which the content has been created. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedResult Created(Uri uri, object value) { if (uri == null) { throw new ArgumentNullException(nameof(uri)); } var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new CreatedResult(uri, value); } /// /// Creates a object that produces a Created (201) response. /// /// The name of the action to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtActionResult CreatedAtAction(string actionName, object value) { return CreatedAtAction(actionName, routeValues: null, value: value); } /// /// Creates a object that produces a Created (201) response. /// /// The name of the action to use for generating the URL. /// The route data to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtActionResult CreatedAtAction(string actionName, object routeValues, object value) { return CreatedAtAction(actionName, controllerName: null, routeValues: routeValues, value: value); } /// /// Creates a object that produces a Created (201) response. /// /// The name of the action to use for generating the URL. /// The name of the controller to use for generating the URL. /// The route data to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtActionResult CreatedAtAction( string actionName, string controllerName, object routeValues, object value) { var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new CreatedAtActionResult(actionName, controllerName, routeValues, value); } /// /// Creates a object that produces a Created (201) response. /// /// The name of the route to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object value) { return CreatedAtRoute(routeName, routeValues: null, value: value); } /// /// Creates a object that produces a Created (201) response. /// /// The route data to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtRouteResult CreatedAtRoute(object routeValues, object value) { return CreatedAtRoute(routeName: null, routeValues: routeValues, value: value); } /// /// Creates a object that produces a Created (201) response. /// /// The name of the route to use for generating the URL. /// The route data to use for generating the URL. /// The content value to format in the entity body. /// The created for the response. [NonAction] public virtual CreatedAtRouteResult CreatedAtRoute(string routeName, object routeValues, object value) { var disposableValue = value as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new CreatedAtRouteResult(routeName, routeValues, value); } /// /// 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()); } } /// /// Updates the specified instance using values from the controller's current /// . /// /// The type of the model object. /// The model instance to update. /// A that on completion returns true if the update is successful. [NonAction] public virtual Task TryUpdateModelAsync( TModel model) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } return TryUpdateModelAsync(model, prefix: string.Empty); } /// /// Updates the specified instance using values from the controller's current /// and a . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the current . /// /// A that on completion returns true if the update is successful. [NonAction] public virtual Task TryUpdateModelAsync( TModel model, string prefix) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (prefix == null) { throw new ArgumentNullException(nameof(prefix)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return TryUpdateModelAsync(model, prefix, BindingContext.ValueProvider); } /// /// Updates the specified instance using the and a /// . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the . /// /// The used for looking up values. /// A that on completion returns true if the update is successful. [NonAction] public virtual Task TryUpdateModelAsync( TModel model, string prefix, IValueProvider valueProvider) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (prefix == null) { throw new ArgumentNullException(nameof(prefix)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, valueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider); } /// /// Updates the specified instance using values from the controller's current /// and a . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the current . /// /// (s) which represent top-level properties /// which need to be included for the current model. /// A that on completion returns true if the update is successful. [NonAction] public Task TryUpdateModelAsync( TModel model, string prefix, params Expression>[] includeExpressions) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (includeExpressions == null) { throw new ArgumentNullException(nameof(includeExpressions)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, BindingContext.ValueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider, includeExpressions); } /// /// Updates the specified instance using values from the controller's current /// and a . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the current . /// /// A predicate which can be used to filter properties at runtime. /// A that on completion returns true if the update is successful. [NonAction] public Task TryUpdateModelAsync( TModel model, string prefix, Func predicate) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, BindingContext.ValueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider, predicate); } /// /// Updates the specified instance using the and a /// . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the . /// /// The used for looking up values. /// (s) which represent top-level properties /// which need to be included for the current model. /// A that on completion returns true if the update is successful. [NonAction] public Task TryUpdateModelAsync( TModel model, string prefix, IValueProvider valueProvider, params Expression>[] includeExpressions) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (includeExpressions == null) { throw new ArgumentNullException(nameof(includeExpressions)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, valueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider, includeExpressions); } /// /// Updates the specified instance using the and a /// . /// /// The type of the model object. /// The model instance to update. /// The prefix to use when looking up values in the . /// /// The used for looking up values. /// A predicate which can be used to filter properties at runtime. /// A that on completion returns true if the update is successful. [NonAction] public Task TryUpdateModelAsync( TModel model, string prefix, IValueProvider valueProvider, Func predicate) where TModel : class { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, valueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider, predicate); } /// /// Updates the specified instance using values from the controller's current /// and a . /// /// The model instance to update. /// The type of model instance to update. /// The prefix to use when looking up values in the current . /// /// A that on completion returns true if the update is successful. [NonAction] public virtual Task TryUpdateModelAsync( object model, Type modelType, string prefix) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (modelType == null) { throw new ArgumentNullException(nameof(modelType)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, modelType, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, BindingContext.ValueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider); } /// /// Updates the specified instance using the and a /// . /// /// The model instance to update. /// The type of model instance to update. /// The prefix to use when looking up values in the . /// /// The used for looking up values. /// A predicate which can be used to filter properties at runtime. /// A that on completion returns true if the update is successful. [NonAction] public Task TryUpdateModelAsync( object model, Type modelType, string prefix, IValueProvider valueProvider, Func predicate) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (modelType == null) { throw new ArgumentNullException(nameof(modelType)); } if (valueProvider == null) { throw new ArgumentNullException(nameof(valueProvider)); } if (predicate == null) { throw new ArgumentNullException(nameof(predicate)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return ModelBindingHelper.TryUpdateModelAsync( model, modelType, prefix, ActionContext.HttpContext, ModelState, MetadataProvider, BindingContext.ModelBinder, valueProvider, BindingContext.InputFormatters, ObjectValidator, BindingContext.ValidatorProvider, predicate); } /// /// Validates the specified instance. /// /// The model to validate. /// true if the is valid; false otherwise. [NonAction] public virtual bool TryValidateModel( object model) { if (model == null) { throw new ArgumentNullException(nameof(model)); } return TryValidateModel(model, prefix: null); } /// /// Validates the specified instance. /// /// The model to validate. /// The key to use when looking up information in . /// /// true if the is valid;false otherwise. [NonAction] public virtual bool TryValidateModel( object model, string prefix) { if (model == null) { throw new ArgumentNullException(nameof(model)); } if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } var modelExplorer = MetadataProvider.GetModelExplorerForType(model.GetType(), model); var modelName = prefix ?? string.Empty; // Clear ModelStateDictionary entries for the model so that it will be re-validated. ModelBindingHelper.ClearValidationStateForModel( model.GetType(), ModelState, MetadataProvider, modelName); ObjectValidator.Validate( BindingContext.ValidatorProvider, ModelState, validationState: null, prefix: prefix, model: model); return ModelState.IsValid; } /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } /// /// 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) { } } }