private PageActionInvokerCacheEntry CreateCacheEntry( CompiledPageActionDescriptor compiledActionDescriptor, FilterItem[] cachedFilters) { var viewDataFactory = ViewDataDictionaryFactory.CreateFactory(compiledActionDescriptor.DeclaredModelTypeInfo); var pageFactory = _pageFactoryProvider.CreatePageFactory(compiledActionDescriptor); var pageDisposer = _pageFactoryProvider.CreateAsyncPageDisposer(compiledActionDescriptor); var propertyBinder = PageBinderFactory.CreatePropertyBinder( _parameterBinder, _modelMetadataProvider, _modelBinderFactory, compiledActionDescriptor); Func <PageContext, object>? modelFactory = null; Func <PageContext, object, ValueTask>?modelReleaser = null; if (compiledActionDescriptor.ModelTypeInfo != compiledActionDescriptor.PageTypeInfo) { modelFactory = _modelFactoryProvider.CreateModelFactory(compiledActionDescriptor); modelReleaser = _modelFactoryProvider.CreateAsyncModelDisposer(compiledActionDescriptor); } var viewStartFactories = GetViewStartFactories(compiledActionDescriptor); var handlerExecutors = GetHandlerExecutors(compiledActionDescriptor); var handlerBinders = GetHandlerBinders(compiledActionDescriptor); return(new PageActionInvokerCacheEntry( compiledActionDescriptor, viewDataFactory, pageFactory, pageDisposer, modelFactory, modelReleaser, propertyBinder, handlerExecutors, handlerBinders, viewStartFactories, cachedFilters)); }
private PageHandlerBinderDelegate[] GetHandlerBinders(CompiledPageActionDescriptor actionDescriptor) { if (actionDescriptor.HandlerMethods == null || actionDescriptor.HandlerMethods.Count == 0) { return(Array.Empty <PageHandlerBinderDelegate>()); } var results = new PageHandlerBinderDelegate[actionDescriptor.HandlerMethods.Count]; for (var i = 0; i < actionDescriptor.HandlerMethods.Count; i++) { results[i] = PageBinderFactory.CreateHandlerBinder( _parameterBinder, _modelMetadataProvider, _modelBinderFactory, actionDescriptor, actionDescriptor.HandlerMethods[i]); } return(results); }
public void CreateModelDisposer_ReturnsDisposerFromModelActivatorProvider() { // Arrange var descriptor = new CompiledPageActionDescriptor { ModelTypeInfo = typeof(SimpleModel).GetTypeInfo() }; var pageContext = new PageContext(); var modelActivatorProvider = new Mock <IPageModelActivatorProvider>(); Action <PageContext, object> disposer = (_, __) => { }; modelActivatorProvider.Setup(p => p.CreateReleaser(descriptor)) .Returns(disposer); var factoryProvider = CreateModelFactoryProvider(modelActivatorProvider.Object); // Act var actual = factoryProvider.CreateModelDisposer(descriptor); // Assert Assert.Same(disposer, actual); }
/// <inheritdoc /> public virtual Func <PageContext, object> CreateActivator(CompiledPageActionDescriptor actionDescriptor) { if (actionDescriptor == null) { throw new ArgumentNullException(nameof(actionDescriptor)); } var modelTypeInfo = actionDescriptor.ModelTypeInfo?.AsType(); if (modelTypeInfo == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( nameof(actionDescriptor.ModelTypeInfo), nameof(actionDescriptor)), nameof(actionDescriptor)); } var factory = ActivatorUtilities.CreateFactory(modelTypeInfo, Type.EmptyTypes); return((context) => factory(context.HttpContext.RequestServices, Array.Empty <object>())); }
private static AuthorizationFailedHandlerAttribute GetCustomHandlerOrDefault(CompiledPageActionDescriptor compiledPageActionDescriptor) { AuthorizationFailedHandlerAttribute result; HandlerMethodDescriptor methodDescriptor = compiledPageActionDescriptor.HandlerMethods[0]; if (methodDescriptor != null) { result = methodDescriptor.MethodInfo .GetCustomAttributes <AuthorizationFailedHandlerAttribute>(false) .FirstOrDefault(); if (result != null) { return(result); } } result = compiledPageActionDescriptor.ModelTypeInfo .GetCustomAttributes <AuthorizationFailedHandlerAttribute>(true) .FirstOrDefault(); return(result); }
public void CreateReleaser_CreatesDelegateThatDisposesDisposableTypes() { // Arrange var context = new PageContext(); var activator = new DefaultPageModelActivatorProvider(); var actionDescriptor = new CompiledPageActionDescriptor { ModelTypeInfo = typeof(DisposableModel).GetTypeInfo(), }; var model = new DisposableModel(); // Act & Assert var releaser = activator.CreateReleaser(actionDescriptor); releaser(context, model); // Assert Assert.True(model.Disposed); }
public void GetModelBinderFactory_ReturnsNullIfPageModelHasNoVisibleBoundProperties() { // Arrange var actionDescriptor = new CompiledPageActionDescriptor { PageTypeInfo = typeof(object).GetTypeInfo(), ModelTypeInfo = typeof(PageModelWithNoVisibleBoundProperties).GetTypeInfo(), }; var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var binder = new ParameterBinder( modelMetadataProvider, TestModelBinderFactory.CreateDefault(), Mock.Of <IModelValidatorProvider>(), NullLoggerFactory.Instance); // Act var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); // Assert Assert.Null(factory); }
public void CreateActivator_ReturnsFactoryForPage(Type type) { // Arrange var pageContext = new PageContext(); var viewContext = new ViewContext(); var descriptor = new CompiledPageActionDescriptor { PageTypeInfo = type.GetTypeInfo(), }; var activator = new DefaultPageActivatorProvider(); // Act var factory = activator.CreateActivator(descriptor); var instance = factory(pageContext, viewContext); // Assert Assert.NotNull(instance); Assert.IsType(type, instance); }
/// <inheritdoc/> public Func <PageContext, object> CreateActivator(CompiledPageActionDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } var modelType = descriptor.ModelTypeInfo?.AsType(); if (modelType == null) { throw new ArgumentException(Resources.FormatPropertyOfTypeCannotBeNull( nameof(descriptor.ModelTypeInfo), nameof(descriptor)), nameof(descriptor)); } return(context => { return context.HttpContext.RequestServices.GetRequiredService(modelType); }); }
public void GetModelBinderFactory_ReturnsNullIfPageHasNoSettableBoundProperties() { // Arrange var actionDescriptor = new CompiledPageActionDescriptor { PageTypeInfo = typeof(PageWithReadOnlyProperties).GetTypeInfo(), }; var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var modelBinderFactory = TestModelBinderFactory.CreateDefault(); var binder = new ParameterBinder( modelMetadataProvider, modelBinderFactory, Mock.Of <IObjectModelValidator>(), NullLoggerFactory.Instance); // Act var factory = PageBinderFactory.CreatePropertyBinder(binder, modelMetadataProvider, modelBinderFactory, actionDescriptor); // Assert Assert.Same(PageBinderFactory.NullPropertyBinder, factory); }
private AuthenticationFailedHandlerAttribute[] GetCustomHandlers(CompiledPageActionDescriptor compiledPageActionDescriptor) { List <AuthenticationFailedHandlerAttribute> result = new List <AuthenticationFailedHandlerAttribute>(); HandlerMethodDescriptor methodDescriptor = compiledPageActionDescriptor.HandlerMethods[0]; bool checkPageModel = true; if (methodDescriptor != null) { MethodInfo method = methodDescriptor.MethodInfo; if (method.HasAttribute <AuthenticationFailedHandlerAttribute>(false)) { result.AddRange(method.GetCustomAttributes <AuthenticationFailedHandlerAttribute>(false)); checkPageModel = false; } } if (checkPageModel) { Type baseType; TypeInfo controllerType; while (true) { controllerType = compiledPageActionDescriptor.ModelTypeInfo; if (controllerType.HasAttribute <AuthenticationFailedHandlerAttribute>(false)) { result.AddRange(controllerType.GetCustomAttributes <AuthenticationFailedHandlerAttribute>(false)); break; } baseType = controllerType.BaseType; if (baseType == null) { break; } controllerType = baseType.GetTypeInfo(); } } return(result.ToArray()); }
public async Task LoadAsync_CompiledPageActionDescriptor_ReturnsSelf() { // Arrange var mvcOptions = Options.Create(new MvcOptions()); var endpointFactory = new ActionEndpointFactory(Mock.Of <RoutePatternTransformer>(), Enumerable.Empty <IRequestDelegateFactory>(), Mock.Of <IServiceProvider>()); var loader = new DefaultPageLoader( new[] { Mock.Of <IPageApplicationModelProvider>() }, Mock.Of <IViewCompilerProvider>(), endpointFactory, RazorPagesOptions, mvcOptions); var pageDescriptor = new CompiledPageActionDescriptor(); // Act var result1 = await loader.LoadAsync(pageDescriptor, new EndpointMetadataCollection()); var result2 = await loader.LoadAsync(pageDescriptor, new EndpointMetadataCollection()); // Assert Assert.Same(pageDescriptor, result1); Assert.Same(pageDescriptor, result2); }
/// <summary> /// Creates a Razor Page model activator. /// </summary> /// <param name="descriptor">The <see cref="CompiledPageActionDescriptor"/>.</param> /// <returns>The delegate used to activate the page model.</returns> public Func <PageContext, object> CreateActivator(CompiledPageActionDescriptor descriptor) { if (descriptor is null) { throw new ArgumentNullException(nameof(descriptor)); } if (descriptor.ModelTypeInfo is null) { throw new ArgumentNullException( nameof(descriptor.ModelTypeInfo) + " property cannot be null.", nameof(descriptor)); } Type pageModelType = descriptor.ModelTypeInfo.AsType(); InstanceProducer?producer = this.pageModelProducers.GetOrAdd(pageModelType, this.GetPageModelProducer); if (producer is null) { throw new InvalidOperationException( string.Format( CultureInfo.InvariantCulture, "For the {0} to function properly, it requires all page models to be registered explicitly " + "in Simple Injector, but a registration for {1} is missing. To ensure all page models are " + "registered properly, call the RegisterPageModels extension method on the Container " + "from within your Startup.Configure method while supplying the IApplicationBuilder " + "instance, e.g. \"this.container.RegisterPageModels(app);\".{2}" + "Full page model name: {3}.", typeof(SimpleInjectorPageModelActivatorProvider).Name, pageModelType.ToFriendlyName(), Environment.NewLine, pageModelType.FullName)); } return(_ => producer.GetInstance()); }
public void PageFactorySetsPageContext() { // Arrange var descriptor = new CompiledPageActionDescriptor { PageTypeInfo = typeof(TestPage).GetTypeInfo(), }; var pageContext = new PageContext { ActionDescriptor = descriptor }; var viewContext = new ViewContext(); var factoryProvider = CreatePageFactory(); // Act var factory = factoryProvider.CreatePageFactory(descriptor); var instance = factory(pageContext, viewContext); // Assert var testPage = Assert.IsType <TestPage>(instance); Assert.Same(pageContext, testPage.PageContext); }
public PageActionInvokerCacheEntry( CompiledPageActionDescriptor actionDescriptor, Func <IModelMetadataProvider, ModelStateDictionary, ViewDataDictionary> viewDataFactory, Func <PageContext, ViewContext, object> pageFactory, Action <PageContext, ViewContext, object> releasePage, Func <PageContext, object> modelFactory, Action <PageContext, object> releaseModel, Func <PageContext, object, Task> propertyBinder, Func <object, object[], Task <IActionResult> >[] executors, IReadOnlyList <Func <IRazorPage> > viewStartFactories, FilterItem[] cacheableFilters) { ActionDescriptor = actionDescriptor; ViewDataFactory = viewDataFactory; PageFactory = pageFactory; ReleasePage = releasePage; ModelFactory = modelFactory; ReleaseModel = releaseModel; PropertyBinder = propertyBinder; Executors = executors; ViewStartFactories = viewStartFactories; CacheableFilters = cacheableFilters; }
public static Func <PageContext, object, Task> CreateBinder( ParameterBinder parameterBinder, IModelMetadataProvider modelMetadataProvider, CompiledPageActionDescriptor actionDescriptor) { if (parameterBinder == null) { throw new ArgumentNullException(nameof(parameterBinder)); } if (actionDescriptor == null) { throw new ArgumentNullException(nameof(actionDescriptor)); } var properties = actionDescriptor.BoundProperties; if (properties == null || properties.Count == 0) { return(null); } var type = actionDescriptor.HandlerTypeInfo.AsType(); var metadata = new ModelMetadata[properties.Count]; for (var i = 0; i < properties.Count; i++) { metadata[i] = modelMetadataProvider.GetMetadataForProperty(type, properties[i].Name); } return(Bind); Task Bind(PageContext pageContext, object instance) { return(BindPropertiesAsync(parameterBinder, pageContext, instance, properties, metadata)); } }
public async Task OnResourceExecutionAsync(ResourceExecutingContext context, ResourceExecutionDelegate next) { IEnumerable <Attribute> attributes = context.ActionDescriptor switch { CompiledPageActionDescriptor p => p.ModelTypeInfo.GetCustomAttributes(), ControllerActionDescriptor c => c.ControllerTypeInfo.GetCustomAttributes(), _ => throw new NotImplementedException( $"Unknown controller type: {context.ActionDescriptor.GetType().Name}" ) }; ISet <SanityCheckKind> failures = this._checker.Run(SanityCheckKind.MainPasswordIsSet); if (failures.Count > 0 && attributes.All(a => a.GetType() != typeof(Ignore))) { this._nb.Add($"Sanity checks failed: {String.Join(", ", failures)}."); context.Result = new RedirectResult(Urls.InitUrl); } else { await next(); } } }
public void GetViewStartFactories_FindsFullHeirarchy() { // Arrange var descriptor = new PageActionDescriptor() { RelativePath = "/Pages/Level1/Level2/Index.cshtml", FilterDescriptors = new FilterDescriptor[0], ViewEnginePath = "/Pages/Level1/Level2/Index.cshtml" }; var compiledPageDescriptor = new CompiledPageActionDescriptor(descriptor) { PageTypeInfo = typeof(object).GetTypeInfo(), }; var loader = new Mock <IPageLoader>(); loader .Setup(l => l.Load(It.IsAny <PageActionDescriptor>())) .Returns(compiledPageDescriptor); var fileProvider = new TestFileProvider(); fileProvider.AddFile("/_ViewStart.cshtml", "page content"); fileProvider.AddFile("/Pages/_ViewStart.cshtml", "page content"); fileProvider.AddFile("/Pages/Level1/_ViewStart.cshtml", "page content"); fileProvider.AddFile("/Pages/Level1/Level2/_ViewStart.cshtml", "page content"); fileProvider.AddFile("/Pages/Level1/Level3/_ViewStart.cshtml", "page content"); var razorProject = new TestRazorProject(fileProvider, _hostingEnvironment); var mock = new Mock <IRazorPageFactoryProvider>(MockBehavior.Strict); mock .Setup(p => p.CreateFactory("/Pages/Level1/Level2/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null)) .Verifiable(); mock .Setup(p => p.CreateFactory("/Pages/Level1/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null)) .Verifiable(); mock .Setup(p => p.CreateFactory("/Pages/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null)) .Verifiable(); mock .Setup(p => p.CreateFactory("/_ViewStart.cshtml")) .Returns(new RazorPageFactoryResult(new CompiledViewDescriptor(), () => null)) .Verifiable(); var razorPageFactoryProvider = mock.Object; var invokerProvider = CreateInvokerProvider( loader.Object, CreateActionDescriptorCollection(descriptor), razorPageFactoryProvider: razorPageFactoryProvider, razorProject: razorProject); // Act var factories = invokerProvider.GetViewStartFactories(compiledPageDescriptor); // Assert mock.Verify(); }
public async Task ModelBinderFactory_BindsPropertiesOnPageModel() { // Arrange var type = typeof(PageModelWithProperty).GetTypeInfo(); var actionDescriptor = new CompiledPageActionDescriptor { BoundProperties = new[] { new PageBoundPropertyDescriptor() { Name = nameof(PageModelWithProperty.Id), ParameterType = typeof(int), Property = type.GetProperty(nameof(PageModelWithProperty.Id)), }, new PageBoundPropertyDescriptor() { Name = nameof(PageModelWithProperty.RouteDifferentValue), ParameterType = typeof(string), Property = type.GetProperty(nameof(PageModelWithProperty.RouteDifferentValue)), }, new PageBoundPropertyDescriptor() { Name = nameof(PageModelWithProperty.PropertyWithNoValue), ParameterType = typeof(string), Property = type.GetProperty(nameof(PageModelWithProperty.PropertyWithNoValue)), } }, HandlerTypeInfo = typeof(PageModelWithProperty).GetTypeInfo(), PageTypeInfo = typeof(PageWithProperty).GetTypeInfo(), ModelTypeInfo = typeof(PageModelWithProperty).GetTypeInfo(), }; var binder = new TestParameterBinder(new Dictionary <string, object> { { nameof(PageModelWithProperty.Id), 10 }, { nameof(PageModelWithProperty.RouteDifferentValue), "route-value" } }); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var factory = PagePropertyBinderFactory.CreateBinder(binder, modelMetadataProvider, actionDescriptor); var page = new PageWithProperty { PageContext = GetPageContext() }; var model = new PageModelWithProperty(); // Act await factory(page.PageContext, model); // Assert // Verify that the page properties were not bound. Assert.Equal(default(int), page.Id); Assert.Null(page.RouteDifferentValue); Assert.Equal(10, model.Id); Assert.Equal("route-value", model.RouteDifferentValue); Assert.Null(model.PropertyWithNoValue); }
public Func <PageContext, object> CreateActivator([NotNull] CompiledPageActionDescriptor descriptor) { Check.NotNull(descriptor, nameof(descriptor)); return(context => context.HttpContext.RequestServices.GetRequiredService(descriptor.ModelTypeInfo)); }
public async Task ModelBinderFactory_BindsPropertyWithoutSupportsGet_WhenRequestIsNotGet() { // Arrange var type = typeof(PageModelWithSupportsGetProperty).GetTypeInfo(); var actionDescriptor = new CompiledPageActionDescriptor { BoundProperties = new[] { new PageBoundPropertyDescriptor() { Name = nameof(PageModelWithSupportsGetProperty.SupportsGet), ParameterType = typeof(string), Property = type.GetProperty(nameof(PageModelWithSupportsGetProperty.SupportsGet)), BindingInfo = new BindingInfo() { RequestPredicate = ((IRequestPredicateProvider) new BindPropertyAttribute() { SupportsGet = true }).RequestPredicate, } }, new PageBoundPropertyDescriptor() { Name = nameof(PageModelWithSupportsGetProperty.Default), ParameterType = typeof(string), Property = type.GetProperty(nameof(PageModelWithSupportsGetProperty.Default)), }, }, HandlerTypeInfo = type, PageTypeInfo = typeof(PageWithProperty).GetTypeInfo(), ModelTypeInfo = type, }; var binder = new TestParameterBinder(new Dictionary <string, object>() { { "SupportsGet", "value" }, { "Default", "value" }, }); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var modelBinderFactory = TestModelBinderFactory.CreateDefault(); var factory = PageBinderFactory.CreatePropertyBinder(binder, modelMetadataProvider, modelBinderFactory, actionDescriptor); var page = new PageWithProperty { PageContext = GetPageContext() }; page.HttpContext.Request.Method = "Post"; var model = new PageModelWithSupportsGetProperty(); // Act await factory(page.PageContext, model); // Assert Assert.Equal("value", model.SupportsGet); Assert.Equal("value", model.Default); }
/// <inheritdoc /> public Action <PageContext, object> CreateReleaser(CompiledPageActionDescriptor descriptor) => null;
/// <inheritdoc/> public Action <PageContext, object>?CreateReleaser(CompiledPageActionDescriptor descriptor) { return(null); }
public async Task BindModelAsync_WithBindPageProperty_EnforcesBindRequired(int?input, bool isValid) { // Arrange var propertyInfo = typeof(TestPage).GetProperty(nameof(TestPage.BindRequiredProperty)); var propertyDescriptor = new PageBoundPropertyDescriptor { BindingInfo = BindingInfo.GetBindingInfo(new[] { new FromQueryAttribute { Name = propertyInfo.Name }, }), Name = propertyInfo.Name, ParameterType = propertyInfo.PropertyType, Property = propertyInfo, }; var typeInfo = typeof(TestPage).GetTypeInfo(); var actionDescriptor = new CompiledPageActionDescriptor { BoundProperties = new[] { propertyDescriptor }, HandlerTypeInfo = typeInfo, ModelTypeInfo = typeInfo, PageTypeInfo = typeInfo, }; var testContext = ModelBindingTestHelper.GetTestContext(request => { request.Method = "POST"; if (input.HasValue) { request.QueryString = new QueryString($"?{propertyDescriptor.Name}={input.Value}"); } }); var modelMetadataProvider = TestModelMetadataProvider.CreateDefaultProvider(); var parameterBinder = ModelBindingTestHelper.GetParameterBinder(modelMetadataProvider); var modelBinderFactory = ModelBindingTestHelper.GetModelBinderFactory(modelMetadataProvider); var modelMetadata = modelMetadataProvider .GetMetadataForProperty(typeof(TestPage), propertyDescriptor.Name); var pageBinder = PageBinderFactory.CreatePropertyBinder( parameterBinder, modelMetadataProvider, modelBinderFactory, actionDescriptor); var pageContext = new PageContext { ActionDescriptor = actionDescriptor, HttpContext = testContext.HttpContext, RouteData = testContext.RouteData, ValueProviderFactories = testContext.ValueProviderFactories, }; var page = new TestPage(); // Act await pageBinder(pageContext, page); // Assert Assert.Equal(isValid, pageContext.ModelState.IsValid); if (isValid) { Assert.Equal(input.Value, page.BindRequiredProperty); } }
public Func <PageContext, ViewContext, object, ValueTask>?CreateAsyncPageDisposer(CompiledPageActionDescriptor descriptor) { if (descriptor == null) { throw new ArgumentNullException(nameof(descriptor)); } return(_pageActivator.CreateAsyncReleaser(descriptor)); }
public static Func <PageContext, object, Task> CreatePropertyBinder( ParameterBinder parameterBinder, IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, CompiledPageActionDescriptor actionDescriptor) { if (parameterBinder == null) { throw new ArgumentNullException(nameof(parameterBinder)); } if (actionDescriptor == null) { throw new ArgumentNullException(nameof(actionDescriptor)); } var properties = actionDescriptor.BoundProperties; if (properties == null || properties.Count == 0) { return(NullPropertyBinder); } var handlerType = actionDescriptor.HandlerTypeInfo.AsType(); var propertyBindingInfo = new BinderItem[properties.Count]; for (var i = 0; i < properties.Count; i++) { var property = properties[i]; var metadata = modelMetadataProvider.GetMetadataForProperty(handlerType, property.Name); var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = property.BindingInfo, Metadata = metadata, CacheToken = property, }); propertyBindingInfo[i] = new BinderItem(binder, metadata); } return(Bind); async Task Bind(PageContext pageContext, object instance) { var valueProvider = await CompositeValueProvider.CreateAsync(pageContext, pageContext.ValueProviderFactories); for (var i = 0; i < properties.Count; i++) { var property = properties[i]; var bindingInfo = propertyBindingInfo[i]; var modelMetadata = bindingInfo.ModelMetadata; if (!modelMetadata.IsBindingAllowed) { continue; } var result = await parameterBinder.BindModelAsync( pageContext, bindingInfo.ModelBinder, valueProvider, property, modelMetadata, value : null); if (result.IsModelSet) { PropertyValueSetter.SetValue(bindingInfo.ModelMetadata, instance, result.Model); } } } }
public static PageHandlerBinderDelegate CreateHandlerBinder( ParameterBinder parameterBinder, IModelMetadataProvider modelMetadataProvider, IModelBinderFactory modelBinderFactory, CompiledPageActionDescriptor actionDescriptor, HandlerMethodDescriptor handler, MvcOptions mvcOptions) { if (handler.Parameters == null || handler.Parameters.Count == 0) { return(NullHandlerBinder); } var handlerType = actionDescriptor.HandlerTypeInfo.AsType(); var parameterBindingInfo = new BinderItem[handler.Parameters.Count]; for (var i = 0; i < parameterBindingInfo.Length; i++) { var parameter = handler.Parameters[i]; ModelMetadata metadata; if (mvcOptions.AllowValidatingTopLevelNodes && modelMetadataProvider is ModelMetadataProvider modelMetadataProviderBase) { // The default model metadata provider derives from ModelMetadataProvider // and can therefore supply information about attributes applied to parameters. metadata = modelMetadataProviderBase.GetMetadataForParameter(parameter.ParameterInfo); } else { // For backward compatibility, if there's a custom model metadata provider that // only implements the older IModelMetadataProvider interface, access the more // limited metadata information it supplies. In this scenario, validation attributes // are not supported on parameters. metadata = modelMetadataProvider.GetMetadataForType(parameter.ParameterType); } var binder = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext { BindingInfo = parameter.BindingInfo, Metadata = metadata, CacheToken = parameter, }); parameterBindingInfo[i] = new BinderItem(binder, metadata); } return(Bind); async Task Bind(PageContext pageContext, IDictionary <string, object> arguments) { var valueProvider = await CompositeValueProvider.CreateAsync(pageContext, pageContext.ValueProviderFactories); for (var i = 0; i < parameterBindingInfo.Length; i++) { var parameter = handler.Parameters[i]; var bindingInfo = parameterBindingInfo[i]; var modelMetadata = bindingInfo.ModelMetadata; if (!modelMetadata.IsBindingAllowed) { continue; } var result = await parameterBinder.BindModelAsync( pageContext, bindingInfo.ModelBinder, valueProvider, parameter, modelMetadata, value : null); if (result.IsModelSet) { arguments[parameter.Name] = result.Model; } } } }
/// <summary> /// 获取Html生成路径特性 /// </summary> /// <param name="compiledPage">编译后的页面</param> private HtmlPathAttribute GetHtmlPathAttribute(CompiledPageActionDescriptor compiledPage) => compiledPage.PageTypeInfo.GetCustomAttribute <HtmlPathAttribute>() ?? compiledPage.DeclaredModelTypeInfo.GetCustomAttribute <HtmlPathAttribute>();