public void OnProvidersExecuting(ActionInvokerProviderContext context) { if (context == null) { throw new ArgumentNullException(nameof(context)); } if (context.ActionContext.ActionDescriptor is ControllerActionDescriptor) { var controllerContext = new ControllerContext(context.ActionContext) { // PERF: These are rarely going to be changed, so let's go copy-on-write. ValueProviderFactories = new CopyOnWriteList <IValueProviderFactory>(_valueProviderFactories) }; controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; var(cacheEntry, filters) = _controllerActionInvokerCache.GetCachedResult(controllerContext); var invoker = new ControllerActionInvoker( _logger, _diagnosticListener, _actionContextAccessor, _mapper, controllerContext, cacheEntry, filters); context.Result = invoker; } }
/// <summary> /// 提供程序执行时调用 /// </summary> /// <param name="context"></param> /// <exception cref="NotImplementedException"></exception> public void OnProvidersExecuting(ActionInvokerProviderContext context) { // 只针对控制器的Action进行操作 if (!(context.ActionContext.ActionDescriptor is ControllerActionDescriptor controllerActionDescriptor)) { return; } // 只对ClownFish的Action进行参数绑定处理 if (controllerActionDescriptor.Properties.ContainsKey("ClownFish") == false) { return; } ControllerContext controllerContext = new ControllerContext(context.ActionContext); controllerContext.ValueProviderFactories = new CopyOnWriteList <IValueProviderFactory>(_valueProviderFactories); controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; var cachedResult = _controllerActionInvokerCache.GetCachedResult(controllerContext); var controllerActionInvokerCacheEntry = cachedResult.cacheEntry; if (controllerActionInvokerCacheEntry != null) { //兼容多参数绑定的实现 CompatibilityClownFishWeb(controllerActionDescriptor, controllerActionInvokerCacheEntry); } }
/// <summary> /// /// </summary> /// <param name="controllerContext"></param> /// <returns></returns> private object[] BindArguments(ControllerContext controllerContext) { (var cacheEntry, var _) = _controllerActionInvokerCache.GetCachedResult(controllerContext); var actionMethodExecutor = cacheEntry.GetActionMethodExecutor(); var controllerActionInvoker = (ControllerActionInvoker)_actionInvokerFactory.CreateInvoker(_actionContext); var binder = cacheEntry.ControllerBinderDelegate; var arguments = new Dictionary <string, object>(StringComparer.OrdinalIgnoreCase); binder?.Invoke(controllerContext, new object(), arguments).Wait(); var orderedArguments = controllerActionInvoker.PrepareArguments(arguments, actionMethodExecutor); return(orderedArguments); }
public RequestDelegate CreateRequestDelegate(ActionDescriptor actionDescriptor, RouteValueDictionary dataTokens) { // Fallback to action invoker extensibility so that invokers can override any default behaviors if (!_enableActionInvokers && actionDescriptor is ControllerActionDescriptor) { return(context => { RouteData routeData = null; if (dataTokens is null or { Count : 0 }) { routeData = new RouteData(context.Request.RouteValues); } else { routeData = new RouteData(); routeData.PushState(router: null, context.Request.RouteValues, dataTokens); } var actionContext = new ActionContext(context, routeData, actionDescriptor); var controllerContext = new ControllerContext(actionContext) { // PERF: These are rarely going to be changed, so let's go copy-on-write. ValueProviderFactories = new CopyOnWriteList <IValueProviderFactory>(_valueProviderFactories) }; controllerContext.ModelState.MaxAllowedErrors = _maxModelValidationErrors; var(cacheEntry, filters) = _controllerActionInvokerCache.GetCachedResult(controllerContext); var invoker = new ControllerActionInvoker( _logger, _diagnosticListener, _actionContextAccessor, _mapper, controllerContext, cacheEntry, filters); return invoker.InvokeAsync(); });