예제 #1
0
        private static BindingInfo[] GetPropertyBindingInfo(
            IModelBinderFactory modelBinderFactory,
            IModelMetadataProvider modelMetadataProvider,
            ControllerActionDescriptor actionDescriptor)
        {
            var properties = actionDescriptor.BoundProperties;

            if (properties.Count == 0)
            {
                return(null);
            }

            var propertyBindingInfo = new BindingInfo[properties.Count];
            var controllerType      = actionDescriptor.ControllerTypeInfo.AsType();

            for (var i = 0; i < properties.Count; i++)
            {
                var property = properties[i];
                var metadata = modelMetadataProvider.GetMetadataForProperty(controllerType, property.Name);
                var binder   = modelBinderFactory.CreateBinder(new ModelBinderFactoryContext
                {
                    BindingInfo = property.BindingInfo,
                    Metadata    = metadata,
                    CacheToken  = property,
                });

                propertyBindingInfo[i] = new BindingInfo(binder, metadata);
            }

            return(propertyBindingInfo);
        }
예제 #2
0
        public override void Process(TagHelperContext context, TagHelperOutput output)
        {
            var myValidationAttribute = this.For.Metadata.ValidatorMetadata.OfType <MyValidationAttribute>().SingleOrDefault();

            if (myValidationAttribute.ViewModelEnum == ViewModelEnum.ViewModelBase)
            {
                output.PostElement.AppendHtml($"<br /><span>Actual value : {myValidationAttribute.ViewModelEnum.ToString()}</span><br />");
            }

            if (typeof(IViewModel).IsAssignableFrom(this.For.Metadata.ContainerType))
            {
                var modelType = this.ViewContext.ViewData.ModelMetadata.ModelType;

                if (this.For.Metadata.ContainerType != modelType)
                {
                    var propertyMetadata = _modelMetadataProvider.GetMetadataForProperty(modelType, this.For.Name);
                    myValidationAttribute = propertyMetadata.ValidatorMetadata.OfType <MyValidationAttribute>().SingleOrDefault();
                }
            }

            if (myValidationAttribute.ViewModelEnum == ViewModelEnum.ChildViewModel)
            {
                output.PreElement.AppendHtml($"<br /><span>Expected value : {ViewModelEnum.ChildViewModel.ToString()}</span><br />");
            }

            output.TagName = "input";
            base.Process(context, output);
        }
        /// <summary>
        /// Creates a <see cref="PagePropertyModel"/> for the <paramref name="property"/>.
        /// </summary>
        /// <param name="property">The <see cref="PropertyInfo"/>.</param>
        /// <returns>The <see cref="PagePropertyModel"/>.</returns>
        protected virtual PagePropertyModel CreatePropertyModel(PropertyInfo property)
        {
            if (property == null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            var propertyAttributes = property.GetCustomAttributes(inherit: true);

            var propertyMetadata = _modelMetadataProvider.GetMetadataForProperty(property.DeclaringType, property.Name);
            var bindingInfo      = BindingInfo.GetBindingInfo(propertyAttributes, propertyMetadata);

            if (bindingInfo == null)
            {
                // Look for binding info on the handler if nothing is specified on the property.
                // This allows BindProperty attributes on handlers to apply to properties.
                var handlerType       = property.DeclaringType;
                var handlerAttributes = handlerType.GetCustomAttributes(inherit: true);
                var handlerMetadata   = _modelMetadataProvider.GetMetadataForType(property.DeclaringType);
                bindingInfo = BindingInfo.GetBindingInfo(handlerAttributes, handlerMetadata);
            }

            var model = new PagePropertyModel(property, propertyAttributes)
            {
                PropertyName = property.Name,
                BindingInfo  = bindingInfo,
            };

            return(model);
        }
예제 #4
0
        private static ClientModelValidationContext GetValidationContext(
            IUrlHelper urlHelper,
            IStringLocalizerFactory localizerFactory = null,
            IModelMetadataProvider metadataProvider  = null)
        {
            var serviceCollection = GetServiceCollection(localizerFactory);
            var factory           = new Mock <IUrlHelperFactory>(MockBehavior.Strict);

            serviceCollection.AddSingleton <IUrlHelperFactory>(factory.Object);

            var serviceProvider = serviceCollection.BuildServiceProvider();
            var actionContext   = GetActionContext(serviceProvider, routeData: null);

            factory
            .Setup(f => f.GetUrlHelper(actionContext))
            .Returns(urlHelper);

            var metadata = _metadata;

            if (metadataProvider == null)
            {
                metadataProvider = _metadataProvider;
            }
            else
            {
                metadata = metadataProvider.GetMetadataForProperty(typeof(string), nameof(string.Length));
            }

            return(new ClientModelValidationContext(
                       actionContext,
                       metadata,
                       metadataProvider,
                       new AttributeDictionary()));
        }
예제 #5
0
        /// <summary>
        /// Creates a <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.
        /// </summary>
        /// <param name="propertyInfo">The <see cref="PropertyInfo"/>.</param>
        /// <returns>A <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.</returns>
        protected virtual PropertyModel CreatePropertyModel(PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                throw new ArgumentNullException(nameof(propertyInfo));
            }

            var attributes = propertyInfo.GetCustomAttributes(inherit: true);


            var modelMetadata = _modelMetadataProvider.GetMetadataForProperty(propertyInfo.DeclaringType, propertyInfo.Name);
            var bindingInfo   = BindingInfo.GetBindingInfo(attributes, modelMetadata);

            if (bindingInfo == null)
            {
                var declaringType = propertyInfo.DeclaringType;
                if (declaringType.IsDefined(typeof(BindPropertyAttribute), inherit: true))
                {
                    // Specify a BindingInfo so that the property is now considered for model binding.
                    bindingInfo = new BindingInfo();
                }
            }

            var propertyModel = new PropertyModel(propertyInfo, attributes)
            {
                PropertyName = propertyInfo.Name,
                BindingInfo  = bindingInfo,
            };

            return(propertyModel);
        }
예제 #6
0
        private void ValidateIfRequired <TKey>(List <ResourceForSave> entities, Expression <Func <ResourceForSave, TKey> > selector, string visibility)
        {
            if (visibility == Visibility.Required && !ModelState.HasReachedMaxErrors)
            {
                Func <ResourceForSave, TKey> getPropValue = selector.Compile(); // The function to access the property value

                foreach (var(entity, index) in entities.Select((e, i) => (e, i)))
                {
                    if (getPropValue(entity) == null)
                    {
                        string propName        = (selector.Body as MemberExpression).Member.Name; // The name of the property we're validating
                        string path            = $"[{index}].{propName}";
                        string propDisplayName = _modelMetadataProvider.GetMetadataForProperty(typeof(ResourceForSave), propName)? .DisplayName;
                        string errorMsg        = _localizer[nameof(RequiredAttribute), propDisplayName];

                        ModelState.AddModelError(path, errorMsg);

                        if (ModelState.HasReachedMaxErrors)
                        {
                            // No need to keep going forever
                            break;
                        }
                    }
                }
            }
        }
        public static HtmlString DisplayName(this object model, string propertyName, IModelMetadataProvider modelMetadataProvider)
        {
            Type type          = ModelType(model);
            var  modelMetadata = modelMetadataProvider.GetMetadataForProperty(type, propertyName);
            var  value         = modelMetadata.DisplayName ?? modelMetadata.PropertyName;

            return(new HtmlString(HtmlEncoder.Default.Encode(value)));
        }
		private static ModelMetadata GetMetadataFromProvider(Func<object> modelAccessor, Type modelType, string propertyName, Type containerType, IModelMetadataProvider provider)
		{
			if (containerType != null && !string.IsNullOrWhiteSpace(propertyName))
			{
				return provider.GetMetadataForProperty(modelAccessor, containerType, propertyName);
			}

			return provider.GetMetadataForType(modelAccessor, modelType);
		}
예제 #9
0
        private static ModelMetadata GetMetadataFromProvider(Func <object> modelAccessor, Type modelType, string propertyName, Type containerType, IModelMetadataProvider provider)
        {
            if (containerType != null && !string.IsNullOrWhiteSpace(propertyName))
            {
                return(provider.GetMetadataForProperty(modelAccessor, containerType, propertyName));
            }

            return(provider.GetMetadataForType(modelAccessor, modelType));
        }
예제 #10
0
        protected override async Task SaveValidateAsync(List <UserForSave> entities)
        {
            // Hash the indices for performance
            var indices = entities.ToIndexDictionary();

            // Check that line ids are unique and that they have supplied a RoleId
            var duplicateLineIds = entities
                                   .SelectMany(e => e.Roles) // All lines
                                   .Where(e => e.Id != 0)
                                   .GroupBy(e => e.Id)
                                   .Where(g => g.Count() > 1)        // Duplicate Ids
                                   .SelectMany(g => g)
                                   .ToDictionary(e => e, e => e.Id); // to dictionary

            foreach (var entity in entities)
            {
                var lineIndices = entity.Roles.ToIndexDictionary();
                foreach (var line in entity.Roles)
                {
                    if (duplicateLineIds.ContainsKey(line))
                    {
                        // This error indicates a bug
                        var index     = indices[entity];
                        var lineIndex = lineIndices[line];
                        var id        = duplicateLineIds[line];
                        ModelState.AddModelError($"[{index}].{nameof(entity.Roles)}[{lineIndex}].{nameof(entity.Id)}",
                                                 _localizer["Error_TheEntityWithId0IsSpecifiedMoreThanOnce", id]);
                    }

                    if (line.RoleId == null)
                    {
                        var index           = indices[entity];
                        var lineIndex       = lineIndices[line];
                        var propName        = nameof(RoleMembershipForSave.RoleId);
                        var propDisplayName = _metadataProvider.GetMetadataForProperty(typeof(RoleMembershipForSave), propName)?.DisplayName ?? propName;
                        ModelState.AddModelError($"[{index}].{nameof(entity.Roles)}[{lineIndex}].{nameof(RoleMembershipForSave.RoleId)}",
                                                 _localizer[nameof(RequiredAttribute), propDisplayName]);
                    }
                }
            }

            // No need to invoke SQL if the model state is full of errors
            if (ModelState.HasReachedMaxErrors)
            {
                return;
            }

            // SQL validation
            int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount;
            var sqlErrors           = await _appRepo.Users_Validate__Save(entities, top : remainingErrorCount);

            // Add errors to model state
            ModelState.AddLocalizedErrors(sqlErrors, _localizer);
        }
예제 #11
0
        protected override AbstractDataGrid GetImportTemplate()
        {
            // Get the properties of the DTO for Save, excluding Id or EntityState
            var type  = typeof(MeasurementUnitForSave);
            var props = type.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);

            // The result that will be returned
            var result = new AbstractDataGrid(props.Length, 1);

            // Add the header
            var header = result[result.AddRow()];
            int i      = 0;

            foreach (var prop in props)
            {
                var display = _metadataProvider.GetMetadataForProperty(type, prop.Name)?.DisplayName ?? prop.Name;
                if (display != Constants.Hidden)
                {
                    header[i++] = AbstractDataCell.Cell(display);
                }
            }

            return(result);
        }
예제 #12
0
        protected override AbstractDataGrid GetImportTemplate()
        {
            // Get the properties of the DTO for Save, excluding Id or EntityState
            var custodyType  = typeof(CustodyForSave);
            var agentType    = typeof(AgentForSave);
            var custodyProps = custodyType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            var agentProps   = agentType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly);
            var props        = custodyProps.Union(agentProps);

            if (ViewId() == ORGANIZATION)
            {
                // For organizations, some properties are left blank
                var exemptProperties = new string[] { nameof(Agent.Title), nameof(Agent.Title2), nameof(Agent.Gender) };
                props.Where(p => !exemptProperties.Contains(p.Name));
            }

            var propsArray = props.ToArray();

            // The result that will be returned
            var result = new AbstractDataGrid(propsArray.Length, 1);

            // Add the header
            var header = result[result.AddRow()];
            int i      = 0;

            foreach (var prop in props)
            {
                var display = _metadataProvider.GetMetadataForProperty(agentType, prop.Name)?.DisplayName ?? prop.Name;
                if (display != Constants.Hidden)
                {
                    header[i++] = AbstractDataCell.Cell(display);
                }
            }

            return(result);
        }
        // For any complex types that are bound from value providers, set the prefix
        // to the empty prefix by default. This makes binding much more predictable
        // and describable via ApiExplorer

        // internal for testing
        internal void InferBoundPropertyModelPrefixes(ControllerModel controllerModel)
        {
            foreach (var property in controllerModel.ControllerProperties)
            {
                if (property.BindingInfo != null &&
                    property.BindingInfo.BinderModelName == null &&
                    property.BindingInfo.BindingSource != null &&
                    !property.BindingInfo.BindingSource.IsGreedy)
                {
                    var metadata = _modelMetadataProvider.GetMetadataForProperty(
                        controllerModel.ControllerType,
                        property.PropertyInfo.Name);
                    if (metadata.IsComplexType)
                    {
                        property.BindingInfo.BinderModelName = string.Empty;
                    }
                }
            }
        }
예제 #14
0
        // An IModelMetadataProvider is not required unless this method is called. Therefore other methods in this
        // class lack [NotNull] attributes for their corresponding parameter.
        private static ModelMetadata GetMetadataFromProvider(Func <object> modelAccessor,
                                                             Type modelType,
                                                             string propertyName,
                                                             object container,
                                                             Type containerType,
                                                             [NotNull] IModelMetadataProvider metadataProvider)
        {
            if (containerType != null && !string.IsNullOrEmpty(propertyName))
            {
                var metadata =
                    metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName);
                if (metadata != null)
                {
                    metadata.Container = container;
                }

                return(metadata);
            }

            return(metadataProvider.GetMetadataForType(modelAccessor, modelType));
        }
예제 #15
0
        /// <summary>
        /// Creates a <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.
        /// </summary>
        /// <param name="propertyInfo">The <see cref="PropertyInfo"/>.</param>
        /// <returns>A <see cref="PropertyModel"/> for the given <see cref="PropertyInfo"/>.</returns>
        protected virtual PropertyModel CreatePropertyModel(PropertyInfo propertyInfo)
        {
            if (propertyInfo == null)
            {
                throw new ArgumentNullException(nameof(propertyInfo));
            }

            var attributes = propertyInfo.GetCustomAttributes(inherit: true);


            var modelMetadata = _modelMetadataProvider.GetMetadataForProperty(propertyInfo.DeclaringType, propertyInfo.Name);
            var bindingInfo   = BindingInfo.GetBindingInfo(attributes, modelMetadata);

            var propertyModel = new PropertyModel(propertyInfo, attributes)
            {
                PropertyName = propertyInfo.Name,
                BindingInfo  = bindingInfo,
            };

            return(propertyModel);
        }
        /// <summary>
        /// Creates a <see cref="PagePropertyModel"/> for the <paramref name="property"/>.
        /// </summary>
        /// <param name="property">The <see cref="PropertyInfo"/>.</param>
        /// <returns>The <see cref="PagePropertyModel"/>.</returns>
        protected virtual PagePropertyModel CreatePropertyModel(PropertyInfo property)
        {
            if (property == null)
            {
                throw new ArgumentNullException(nameof(property));
            }

            var propertyAttributes = property.GetCustomAttributes(inherit: true);

            // BindingInfo for properties can be either specified by decorating the property with binding-specific attributes.
            // ModelMetadata also adds information from the property's type and any configured IBindingMetadataProvider.
            var propertyMetadata = _modelMetadataProvider.GetMetadataForProperty(property.DeclaringType, property.Name);
            var bindingInfo      = BindingInfo.GetBindingInfo(propertyAttributes, propertyMetadata);

            if (bindingInfo == null)
            {
                // Look for BindPropertiesAttribute on the handler type if no BindingInfo was inferred for the property.
                // This allows a user to enable model binding on properties by decorating the controller type with BindPropertiesAttribute.
                var declaringType           = property.DeclaringType;
                var bindPropertiesAttribute = declaringType.GetCustomAttribute <BindPropertiesAttribute>(inherit: true);
                if (bindPropertiesAttribute != null)
                {
                    var requestPredicate = bindPropertiesAttribute.SupportsGet ? _supportsAllRequests : _supportsNonGetRequests;
                    bindingInfo = new BindingInfo
                    {
                        RequestPredicate = requestPredicate,
                    };
                }
            }

            var model = new PagePropertyModel(property, propertyAttributes)
            {
                PropertyName = property.Name,
                BindingInfo  = bindingInfo,
            };

            return(model);
        }
예제 #17
0
        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));
            }
        }
예제 #18
0
        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);
                    }
                }
            }
        }
예제 #19
0
        protected override async Task ValidateAsync(List <LocalUserForSave> entities)
        {
            // For changing pictures, only one user at a time is allowed
            var usersWithUpdatedImgIds = entities.Where(e => e.Image != null);

            if (usersWithUpdatedImgIds.Count() > 1)
            {
                throw new BadRequestException("This API does not support changing pictures for more than one employee at a time");
            }

            // Hash the indices for performance
            var indices = entities.ToIndexDictionary();

            // Check that Ids make sens {e in relation to EntityState, and that no entity is DELETED
            // All these errors indicate a bug
            foreach (var entity in entities)
            {
                if (entity.EntityState == EntityStates.Deleted)
                {
                    // Won't be supported for this API
                    var index = indices[entity];
                    ModelState.AddModelError($"[{index}].{nameof(entity.EntityState)}", _localizer["Error_Deleting0IsNotSupportedFromThisAPI", _localizer["LocalUsers"]]);
                }
            }

            // Check that Ids are unique
            var duplicateIds = entities.Where(e => e.Id != null).GroupBy(e => e.Id.Value).Where(g => g.Count() > 1);

            foreach (var groupWithDuplicateIds in duplicateIds)
            {
                foreach (var entity in groupWithDuplicateIds)
                {
                    // This error indicates a bug
                    var index = indices[entity];
                    ModelState.AddModelError($"[{index}].{nameof(entity.Id)}",
                                             _localizer["Error_TheEntityWithId0IsSpecifiedMoreThanOnce", entity.Id]);
                }
            }

            // Check that line ids are unique and that they have supplied a RoleId
            var duplicateLineIds = entities.SelectMany(e => e.Roles)                                            // All lines
                                   .Where(e => e.Id != null).GroupBy(e => e.Id.Value).Where(g => g.Count() > 1) // Duplicate Ids
                                   .SelectMany(g => g).ToDictionary(e => e, e => e.Id.Value);                   // to dictionary

            foreach (var entity in entities)
            {
                var lineIndices = entity.Roles.ToIndexDictionary();
                foreach (var line in entity.Roles)
                {
                    if (duplicateLineIds.ContainsKey(line))
                    {
                        // This error indicates a bug
                        var index     = indices[entity];
                        var lineIndex = lineIndices[line];
                        var id        = duplicateLineIds[line];
                        ModelState.AddModelError($"[{index}].{nameof(entity.Roles)}[{lineIndex}].{nameof(entity.Id)}",
                                                 _localizer["Error_TheEntityWithId0IsSpecifiedMoreThanOnce", id]);
                    }

                    if (line.RoleId == null)
                    {
                        var index           = indices[entity];
                        var lineIndex       = lineIndices[line];
                        var propName        = nameof(RoleMembershipForSave.RoleId);
                        var propDisplayName = _metadataProvider.GetMetadataForProperty(typeof(RoleMembershipForSave), propName)?.DisplayName ?? propName;
                        ModelState.AddModelError($"[{index}].{nameof(entity.Roles)}[{lineIndex}].{nameof(RoleMembershipForSave.RoleId)}",
                                                 _localizer[nameof(RequiredAttribute), propDisplayName]);
                    }
                }
            }

            // No need to invoke SQL if the model state is full of errors
            if (ModelState.HasReachedMaxErrors)
            {
                return;
            }

            // Perform SQL-side validation
            DataTable LocalUsersTable = LocalUsersDataTable(entities);
            var       LocalUsersTvp   = new SqlParameter("LocalUsers", LocalUsersTable)
            {
                TypeName = $"dbo.{nameof(LocalUserForSave)}List", SqlDbType = SqlDbType.Structured
            };

            var       rolesHeaderIndices = indices.Keys.Select(LocalUser => (LocalUser.Roles, indices[LocalUser]));
            DataTable rolesTable         = DataTableWithHeaderIndex(rolesHeaderIndices, e => e.EntityState != null);
            var       rolesTvp           = new SqlParameter("Roles", rolesTable)
            {
                TypeName = $"dbo.{nameof(RoleMembershipForSave)}List", SqlDbType = SqlDbType.Structured
            };

            int remainingErrorCount = ModelState.MaxAllowedErrors - ModelState.ErrorCount;

            // (1) Code must be unique
            var sqlErrors = await _db.Validation.FromSql($@"
    SET NOCOUNT ON;
	DECLARE @ValidationErrors [dbo].[ValidationErrorList];
	DECLARE @Now DATETIMEOFFSET(7) = SYSDATETIMEOFFSET();

    INSERT INTO @ValidationErrors([Key], [ErrorName])
    SELECT '[' + CAST([Index] AS NVARCHAR(255)) + '].Id' As [Key], N'Error_CannotModifyInactiveItem' As [ErrorName]
    FROM @LocalUsers
    WHERE Id IN (SELECT Id from [dbo].[LocalUsers] WHERE IsActive = 0)
	OPTION(HASH JOIN);

    INSERT INTO @ValidationErrors([Key], [ErrorName], [Argument1])
    SELECT '[' + CAST([Index] AS NVARCHAR(255)) + '].Id' As [Key], N'Error_TheId0WasNotFound' As [ErrorName], CAST([Id] As NVARCHAR(255)) As [Argument1]
    FROM @LocalUsers
    WHERE Id Is NOT NULL
	AND Id NOT IN (SELECT Id from [dbo].[LocalUsers])
	OPTION(HASH JOIN);
		
	-- Email must not be already in the back end
	INSERT INTO @ValidationErrors([Key], [ErrorName], [Argument1], [Argument2], [Argument3], [Argument4], [Argument5]) 
	SELECT '[' + CAST(FE.[Index] AS NVARCHAR(255)) + '].Email' As [Key], N'Error_TheEmail0IsUsed' As [ErrorName],
		FE.Email AS Argument1, NULL AS Argument2, NULL AS Argument3, NULL AS Argument4, NULL AS Argument5
	FROM @LocalUsers FE 
	JOIN [dbo].LocalUsers BE ON FE.Email = BE.Email
	AND ((FE.[EntityState] = N'Inserted') OR (FE.Id <> BE.Id))
	OPTION(HASH JOIN);

	-- Email must not be duplicated in the uploaded list
	INSERT INTO @ValidationErrors([Key], [ErrorName], [Argument1], [Argument2], [Argument3], [Argument4], [Argument5]) 
	SELECT '[' + CAST([Index] AS NVARCHAR(255)) + '].Email' As [Key], N'Error_TheEmail0IsDuplicated' As [ErrorName],
		[Email] AS Argument1, NULL AS Argument2, NULL AS Argument3, NULL AS Argument4, NULL AS Argument5
	FROM @LocalUsers
	WHERE [Email] IN (
		SELECT [Email]
		FROM @LocalUsers
		WHERE [Email] IS NOT NULL
		GROUP BY [Email]
		HAVING COUNT(*) > 1
	) OPTION(HASH JOIN);

    -- No email can change 
	INSERT INTO @ValidationErrors([Key], [ErrorName], [Argument1], [Argument2], [Argument3], [Argument4], [Argument5]) 
	SELECT '[' + CAST(FE.[Index] AS NVARCHAR(255)) + '].Email' As [Key], N'Error_TheEmailCannotBeModified' As [ErrorName],
		NULL AS Argument1, NULL AS Argument2, NULL AS Argument3, NULL AS Argument4, NULL AS Argument5
	FROM @LocalUsers FE 
	JOIN [dbo].LocalUsers BE ON FE.Id = BE.Id
	AND ((FE.[EntityState] = N'Updated') AND (FE.Email <> BE.Email))
	OPTION(HASH JOIN);

	-- No inactive role
	INSERT INTO @ValidationErrors([Key], [ErrorName], [Argument1], [Argument2], [Argument3], [Argument4], [Argument5]) 
	SELECT '[' + CAST(P.[HeaderIndex] AS NVARCHAR(255)) + '].Roles[' + 
				CAST(P.[Index] AS NVARCHAR(255)) + '].RoleId' As [Key], N'Error_TheView0IsInactive' As [ErrorName],
				P.[RoleId] AS Argument1, NULL AS Argument2, NULL AS Argument3, NULL AS Argument4, NULL AS Argument5
	FROM @Roles P
	WHERE P.RoleId NOT IN (
		SELECT [Id] FROM dbo.[Roles] WHERE IsActive = 1
		)
	AND (P.[EntityState] IN (N'Inserted', N'Updated'));
    SELECT TOP {remainingErrorCount} * FROM @ValidationErrors;
", LocalUsersTvp, rolesTvp).ToListAsync();

            // Loop over the errors returned from SQL and add them to ModelState
            foreach (var sqlError in sqlErrors)
            {
                var formatArguments = sqlError.ToFormatArguments();

                string key          = sqlError.Key;
                string errorMessage = _localizer[sqlError.ErrorName, formatArguments];

                ModelState.AddModelError(key: key, errorMessage: errorMessage);
            }
        }
예제 #20
0
        private static ClientModelValidationContext GetValidationContext(
            IUrlHelper urlHelper,
            IStringLocalizerFactory localizerFactory = null,
            IModelMetadataProvider metadataProvider = null)
        {
            var serviceCollection = GetServiceCollection(localizerFactory);
            var factory = new Mock<IUrlHelperFactory>(MockBehavior.Strict);
            serviceCollection.AddSingleton<IUrlHelperFactory>(factory.Object);

            var serviceProvider = serviceCollection.BuildServiceProvider();
            var actionContext = GetActionContext(serviceProvider, routeData: null);

            factory
                .Setup(f => f.GetUrlHelper(actionContext))
                .Returns(urlHelper);

            var metadata = _metadata;
            if (metadataProvider == null)
            {
                metadataProvider = _metadataProvider;
            }
            else
            {
                metadata = metadataProvider.GetMetadataForProperty(typeof(string), nameof(string.Length));
            }

            return new ClientModelValidationContext(
                actionContext,
                metadata,
                metadataProvider,
                new AttributeDictionary());
        }