1 // Copyright (c) Microsoft Corporation. All rights reserved. See License.txt in the project root for license information. 2 3 using System.Diagnostics.CodeAnalysis; 4 using System.Globalization; 5 using System.IO; 6 using System.Security.Principal; 7 using System.Text; 8 using System.Web.Mvc.Async; 9 using System.Web.Mvc.Properties; 10 using System.Web.Profile; 11 using System.Web.Routing; 12 13 namespace System.Web.Mvc 14 { 15 [SuppressMessage("Microsoft.Maintainability", "CA1506:AvoidExcessiveClassCoupling", Justification = "Class complexity dictated by public surface area")] 16 public abstract class Controller : ControllerBase, IActionFilter, IAuthorizationFilter, IDisposable, IExceptionFilter, IResultFilter, IAsyncController, IAsyncManagerContainer 17 { 18 private static readonly object _executeTag = new object(); 19 private static readonly object _executeCoreTag = new object(); 20 21 private readonly AsyncManager _asyncManager = new AsyncManager(); 22 private IActionInvoker _actionInvoker; 23 private ModelBinderDictionary _binders; 24 private RouteCollection _routeCollection; 25 private ITempDataProvider _tempDataProvider; 26 private ViewEngineCollection _viewEngineCollection; 27 28 private IDependencyResolver _resolver; 29 30 // By default, use the global resolver with caching. 31 // Or we can override to supply this instance with its own cache. 32 internal IDependencyResolver Resolver 33 { 34 get { return _resolver ?? DependencyResolver.CurrentCache; } 35 set { _resolver = value; } 36 } 37 38 public AsyncManager AsyncManager 39 { 40 get { return _asyncManager; } 41 } 42 43 /// <summary> 44 /// This is for backwards compat. MVC 4.0 starts allowing Controller to support asynchronous patterns. 45 /// This means ExecuteCore doesn't get called on derived classes. Derived classes can override this 46 /// flag and set to true if they still need ExecuteCore to be called. 47 /// </summary> 48 protected virtual bool DisableAsyncSupport 49 { 50 get { return false; } 51 } 52 53 public IActionInvoker ActionInvoker 54 { 55 get 56 { 57 if (_actionInvoker == null) 58 { 59 _actionInvoker = CreateActionInvoker(); 60 } 61 return _actionInvoker; 62 } 63 set { _actionInvoker = value; } 64 } 65 66 [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "Property is settable so that the dictionary can be provided for unit testing purposes.")] 67 protected internal ModelBinderDictionary Binders 68 { 69 get 70 { 71 if (_binders == null) 72 { 73 _binders = ModelBinders.Binders; 74 } 75 return _binders; 76 } 77 set { _binders = value; } 78 } 79 80 public HttpContextBase HttpContext 81 { 82 get { return ControllerContext == null ? null : ControllerContext.HttpContext; } 83 } 84 85 public ModelStateDictionary ModelState 86 { 87 get { return ViewData.ModelState; } 88 } 89 90 public ProfileBase Profile 91 { 92 get { return HttpContext == null ? null : HttpContext.Profile; } 93 } 94 95 public HttpRequestBase Request 96 { 97 get { return HttpContext == null ? null : HttpContext.Request; } 98 } 99 100 public HttpResponseBase Response 101 { 102 get { return HttpContext == null ? null : HttpContext.Response; } 103 } 104 105 internal RouteCollection RouteCollection 106 { 107 get 108 { 109 if (_routeCollection == null) 110 { 111 _routeCollection = RouteTable.Routes; 112 } 113 return _routeCollection; 114 } 115 set { _routeCollection = value; } 116 } 117 118 public RouteData RouteData 119 { 120 get { return ControllerContext == null ? null : ControllerContext.RouteData; } 121 } 122 123 public HttpServerUtilityBase Server 124 { 125 get { return HttpContext == null ? null : HttpContext.Server; } 126 } 127 128 public HttpSessionStateBase Session 129 { 130 get { return HttpContext == null ? null : HttpContext.Session; } 131 } 132 133 public ITempDataProvider TempDataProvider 134 { 135 get 136 { 137 if (_tempDataProvider == null) 138 { 139 _tempDataProvider = CreateTempDataProvider(); 140 } 141 return _tempDataProvider; 142 } 143 set { _tempDataProvider = value; } 144 } 145 146 public UrlHelper Url { get; set; } 147 148 public IPrincipal User 149 { 150 get { return HttpContext == null ? null : HttpContext.User; } 151 } 152 153 [SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly", Justification = "This entire type is meant to be mutable.")] 154 public ViewEngineCollection ViewEngineCollection 155 { 156 get { return _viewEngineCollection ?? ViewEngines.Engines; } 157 set { _viewEngineCollection = value; } 158 } 159 160 [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Justification = "'Content' refers to ContentResult type; 'content' refers to ContentResult.Content property.")] Content(string content)161 protected internal ContentResult Content(string content) 162 { 163 return Content(content, null /* contentType */); 164 } 165 166 [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Justification = "'Content' refers to ContentResult type; 'content' refers to ContentResult.Content property.")] Content(string content, string contentType)167 protected internal ContentResult Content(string content, string contentType) 168 { 169 return Content(content, contentType, null /* contentEncoding */); 170 } 171 172 [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Justification = "'Content' refers to ContentResult type; 'content' refers to ContentResult.Content property.")] Content(string content, string contentType, Encoding contentEncoding)173 protected internal virtual ContentResult Content(string content, string contentType, Encoding contentEncoding) 174 { 175 return new ContentResult 176 { 177 Content = content, 178 ContentType = contentType, 179 ContentEncoding = contentEncoding 180 }; 181 } 182 CreateActionInvoker()183 protected virtual IActionInvoker CreateActionInvoker() 184 { 185 // Controller supports asynchronous operations by default. 186 return Resolver.GetService<IAsyncActionInvoker>() ?? Resolver.GetService<IActionInvoker>() ?? new AsyncControllerActionInvoker(); 187 } 188 CreateTempDataProvider()189 protected virtual ITempDataProvider CreateTempDataProvider() 190 { 191 return Resolver.GetService<ITempDataProvider>() ?? new SessionStateTempDataProvider(); 192 } 193 194 // The default invoker will never match methods defined on the Controller type, so 195 // the Dispose() method is not web-callable. However, in general, since implicitly- 196 // implemented interface methods are public, they are web-callable unless decorated with 197 // [NonAction]. Dispose()198 public void Dispose() 199 { 200 Dispose(true /* disposing */); 201 GC.SuppressFinalize(this); 202 } 203 Dispose(bool disposing)204 protected virtual void Dispose(bool disposing) 205 { 206 } 207 ExecuteCore()208 protected override void ExecuteCore() 209 { 210 // If code in this method needs to be updated, please also check the BeginExecuteCore() and 211 // EndExecuteCore() methods of AsyncController to see if that code also must be updated. 212 213 PossiblyLoadTempData(); 214 try 215 { 216 string actionName = RouteData.GetRequiredString("action"); 217 if (!ActionInvoker.InvokeAction(ControllerContext, actionName)) 218 { 219 HandleUnknownAction(actionName); 220 } 221 } 222 finally 223 { 224 PossiblySaveTempData(); 225 } 226 } 227 File(byte[] fileContents, string contentType)228 protected internal FileContentResult File(byte[] fileContents, string contentType) 229 { 230 return File(fileContents, contentType, null /* fileDownloadName */); 231 } 232 File(byte[] fileContents, string contentType, string fileDownloadName)233 protected internal virtual FileContentResult File(byte[] fileContents, string contentType, string fileDownloadName) 234 { 235 return new FileContentResult(fileContents, contentType) { FileDownloadName = fileDownloadName }; 236 } 237 File(Stream fileStream, string contentType)238 protected internal FileStreamResult File(Stream fileStream, string contentType) 239 { 240 return File(fileStream, contentType, null /* fileDownloadName */); 241 } 242 File(Stream fileStream, string contentType, string fileDownloadName)243 protected internal virtual FileStreamResult File(Stream fileStream, string contentType, string fileDownloadName) 244 { 245 return new FileStreamResult(fileStream, contentType) { FileDownloadName = fileDownloadName }; 246 } 247 File(string fileName, string contentType)248 protected internal FilePathResult File(string fileName, string contentType) 249 { 250 return File(fileName, contentType, null /* fileDownloadName */); 251 } 252 File(string fileName, string contentType, string fileDownloadName)253 protected internal virtual FilePathResult File(string fileName, string contentType, string fileDownloadName) 254 { 255 return new FilePathResult(fileName, contentType) { FileDownloadName = fileDownloadName }; 256 } 257 HandleUnknownAction(string actionName)258 protected virtual void HandleUnknownAction(string actionName) 259 { 260 throw new HttpException(404, String.Format(CultureInfo.CurrentCulture, 261 MvcResources.Controller_UnknownAction, actionName, GetType().FullName)); 262 } 263 HttpNotFound()264 protected internal HttpNotFoundResult HttpNotFound() 265 { 266 return HttpNotFound(null); 267 } 268 HttpNotFound(string statusDescription)269 protected internal virtual HttpNotFoundResult HttpNotFound(string statusDescription) 270 { 271 return new HttpNotFoundResult(statusDescription); 272 } 273 JavaScript(string script)274 protected internal virtual JavaScriptResult JavaScript(string script) 275 { 276 return new JavaScriptResult { Script = script }; 277 } 278 Json(object data)279 protected internal JsonResult Json(object data) 280 { 281 return Json(data, null /* contentType */, null /* contentEncoding */, JsonRequestBehavior.DenyGet); 282 } 283 Json(object data, string contentType)284 protected internal JsonResult Json(object data, string contentType) 285 { 286 return Json(data, contentType, null /* contentEncoding */, JsonRequestBehavior.DenyGet); 287 } 288 Json(object data, string contentType, Encoding contentEncoding)289 protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding) 290 { 291 return Json(data, contentType, contentEncoding, JsonRequestBehavior.DenyGet); 292 } 293 Json(object data, JsonRequestBehavior behavior)294 protected internal JsonResult Json(object data, JsonRequestBehavior behavior) 295 { 296 return Json(data, null /* contentType */, null /* contentEncoding */, behavior); 297 } 298 Json(object data, string contentType, JsonRequestBehavior behavior)299 protected internal JsonResult Json(object data, string contentType, JsonRequestBehavior behavior) 300 { 301 return Json(data, contentType, null /* contentEncoding */, behavior); 302 } 303 Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior)304 protected internal virtual JsonResult Json(object data, string contentType, Encoding contentEncoding, JsonRequestBehavior behavior) 305 { 306 return new JsonResult 307 { 308 Data = data, 309 ContentType = contentType, 310 ContentEncoding = contentEncoding, 311 JsonRequestBehavior = behavior 312 }; 313 } 314 Initialize(RequestContext requestContext)315 protected override void Initialize(RequestContext requestContext) 316 { 317 base.Initialize(requestContext); 318 Url = new UrlHelper(requestContext); 319 } 320 OnActionExecuting(ActionExecutingContext filterContext)321 protected virtual void OnActionExecuting(ActionExecutingContext filterContext) 322 { 323 } 324 OnActionExecuted(ActionExecutedContext filterContext)325 protected virtual void OnActionExecuted(ActionExecutedContext filterContext) 326 { 327 } 328 OnAuthorization(AuthorizationContext filterContext)329 protected virtual void OnAuthorization(AuthorizationContext filterContext) 330 { 331 } 332 OnException(ExceptionContext filterContext)333 protected virtual void OnException(ExceptionContext filterContext) 334 { 335 } 336 OnResultExecuted(ResultExecutedContext filterContext)337 protected virtual void OnResultExecuted(ResultExecutedContext filterContext) 338 { 339 } 340 OnResultExecuting(ResultExecutingContext filterContext)341 protected virtual void OnResultExecuting(ResultExecutingContext filterContext) 342 { 343 } 344 PartialView()345 protected internal PartialViewResult PartialView() 346 { 347 return PartialView(null /* viewName */, null /* model */); 348 } 349 PartialView(object model)350 protected internal PartialViewResult PartialView(object model) 351 { 352 return PartialView(null /* viewName */, model); 353 } 354 PartialView(string viewName)355 protected internal PartialViewResult PartialView(string viewName) 356 { 357 return PartialView(viewName, null /* model */); 358 } 359 PartialView(string viewName, object model)360 protected internal virtual PartialViewResult PartialView(string viewName, object model) 361 { 362 if (model != null) 363 { 364 ViewData.Model = model; 365 } 366 367 return new PartialViewResult 368 { 369 ViewName = viewName, 370 ViewData = ViewData, 371 TempData = TempData, 372 ViewEngineCollection = ViewEngineCollection 373 }; 374 } 375 PossiblyLoadTempData()376 internal void PossiblyLoadTempData() 377 { 378 if (!ControllerContext.IsChildAction) 379 { 380 TempData.Load(ControllerContext, TempDataProvider); 381 } 382 } 383 PossiblySaveTempData()384 internal void PossiblySaveTempData() 385 { 386 if (!ControllerContext.IsChildAction) 387 { 388 TempData.Save(ControllerContext, TempDataProvider); 389 } 390 } 391 392 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Response.Redirect() takes its URI as a string parameter.")] Redirect(string url)393 protected internal virtual RedirectResult Redirect(string url) 394 { 395 if (String.IsNullOrEmpty(url)) 396 { 397 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "url"); 398 } 399 400 return new RedirectResult(url); 401 } 402 403 [SuppressMessage("Microsoft.Design", "CA1054:UriParametersShouldNotBeStrings", MessageId = "0#", Justification = "Response.RedirectPermanent() takes its URI as a string parameter.")] RedirectPermanent(string url)404 protected internal virtual RedirectResult RedirectPermanent(string url) 405 { 406 if (String.IsNullOrEmpty(url)) 407 { 408 throw new ArgumentException(MvcResources.Common_NullOrEmpty, "url"); 409 } 410 411 return new RedirectResult(url, permanent: true); 412 } 413 RedirectToAction(string actionName)414 protected internal RedirectToRouteResult RedirectToAction(string actionName) 415 { 416 return RedirectToAction(actionName, (RouteValueDictionary)null); 417 } 418 RedirectToAction(string actionName, object routeValues)419 protected internal RedirectToRouteResult RedirectToAction(string actionName, object routeValues) 420 { 421 return RedirectToAction(actionName, new RouteValueDictionary(routeValues)); 422 } 423 RedirectToAction(string actionName, RouteValueDictionary routeValues)424 protected internal RedirectToRouteResult RedirectToAction(string actionName, RouteValueDictionary routeValues) 425 { 426 return RedirectToAction(actionName, null /* controllerName */, routeValues); 427 } 428 RedirectToAction(string actionName, string controllerName)429 protected internal RedirectToRouteResult RedirectToAction(string actionName, string controllerName) 430 { 431 return RedirectToAction(actionName, controllerName, (RouteValueDictionary)null); 432 } 433 RedirectToAction(string actionName, string controllerName, object routeValues)434 protected internal RedirectToRouteResult RedirectToAction(string actionName, string controllerName, object routeValues) 435 { 436 return RedirectToAction(actionName, controllerName, new RouteValueDictionary(routeValues)); 437 } 438 RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues)439 protected internal virtual RedirectToRouteResult RedirectToAction(string actionName, string controllerName, RouteValueDictionary routeValues) 440 { 441 RouteValueDictionary mergedRouteValues; 442 443 if (RouteData == null) 444 { 445 mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, null, routeValues, includeImplicitMvcValues: true); 446 } 447 else 448 { 449 mergedRouteValues = RouteValuesHelpers.MergeRouteValues(actionName, controllerName, RouteData.Values, routeValues, includeImplicitMvcValues: true); 450 } 451 452 return new RedirectToRouteResult(mergedRouteValues); 453 } 454 RedirectToActionPermanent(string actionName)455 protected internal RedirectToRouteResult RedirectToActionPermanent(string actionName) 456 { 457 return RedirectToActionPermanent(actionName, (RouteValueDictionary)null); 458 } 459 RedirectToActionPermanent(string actionName, object routeValues)460 protected internal RedirectToRouteResult RedirectToActionPermanent(string actionName, object routeValues) 461 { 462 return RedirectToActionPermanent(actionName, new RouteValueDictionary(routeValues)); 463 } 464 RedirectToActionPermanent(string actionName, RouteValueDictionary routeValues)465 protected internal RedirectToRouteResult RedirectToActionPermanent(string actionName, RouteValueDictionary routeValues) 466 { 467 return RedirectToActionPermanent(actionName, null /* controllerName */, routeValues); 468 } 469 RedirectToActionPermanent(string actionName, string controllerName)470 protected internal RedirectToRouteResult RedirectToActionPermanent(string actionName, string controllerName) 471 { 472 return RedirectToActionPermanent(actionName, controllerName, (RouteValueDictionary)null); 473 } 474 RedirectToActionPermanent(string actionName, string controllerName, object routeValues)475 protected internal RedirectToRouteResult RedirectToActionPermanent(string actionName, string controllerName, object routeValues) 476 { 477 return RedirectToActionPermanent(actionName, controllerName, new RouteValueDictionary(routeValues)); 478 } 479 RedirectToActionPermanent(string actionName, string controllerName, RouteValueDictionary routeValues)480 protected internal virtual RedirectToRouteResult RedirectToActionPermanent(string actionName, string controllerName, RouteValueDictionary routeValues) 481 { 482 RouteValueDictionary implicitRouteValues = (RouteData != null) ? RouteData.Values : null; 483 484 RouteValueDictionary mergedRouteValues = 485 RouteValuesHelpers.MergeRouteValues(actionName, controllerName, implicitRouteValues, routeValues, includeImplicitMvcValues: true); 486 487 return new RedirectToRouteResult(null, mergedRouteValues, permanent: true); 488 } 489 RedirectToRoute(object routeValues)490 protected internal RedirectToRouteResult RedirectToRoute(object routeValues) 491 { 492 return RedirectToRoute(new RouteValueDictionary(routeValues)); 493 } 494 RedirectToRoute(RouteValueDictionary routeValues)495 protected internal RedirectToRouteResult RedirectToRoute(RouteValueDictionary routeValues) 496 { 497 return RedirectToRoute(null /* routeName */, routeValues); 498 } 499 RedirectToRoute(string routeName)500 protected internal RedirectToRouteResult RedirectToRoute(string routeName) 501 { 502 return RedirectToRoute(routeName, (RouteValueDictionary)null); 503 } 504 RedirectToRoute(string routeName, object routeValues)505 protected internal RedirectToRouteResult RedirectToRoute(string routeName, object routeValues) 506 { 507 return RedirectToRoute(routeName, new RouteValueDictionary(routeValues)); 508 } 509 RedirectToRoute(string routeName, RouteValueDictionary routeValues)510 protected internal virtual RedirectToRouteResult RedirectToRoute(string routeName, RouteValueDictionary routeValues) 511 { 512 return new RedirectToRouteResult(routeName, RouteValuesHelpers.GetRouteValues(routeValues)); 513 } 514 RedirectToRoutePermanent(object routeValues)515 protected internal RedirectToRouteResult RedirectToRoutePermanent(object routeValues) 516 { 517 return RedirectToRoutePermanent(new RouteValueDictionary(routeValues)); 518 } 519 RedirectToRoutePermanent(RouteValueDictionary routeValues)520 protected internal RedirectToRouteResult RedirectToRoutePermanent(RouteValueDictionary routeValues) 521 { 522 return RedirectToRoutePermanent(null /* routeName */, routeValues); 523 } 524 RedirectToRoutePermanent(string routeName)525 protected internal RedirectToRouteResult RedirectToRoutePermanent(string routeName) 526 { 527 return RedirectToRoutePermanent(routeName, (RouteValueDictionary)null); 528 } 529 RedirectToRoutePermanent(string routeName, object routeValues)530 protected internal RedirectToRouteResult RedirectToRoutePermanent(string routeName, object routeValues) 531 { 532 return RedirectToRoutePermanent(routeName, new RouteValueDictionary(routeValues)); 533 } 534 RedirectToRoutePermanent(string routeName, RouteValueDictionary routeValues)535 protected internal virtual RedirectToRouteResult RedirectToRoutePermanent(string routeName, RouteValueDictionary routeValues) 536 { 537 return new RedirectToRouteResult(routeName, RouteValuesHelpers.GetRouteValues(routeValues), permanent: true); 538 } 539 540 protected internal bool TryUpdateModel<TModel>(TModel model) where TModel : class 541 { 542 return TryUpdateModel(model, null, null, null, ValueProvider); 543 } 544 545 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix) where TModel : class 546 { 547 return TryUpdateModel(model, prefix, null, null, ValueProvider); 548 } 549 550 protected internal bool TryUpdateModel<TModel>(TModel model, string[] includeProperties) where TModel : class 551 { 552 return TryUpdateModel(model, null, includeProperties, null, ValueProvider); 553 } 554 555 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class 556 { 557 return TryUpdateModel(model, prefix, includeProperties, null, ValueProvider); 558 } 559 560 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class 561 { 562 return TryUpdateModel(model, prefix, includeProperties, excludeProperties, ValueProvider); 563 } 564 565 protected internal bool TryUpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class 566 { 567 return TryUpdateModel(model, null, null, null, valueProvider); 568 } 569 570 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class 571 { 572 return TryUpdateModel(model, prefix, null, null, valueProvider); 573 } 574 575 protected internal bool TryUpdateModel<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class 576 { 577 return TryUpdateModel(model, null, includeProperties, null, valueProvider); 578 } 579 580 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class 581 { 582 return TryUpdateModel(model, prefix, includeProperties, null, valueProvider); 583 } 584 585 protected internal bool TryUpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class 586 { 587 if (model == null) 588 { 589 throw new ArgumentNullException("model"); 590 } 591 if (valueProvider == null) 592 { 593 throw new ArgumentNullException("valueProvider"); 594 } 595 596 Predicate<string> propertyFilter = propertyName => BindAttribute.IsPropertyAllowed(propertyName, includeProperties, excludeProperties); 597 IModelBinder binder = Binders.GetBinder(typeof(TModel)); 598 599 ModelBindingContext bindingContext = new ModelBindingContext() 600 { 601 ModelMetadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, typeof(TModel)), 602 ModelName = prefix, 603 ModelState = ModelState, 604 PropertyFilter = propertyFilter, 605 ValueProvider = valueProvider 606 }; binder.BindModel(ControllerContext, bindingContext)607 binder.BindModel(ControllerContext, bindingContext); 608 return ModelState.IsValid; 609 } 610 TryValidateModel(object model)611 protected internal bool TryValidateModel(object model) 612 { 613 return TryValidateModel(model, null /* prefix */); 614 } 615 TryValidateModel(object model, string prefix)616 protected internal bool TryValidateModel(object model, string prefix) 617 { 618 if (model == null) 619 { 620 throw new ArgumentNullException("model"); 621 } 622 623 ModelMetadata metadata = ModelMetadataProviders.Current.GetMetadataForType(() => model, model.GetType()); 624 625 foreach (ModelValidationResult validationResult in ModelValidator.GetModelValidator(metadata, ControllerContext).Validate(null)) 626 { 627 ModelState.AddModelError(DefaultModelBinder.CreateSubPropertyName(prefix, validationResult.MemberName), validationResult.Message); 628 } 629 630 return ModelState.IsValid; 631 } 632 633 protected internal void UpdateModel<TModel>(TModel model) where TModel : class 634 { UpdateModel(model, null, null, null, ValueProvider)635 UpdateModel(model, null, null, null, ValueProvider); 636 } 637 638 protected internal void UpdateModel<TModel>(TModel model, string prefix) where TModel : class 639 { UpdateModel(model, prefix, null, null, ValueProvider)640 UpdateModel(model, prefix, null, null, ValueProvider); 641 } 642 643 protected internal void UpdateModel<TModel>(TModel model, string[] includeProperties) where TModel : class 644 { UpdateModel(model, null, includeProperties, null, ValueProvider)645 UpdateModel(model, null, includeProperties, null, ValueProvider); 646 } 647 648 protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties) where TModel : class 649 { UpdateModel(model, prefix, includeProperties, null, ValueProvider)650 UpdateModel(model, prefix, includeProperties, null, ValueProvider); 651 } 652 653 protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties) where TModel : class 654 { UpdateModel(model, prefix, includeProperties, excludeProperties, ValueProvider)655 UpdateModel(model, prefix, includeProperties, excludeProperties, ValueProvider); 656 } 657 658 protected internal void UpdateModel<TModel>(TModel model, IValueProvider valueProvider) where TModel : class 659 { UpdateModel(model, null, null, null, valueProvider)660 UpdateModel(model, null, null, null, valueProvider); 661 } 662 663 protected internal void UpdateModel<TModel>(TModel model, string prefix, IValueProvider valueProvider) where TModel : class 664 { UpdateModel(model, prefix, null, null, valueProvider)665 UpdateModel(model, prefix, null, null, valueProvider); 666 } 667 668 protected internal void UpdateModel<TModel>(TModel model, string[] includeProperties, IValueProvider valueProvider) where TModel : class 669 { UpdateModel(model, null, includeProperties, null, valueProvider)670 UpdateModel(model, null, includeProperties, null, valueProvider); 671 } 672 673 protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, IValueProvider valueProvider) where TModel : class 674 { UpdateModel(model, prefix, includeProperties, null, valueProvider)675 UpdateModel(model, prefix, includeProperties, null, valueProvider); 676 } 677 678 protected internal void UpdateModel<TModel>(TModel model, string prefix, string[] includeProperties, string[] excludeProperties, IValueProvider valueProvider) where TModel : class 679 { 680 bool success = TryUpdateModel(model, prefix, includeProperties, excludeProperties, valueProvider); 681 if (!success) 682 { 683 string message = String.Format(CultureInfo.CurrentCulture, MvcResources.Controller_UpdateModel_UpdateUnsuccessful, 684 typeof(TModel).FullName); 685 throw new InvalidOperationException(message); 686 } 687 } 688 ValidateModel(object model)689 protected internal void ValidateModel(object model) 690 { 691 ValidateModel(model, null /* prefix */); 692 } 693 ValidateModel(object model, string prefix)694 protected internal void ValidateModel(object model, string prefix) 695 { 696 if (!TryValidateModel(model, prefix)) 697 { 698 throw new InvalidOperationException( 699 String.Format( 700 CultureInfo.CurrentCulture, 701 MvcResources.Controller_Validate_ValidationFailed, 702 model.GetType().FullName)); 703 } 704 } 705 View()706 protected internal ViewResult View() 707 { 708 return View(viewName: null, masterName: null, model: null); 709 } 710 View(object model)711 protected internal ViewResult View(object model) 712 { 713 return View(null /* viewName */, null /* masterName */, model); 714 } 715 View(string viewName)716 protected internal ViewResult View(string viewName) 717 { 718 return View(viewName, masterName: null, model: null); 719 } 720 View(string viewName, string masterName)721 protected internal ViewResult View(string viewName, string masterName) 722 { 723 return View(viewName, masterName, null /* model */); 724 } 725 View(string viewName, object model)726 protected internal ViewResult View(string viewName, object model) 727 { 728 return View(viewName, null /* masterName */, model); 729 } 730 View(string viewName, string masterName, object model)731 protected internal virtual ViewResult View(string viewName, string masterName, object model) 732 { 733 if (model != null) 734 { 735 ViewData.Model = model; 736 } 737 738 return new ViewResult 739 { 740 ViewName = viewName, 741 MasterName = masterName, 742 ViewData = ViewData, 743 TempData = TempData, 744 ViewEngineCollection = ViewEngineCollection 745 }; 746 } 747 748 [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Justification = "The method name 'View' is a convenient shorthand for 'CreateViewResult'.")] View(IView view)749 protected internal ViewResult View(IView view) 750 { 751 return View(view, null /* model */); 752 } 753 754 [SuppressMessage("Microsoft.Naming", "CA1719:ParameterNamesShouldNotMatchMemberNames", MessageId = "0#", Justification = "The method name 'View' is a convenient shorthand for 'CreateViewResult'.")] View(IView view, object model)755 protected internal virtual ViewResult View(IView view, object model) 756 { 757 if (model != null) 758 { 759 ViewData.Model = model; 760 } 761 762 return new ViewResult 763 { 764 View = view, 765 ViewData = ViewData, 766 TempData = TempData 767 }; 768 } 769 IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)770 IAsyncResult IAsyncController.BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) 771 { 772 return BeginExecute(requestContext, callback, state); 773 } 774 IAsyncController.EndExecute(IAsyncResult asyncResult)775 void IAsyncController.EndExecute(IAsyncResult asyncResult) 776 { 777 EndExecute(asyncResult); 778 } 779 BeginExecute(RequestContext requestContext, AsyncCallback callback, object state)780 protected virtual IAsyncResult BeginExecute(RequestContext requestContext, AsyncCallback callback, object state) 781 { 782 if (DisableAsyncSupport) 783 { 784 // For backwards compat, we can disallow async support and just chain to the sync Execute() function. 785 Action action = () => 786 { 787 Execute(requestContext); 788 }; 789 790 return AsyncResultWrapper.BeginSynchronous(callback, state, action, _executeTag); 791 } 792 else 793 { 794 if (requestContext == null) 795 { 796 throw new ArgumentNullException("requestContext"); 797 } 798 799 // Support Asynchronous behavior. 800 // Execute/ExecuteCore are no longer called. 801 802 VerifyExecuteCalledOnce(); 803 Initialize(requestContext); 804 return AsyncResultWrapper.Begin(callback, state, BeginExecuteCore, EndExecuteCore, _executeTag); 805 } 806 } 807 BeginExecuteCore(AsyncCallback callback, object state)808 protected virtual IAsyncResult BeginExecuteCore(AsyncCallback callback, object state) 809 { 810 // If code in this method needs to be updated, please also check the ExecuteCore() method 811 // of Controller to see if that code also must be updated. 812 PossiblyLoadTempData(); 813 try 814 { 815 string actionName = RouteData.GetRequiredString("action"); 816 IActionInvoker invoker = ActionInvoker; 817 IAsyncActionInvoker asyncInvoker = invoker as IAsyncActionInvoker; 818 if (asyncInvoker != null) 819 { 820 // asynchronous invocation 821 BeginInvokeDelegate beginDelegate = delegate(AsyncCallback asyncCallback, object asyncState) 822 { 823 return asyncInvoker.BeginInvokeAction(ControllerContext, actionName, asyncCallback, asyncState); 824 }; 825 826 EndInvokeDelegate endDelegate = delegate(IAsyncResult asyncResult) 827 { 828 if (!asyncInvoker.EndInvokeAction(asyncResult)) 829 { 830 HandleUnknownAction(actionName); 831 } 832 }; 833 834 return AsyncResultWrapper.Begin(callback, state, beginDelegate, endDelegate, _executeCoreTag); 835 } 836 else 837 { 838 // synchronous invocation 839 Action action = () => 840 { 841 if (!invoker.InvokeAction(ControllerContext, actionName)) 842 { 843 HandleUnknownAction(actionName); 844 } 845 }; 846 return AsyncResultWrapper.BeginSynchronous(callback, state, action, _executeCoreTag); 847 } 848 } 849 catch 850 { 851 PossiblySaveTempData(); 852 throw; 853 } 854 } 855 EndExecute(IAsyncResult asyncResult)856 protected virtual void EndExecute(IAsyncResult asyncResult) 857 { 858 AsyncResultWrapper.End(asyncResult, _executeTag); 859 } 860 EndExecuteCore(IAsyncResult asyncResult)861 protected virtual void EndExecuteCore(IAsyncResult asyncResult) 862 { 863 // If code in this method needs to be updated, please also check the ExecuteCore() method 864 // of Controller to see if that code also must be updated. 865 866 try 867 { 868 AsyncResultWrapper.End(asyncResult, _executeCoreTag); 869 } 870 finally 871 { 872 PossiblySaveTempData(); 873 } 874 } 875 876 #region IActionFilter Members 877 IActionFilter.OnActionExecuting(ActionExecutingContext filterContext)878 void IActionFilter.OnActionExecuting(ActionExecutingContext filterContext) 879 { 880 OnActionExecuting(filterContext); 881 } 882 IActionFilter.OnActionExecuted(ActionExecutedContext filterContext)883 void IActionFilter.OnActionExecuted(ActionExecutedContext filterContext) 884 { 885 OnActionExecuted(filterContext); 886 } 887 888 #endregion 889 890 #region IAuthorizationFilter Members 891 IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext)892 void IAuthorizationFilter.OnAuthorization(AuthorizationContext filterContext) 893 { 894 OnAuthorization(filterContext); 895 } 896 897 #endregion 898 899 #region IExceptionFilter Members 900 IExceptionFilter.OnException(ExceptionContext filterContext)901 void IExceptionFilter.OnException(ExceptionContext filterContext) 902 { 903 OnException(filterContext); 904 } 905 906 #endregion 907 908 #region IResultFilter Members 909 IResultFilter.OnResultExecuting(ResultExecutingContext filterContext)910 void IResultFilter.OnResultExecuting(ResultExecutingContext filterContext) 911 { 912 OnResultExecuting(filterContext); 913 } 914 IResultFilter.OnResultExecuted(ResultExecutedContext filterContext)915 void IResultFilter.OnResultExecuted(ResultExecutedContext filterContext) 916 { 917 OnResultExecuted(filterContext); 918 } 919 920 #endregion 921 } 922 } 923