// 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.ModelBinding; using Microsoft.AspNet.Mvc.ModelBinding.Validation; using Microsoft.AspNet.Mvc.Rendering; using Microsoft.AspNet.Mvc.ViewFeatures; using Microsoft.AspNet.Routing; 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 DynamicViewData _viewBag; private ViewDataDictionary _viewData; private ActionContext _actionContext; /// /// Gets the request-specific . /// public IServiceProvider Resolver { get { return ActionContext?.HttpContext?.RequestServices; } } /// /// Gets the for the executing action. /// public HttpContext Context { 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 codes /// directly instantiate controllers, 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 . /// [FromServices] public IModelMetadataProvider MetadataProvider { get; set; } /// /// Gets or sets the . /// [FromServices] public IUrlHelper Url { get; set; } [FromServices] public IObjectModelValidator ObjectValidator { get; set; } /// /// Gets or sets the for user associated with the executing action. /// public ClaimsPrincipal User { get { return Context?.User; } } /// /// Gets or sets used by and . /// /// /// By default, this property is activated when activates controllers. /// However, when controllers are directly instantiated in user codes, 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 . /// [FromServices] public ITempDataDictionary TempData { get; set; } /// /// 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 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, [NotNull] JsonSerializerSettings serializerSettings) { var disposableValue = data as IDisposable; if (disposableValue != null) { Response.RegisterForDispose(disposableValue); } return new JsonResult(data, serializerSettings); } /// /// 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 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 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([NotNull] ModelStateDictionary 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([NotNull] string uri, object value) { 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([NotNull] Uri uri, object value) { string location; if (uri.IsAbsoluteUri) { location = uri.AbsoluteUri; } else { location = uri.GetComponents(UriComponents.SerializationInfoString, UriFormat.UriEscaped); } return Created(location, 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([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 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([NotNull] TModel model) where TModel : class { 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 async Task TryUpdateModelAsync([NotNull] TModel model, [NotNull] string prefix) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync([NotNull] TModel model, [NotNull] string prefix, [NotNull] IValueProvider valueProvider) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync( [NotNull] TModel model, string prefix, [NotNull] params Expression>[] includeExpressions) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync( [NotNull] TModel model, string prefix, [NotNull] Func predicate) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync( [NotNull] TModel model, string prefix, [NotNull] IValueProvider valueProvider, [NotNull] params Expression>[] includeExpressions) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync( [NotNull] TModel model, string prefix, [NotNull] IValueProvider valueProvider, [NotNull] Func predicate) where TModel : class { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync([NotNull] object model, [NotNull] Type modelType, string prefix) { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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 async Task TryUpdateModelAsync( [NotNull] object model, [NotNull] Type modelType, string prefix, [NotNull] IValueProvider valueProvider, [NotNull] Func predicate) { if (BindingContext == null) { var message = Resources.FormatPropertyOfTypeCannotBeNull( nameof(BindingContext), typeof(Controller).FullName); throw new InvalidOperationException(message); } return await 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([NotNull] object 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([NotNull] object model, string prefix) { 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); var validationContext = new ModelValidationContext( bindingSource: null, validatorProvider: BindingContext.ValidatorProvider, modelState: ModelState, modelExplorer: modelExplorer); ObjectValidator.Validate( validationContext, new ModelValidationNode(modelName, modelExplorer.Metadata, model) { ValidateAllProperties = true }); 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) { } } }