public IDictionary <string, string> GetValidationAttributes( Type modelType, string modelPath, PropertyInfo property, Func <Type, object> services, DryvOptions options) { if (modelPath == null) { modelPath = string.Empty; } var rules = from rule in modelType.GetRulesForProperty(property, modelPath) where rule.Rule.IsEnabled(services) && rule.Rule.EvaluationLocation.HasFlag(RuleEvaluationLocation.Client) select rule; var translatedRules = rules.Translate( services, options, modelPath, modelType); return(this.CreateValidationAttributes(modelType, property, translatedRules)); }
private void ValidateSingleItem( object model, object rootModel, string path, IList <DryvResult> result, ICollection <object> processed, Func <Type, object> services, IDictionary <object, object> cache, DryvOptions options) { if (model == null || processed.Contains(model)) { return; } processed.Add(model); ValidateMethods.GetOrAdd(model.GetType(), this.ruleCompiler.CreateValidateMethods)( this, model, rootModel, path, result, processed, services, cache, options); }
internal IEnumerable <DryvResultMessage> ValidateProperty( object currentModel, object rootModel, PropertyInfo property, Func <Type, object> services, IDictionary <object, object> cache, DryvOptions options) { var disablingRules = this.GetModelsAndRules(currentModel, rootModel, property, services, cache, true, false, RuleType.Disabling); if (disablingRules.Any(rule => this.ruleEvaluator.IsDisabled(rule.Value, rule.Key, services))) { yield break; } var rules = this.GetModelsAndRules(currentModel, rootModel, property, services, cache, true, false, RuleType.Default); foreach (var rule in rules) { var result = this.ruleEvaluator.Validate(rule.Value, rule.Key, services); if (result.IsSuccess()) { continue; } yield return(result); if (options.BreakOnFirstValidationError) { yield break; } } }
public static IDryvBuilder Configure(IDependencyContainer container, Action <DryvOptions> setupAction = null) { if (container == null) { throw new ArgumentNullException(nameof(container)); } ModelValidatorProviders.Providers.Add(new DryvModelValidatorProvider()); var options = new DryvOptions(); setupAction?.Invoke(options); container.RegisterSingleton(typeof(IDryvClientModelValidator), typeof(DryvClientModelValidator)); container.RegisterSingleton(typeof(ITranslator), typeof(JavaScriptTranslator)); container.RegisterSingleton(typeof(ITranslatorProvider), typeof(TranslatorProvider)); container.RegisterInstance(typeof(DryvOptions), options); return(new DryvBuilder(container) .AddTranslator <ObjectTranslator>() .AddTranslator <DryvResultTranslator>() .AddTranslator <StringTranslator>() .AddTranslator <EnumerableTranslator>() .AddTranslator <RegexTranslator>()); }
public static IDryvMvcBuilder AddDryv(this IMvcBuilder mvcBuilder, Action <DryvOptions> setupAction = null) { var options = new DryvOptions(); setupAction?.Invoke(options); // As long as mvc validation is not async, we'll // run the async validation from an action attribute. mvcBuilder.AddMvcOptions(opts => opts.Filters.Add <DryvValidationFilterAttribute>()); return(RegsterServices(mvcBuilder.Services, options)); }
internal async Task ValidatePath( object input, object rootModel, PropertyInfo property, object parentModel, string path, IList <DryvResult> result, ICollection <object> processed, Func <Type, object> services, IDictionary <object, object> cache, DryvOptions options) { if (parentModel != null && property != null) { var disablingRules = this.GetModelsAndRules(parentModel, rootModel, property, services, cache, true, true, RuleType.Disabling); var disabled = await Task.WhenAll(from modelRule in disablingRules select this.ruleEvaluator.IsDisabledAsync(modelRule.Value, modelRule.Key, services)); if (disabled.Any(v => v)) { return; } } if (input is IEnumerable items) { string suffix; if (path.EndsWith(".")) { path = path.TrimEnd('.'); suffix = "."; } else { suffix = string.Empty; } var i = 0; foreach (var model in items.OfType <object>()) { this.ValidateSingleItem(model, rootModel, $"{path}[{i++}]{suffix}", result, processed, services, cache, options); } } else { this.ValidateSingleItem(input, rootModel, path, result, processed, services, cache, options); } }
public static IDryvBuilder AddDryv(this IServiceCollection services, Action <DryvOptions> setupAction) { var options = new DryvOptions(); setupAction?.Invoke(options); services.TryAddSingleton <IDryvClientModelValidator, DryvClientModelValidator>(); services.AddSingleton <ITranslator, JavaScriptTranslator>(); services.AddSingleton <ITranslatorProvider, TranslatorProvider>(); services.AddSingleton(Options.Create(options)); services.AddScoped <IModelProvider, ModelProvider>(); services.AddSingleton <IObjectModelValidator, ObjectModelValidator>(s => new ObjectModelValidator( s.GetRequiredService <IModelMetadataProvider>(), s.GetRequiredService <IOptions <MvcOptions> >().Value.ModelValidatorProviders)); return(new DryvBuilder(services) .AddTranslator <ObjectTranslator>() .AddTranslator <DryvResultTranslator>() .AddTranslator <StringTranslator>() .AddTranslator <EnumerableTranslator>() .AddTranslator <RegexTranslator>()); }
public async Task <IList <DryvResult> > Validate(object model, DryvOptions options, Func <Type, object> services = null) { var results = await this.ValidateCore(model, services ?? (t => null), new Dictionary <object, object>(), options); return(results.Where(r => r.Message.Any(vr => !vr.IsSuccess())).Take(1).ToList()); }
private async Task <IEnumerable <DryvResult> > ValidateCore(object model, Func <Type, object> services, IDictionary <object, object> cache, DryvOptions options) { var result = new List <DryvResult>(); if (model == null) { return(result); } await this.ValidatePath(model, model, null, null, string.Empty, result, new HashSet <object>(), services, cache, options); return(result); }
public static IEnumerable <string> Translate(this IEnumerable <DryvRuleNode> rules, Func <Type, object> objectProvider, DryvOptions options, string modelPath, Type modelType) { var translator = objectProvider(typeof(ITranslator)) as ITranslator; return((from r in rules let rule = r.Rule.Translate(translator, options) where rule.TranslationError == null let path = string.IsNullOrWhiteSpace(r.Path) ? r.Path : $".{r.Path}" let preevaluationOptions = rule.PreevaluationOptionTypes.Select(objectProvider).Union(new[] { path }).ToArray() select rule.TranslatedValidationExpression(preevaluationOptions)).ToList()); }
private static DryvRuleDefinition Translate(this DryvRuleDefinition rule, ITranslator translator, DryvOptions options) { if (rule.TranslatedValidationExpression != null || rule.TranslationError != null) { return(rule); } try { var translatedRule = translator.Translate(rule.ValidationExpression, rule.PropertyExpression); rule.TranslatedValidationExpression = translatedRule.Factory; rule.PreevaluationOptionTypes = translatedRule.OptionTypes; } catch (DryvException ex) { switch (options.TranslationErrorBehavior) { case TranslationErrorBehavior.ValidateOnServer: rule.TranslatedValidationExpression = null; rule.PreevaluationOptionTypes = null; rule.TranslationError = ex; break; default: throw; } } return(rule); }
public DryvRuleTranslator(DryvOptions options, Func <Type, object> serviceProvider) { this.options = options; this.serviceProvider = serviceProvider; }
private static IDryvMvcBuilder RegsterServices(this IServiceCollection services, DryvOptions options) { services.TryAddSingleton <DryvClientValidationLoader>(); services.TryAddSingleton <DryvEndpointRouteBuilderProvider>(); services.TryAddSingleton(typeof(IDryvClientValidationFunctionWriter), options.ClientFunctionWriterType); services.TryAddSingleton <ITranslator, JavaScriptTranslator>(); services.TryAddSingleton <DryvRulesFinder>(); services.TryAddSingleton <DryvValidator>(); services.TryAddSingleton <DryvServerRuleEvaluator>(); services.TryAddSingleton <ITranslatorProvider, TranslatorProvider>(); services.AddSingleton(Options.Create(options)); return(new DryvMvcBuilder(services) .AddTranslator <ObjectTranslator>() .AddTranslator <DryvResultTranslator>() .AddTranslator <StringTranslator>() .AddTranslator <EnumerableTranslator>() .AddTranslator <RegexTranslator>() .AddTranslator <CustomCodeTranslator>()); }