protected virtual void SetProperty(ModelBindingContext bindingContext, string modelName, ModelMetadata propertyMetadata, ModelBindingResult result, ViewConfigure viewConfigure)
        {
            if (bindingContext == null)
            {
                throw new ArgumentNullException(nameof(bindingContext));
            }

            if (modelName == null)
            {
                throw new ArgumentNullException(nameof(modelName));
            }

            if (propertyMetadata == null)
            {
                throw new ArgumentNullException(nameof(propertyMetadata));
            }

            if (!result.IsModelSet)
            {
                return;
            }

            if (propertyMetadata.IsReadOnly)
            {
                return;
            }

            var value = result.Model;

            try
            {
                propertyMetadata.PropertySetter(bindingContext.Model, value);

                var descriptor = viewConfigure.GetViewPortDescriptor(modelName);
                if (descriptor != null)
                {
                    foreach (var valid in descriptor.Validator)
                    {
                        if (!valid.Validate(value))
                        {
                            if (valid.DisplayName == null)
                            {
                                valid.DisplayName = () => descriptor.DisplayName;
                            }
                            if (bindingContext.ModelState.ContainsKey(modelName))
                            {
                                bindingContext.ModelState[modelName].Errors.Clear();
                            }
                            bindingContext.ModelState.TryAddModelError(modelName, valid.ErrorMessage);
                        }
                    }
                }
            }
            catch (Exception exception)
            {
                AddModelError(exception, modelName, bindingContext);
            }
        }
        private async Task BindModelCoreAsync(ModelBindingContext bindingContext, ViewConfigure viewConfigure)
        {
            if (bindingContext.Model == null)
            {
                bindingContext.Model = CreateModel(bindingContext);
            }

            for (var i = 0; i < bindingContext.ModelMetadata.Properties.Count; i++)
            {
                var property = bindingContext.ModelMetadata.Properties[i];
                if (!CanBindProperty(bindingContext, property))
                {
                    continue;
                }

                object propertyModel = null;
                if (property.PropertyGetter != null &&
                    property.IsComplexType &&
                    !property.ModelType.IsArray)
                {
                    propertyModel = property.PropertyGetter(bindingContext.Model);
                }

                var fieldName = property.BinderModelName ?? property.PropertyName;
                var modelName = ModelNames.CreatePropertyModelName(bindingContext.ModelName, fieldName);

                ModelBindingResult result;
                using (bindingContext.EnterNestedScope(
                           modelMetadata: property,
                           fieldName: fieldName,
                           modelName: modelName,
                           model: propertyModel))
                {
                    await _modelBinderProviderContext.CreateBinder(property).BindModelAsync(bindingContext);

                    result = bindingContext.Result;
                }

                if (result.IsModelSet)
                {
                    SetProperty(bindingContext, modelName, property, result, viewConfigure);
                }
                else
                {
                    var descriptor = viewConfigure.GetViewPortDescriptor(modelName);
                    if (descriptor != null && bindingContext.ModelState.ContainsKey(modelName))
                    {
                        foreach (var valid in descriptor.Validator)
                        {
                            if (!valid.Validate(bindingContext.ModelState[modelName].RawValue))
                            {
                                valid.DisplayName = descriptor.DisplayName;
                                bindingContext.ModelState[modelName].Errors.Clear();
                                bindingContext.ModelState.TryAddModelError(modelName, valid.ErrorMessage);
                                break;
                            }
                        }
                    }

                    else if (property.IsBindingRequired)
                    {
                        var message = property.ModelBindingMessageProvider.MissingBindRequiredValueAccessor(fieldName);
                        bindingContext.ModelState.TryAddModelError(modelName, message);
                    }
                }
            }

            bindingContext.Result = ModelBindingResult.Success(bindingContext.Model);
        }