public ValidationRule(string rootType, string property, ModelExpression validationExpression, ModelExpression errorMessageExpression) : base(rootType, property, new Error(GetErrorCode(rootType, property, "Validation"), "Invalid", null), RuleInvocationType.InitNew | RuleInvocationType.PropertyChanged, property) { this.validationExpression = validationExpression; this.errorMessageExpression = errorMessageExpression; Initialize += (s, e) => InitializeExpressions(); }
/// <summary> /// 初始化 /// </summary> /// <param name="expression">属性表达式</param> /// <param name="config">配置</param> public static void Init(ModelExpression expression, SelectConfig config) { new SelectExpressionResolver(expression, config).Init(); }
public async Task ProcessAsync_CallsGeneratorWithExpectedValues_ItemsAndAttribute( IEnumerable <SelectListItem> inputItems, string attributeName, string attributeValue, IEnumerable <SelectListItem> expectedItems) { // Arrange var contextAttributes = new TagHelperAttributeList { // Provided for completeness. Select tag helper does not confirm AllAttributes set is consistent. { attributeName, attributeValue }, }; var originalAttributes = new TagHelperAttributeList { { attributeName, attributeValue }, }; var propertyName = "Property1"; var expectedTagName = "select"; var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: contextAttributes, items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); var metadataProvider = new EmptyModelMetadataProvider(); string model = null; var modelExplorer = metadataProvider.GetModelExplorerForType(typeof(string), model); var htmlGenerator = new Mock <IHtmlGenerator>(MockBehavior.Strict); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator.Object, metadataProvider); // Simulate a (model => model) scenario. E.g. the calling helper may appear in a low-level template. var modelExpression = new ModelExpression(string.Empty, modelExplorer); viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = propertyName; var currentValues = new string[0]; htmlGenerator .Setup(real => real.GetCurrentValues( viewContext, modelExplorer, string.Empty, // expression false)) // allowMultiple .Returns(currentValues) .Verifiable(); htmlGenerator .Setup(real => real.GenerateSelect( viewContext, modelExplorer, null, // optionLabel string.Empty, // expression expectedItems, currentValues, false, // allowMultiple null)) // htmlAttributes .Returns((TagBuilder)null) .Verifiable(); var tagHelper = new SelectTagHelper(htmlGenerator.Object) { For = modelExpression, Items = inputItems, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert htmlGenerator.Verify(); var keyValuePair = Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); var actualCurrentValues = Assert.IsType <CurrentValues>(keyValuePair.Value); Assert.Same(currentValues, actualCurrentValues.Values); }
public async Task ProcessAsync_GeneratesExpectedOutput( object model, Type containerType, Func <object> modelAccessor, NameAndId nameAndId, string ignored) { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes) { { "id", nameAndId.Id }, { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent; var expectedTagName = "not-select"; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer); var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }) { TagMode = TagMode.SelfClosing, }; output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(originalPostContent); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = { { "valid", "from validation attributes" }, } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); var tagHelper = new SelectTagHelper(htmlGenerator) { For = modelExpression, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(TagMode.SelfClosing, output.TagMode); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, output.PostContent.GetContent()); Assert.Equal(expectedTagName, output.TagName); Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); }
public static PropertyInfo GetProperty(this ModelExpression model) { var metadata = model.Metadata; return(metadata.ContainerType.GetProperty(metadata.PropertyName)); }
protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model) { return(IsEnum(model.ModelExplorer) || AreSelectItemsProvided(model.ModelExplorer)); }
protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model) { return(IsRadioGroup(model.ModelExplorer) ? GetAbpRadioInputTagHelper(model) : GetSelectTagHelper(model)); }
void SetRange(ModelExpression minimum, ModelExpression maximum) { this.minExpression = minimum; this.maxExpression = maximum; var minPath = minimum != null ? minimum.Path.Path : ""; var maxPath = maximum != null ? maximum.Path.Path : ""; if (!string.IsNullOrEmpty(minPath) || !string.IsNullOrEmpty(maxPath)) { minPath = minPath.StartsWith("{") ? minPath.Substring(1, minPath.Length - 2) : minPath; maxPath = maxPath.StartsWith("{") ? maxPath.Substring(1, maxPath.Length - 2) : maxPath; Path = "{" + (minPath.Length > 0 && maxPath.Length > 0 ? minPath + "," + maxPath : minPath.Length > 0 ? minPath : maxPath) + "}"; SetPredicates(Property.Name, Path); } }
public ValidationRule(string rootType, string property, string errorName, string[] additionalPredicates, ModelExpression validationExpression, ModelExpression errorMessageExpression) : base(rootType, property, new Error(GetErrorCode(rootType, property, errorName), "Invalid", null), RuleInvocationType.InitNew | RuleInvocationType.PropertyChanged, new string[] { property }.Concat(additionalPredicates).ToArray()) { this.validationExpression = validationExpression; this.errorMessageExpression = errorMessageExpression; Initialize += (s, e) => InitializeExpressions(); }
public async Task ProcessAsync_GeneratesExpectedOutput( object model, Type containerType, Func <object> modelAccessor, string propertyPath, TagHelperOutputContent tagHelperOutputContent) { // Arrange var expectedTagName = "not-label"; var expectedAttributes = new Dictionary <string, string> { { "class", "form-control" }, { "for", tagHelperOutputContent.ExpectedId } }; var metadataProvider = new DataAnnotationsModelMetadataProvider(); // Property name is either nameof(Model.Text) or nameof(NestedModel.Text). var metadata = metadataProvider.GetMetadataForProperty(modelAccessor, containerType, propertyName: "Text"); var modelExpression = new ModelExpression(propertyPath, metadata); var tagHelper = new LabelTagHelper { For = modelExpression, }; var expectedPreContent = "original pre-content"; var expectedPostContent = "original post-content"; var tagHelperContext = new TagHelperContext( allAttributes: new Dictionary <string, object>(), uniqueId: "test", getChildContentAsync: () => Task.FromResult(tagHelperOutputContent.OriginalChildContent)); var htmlAttributes = new Dictionary <string, string> { { "class", "form-control" }, }; var output = new TagHelperOutput(expectedTagName, htmlAttributes) { PreContent = expectedPreContent, PostContent = expectedPostContent, }; // LabelTagHelper checks ContentSet so we don't want to forcibly set it if // tagHelperOutputContent.OriginalContent is going to be null or empty. if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent)) { output.Content = tagHelperOutputContent.OriginalContent; } var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); tagHelper.ViewContext = viewContext; tagHelper.Generator = htmlGenerator; // Act await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent); Assert.Equal(tagHelperOutputContent.ExpectedContent, output.Content); Assert.Equal(expectedPostContent, output.PostContent); Assert.False(output.SelfClosing); Assert.Equal(expectedTagName, output.TagName); }
protected StringLengthAttribute GetStringLengthAttribute(ModelExpression modelExpression) { return(modelExpression.Metadata.ValidatorMetadata.FirstOrDefault(vm => vm is StringLengthAttribute) as StringLengthAttribute); }
protected RequiredAttribute GetRequiredAttribute(ModelExpression modelExpression) { return(modelExpression.Metadata.ValidatorMetadata.FirstOrDefault(vm => vm is RequiredAttribute) as RequiredAttribute); }
/// <summary> /// 初始化 /// </summary> /// <param name="expression">属性表达式</param> /// <param name="config">配置</param> public static void Init(ModelExpression expression, Config config) { new CheckBoxExpressionResolver(expression, config).Init(); }
public static bool IsScalar(this ModelExpression dataSetFor) { return(dataSetFor.Metadata.IsScalar()); }
/// <summary> /// 获取成员 /// </summary> /// <param name="expression">模型表达式</param> /// <returns></returns> public static MemberInfo GetMemberInfo(this ModelExpression expression) { var members = expression.Metadata.ContainerType.GetMember(expression.Metadata.PropertyName); return(members.Length == 0 ? null : members[0]); }
protected override Expression VisitModelMember(ModelExpression.ModelMemberExpression m) { base.VisitModelMember(m); ModelStep step; if (steps.TryGetValue(m.Expression, out step) && !(step.Property is ModelValueProperty)) { // Get the model type of the parent expression var type = step.Property == null ? path.RootType : ((ModelReferenceProperty)step.Property).PropertyType; // Make sure the type of the expression matches the declaring type of the property if (type != m.Property.DeclaringType && !m.Property.DeclaringType.IsSubType(type)) return m; // Determine if the member access represents a property on the model type var property = m.Property; // Create and record a new step var nextStep = step.NextSteps.FirstOrDefault(s => s.Property == property); if (nextStep == null) { nextStep = new ModelStep(path) { Property = property, PreviousStep = step }; step.NextSteps.Add(nextStep); } if (!steps.ContainsKey(m)) steps.Add(m, nextStep); } return m; }
public ValidationRule(string rootType, string property, string errorName, ModelExpression validationExpression, ModelExpression errorMessageExpression) : base(rootType, property, new Error(GetErrorCode(rootType, property, errorName), "Invalid", null), RuleInvocationType.InitNew | RuleInvocationType.PropertyChanged, property) { this.validationExpression = validationExpression; this.errorMessageExpression = errorMessageExpression; Initialize += (s, e) => InitializeExpressions(); }
public async Task ProcessAsync_GeneratesExpectedOutput_WithDisplayName( string displayName, string originalChildContent, string htmlFieldPrefix, string expectedContent, string expectedId) { // Arrange var expectedAttributes = new TagHelperAttributeList { { "for", expectedId } }; var name = nameof(NestedModel.Text); var metadataProvider = new TestModelMetadataProvider(); metadataProvider .ForProperty <NestedModel>(name) .DisplayDetails(metadata => metadata.DisplayName = () => displayName); var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var viewContext = TestableHtmlGenerator.GetViewContext( model: null, htmlGenerator: htmlGenerator, metadataProvider: metadataProvider); var viewData = new ViewDataDictionary <NestedModel>(metadataProvider, viewContext.ModelState); viewData.TemplateInfo.HtmlFieldPrefix = htmlFieldPrefix; viewContext.ViewData = viewData; var containerExplorer = metadataProvider.GetModelExplorerForType(typeof(NestedModel), model: null); var modelExplorer = containerExplorer.GetExplorerForProperty(name); var modelExpression = new ModelExpression(name, modelExplorer); var tagHelper = new LabelTagHelper(htmlGenerator) { For = modelExpression, ViewContext = viewContext, }; var tagHelperContext = new TagHelperContext( tagName: "label", allAttributes: new TagHelperAttributeList(), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( "label", new TagHelperAttributeList(), getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml(originalChildContent); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); // Act await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedContent, HtmlContentUtilities.HtmlContentToString(output.Content)); }
/*========================================================================================================================== | METHOD: INVOKE \-------------------------------------------------------------------------------------------------------------------------*/ /// <summary> /// Provides a dropdown list of metadata associated with the bound property. /// </summary> public IViewComponentResult Invoke( ModelExpression aspFor, string htmlFieldPrefix ) { /*------------------------------------------------------------------------------------------------------------------------ | Establish variables \-----------------------------------------------------------------------------------------------------------------------*/ //### TODO JJC20191119: Ideally, these would be configured as optional parameters. Unfortunately, the tag helper approach //to calling view components doesn't (yet) support optional parameters. These should be reevaluated if that's fixed. For //now, it's not strictly required by current requirements that these be overwritten by the views. var defaultText = "Select one…"; var valueField = nameof(Topic.Title); var textField = nameof(Topic.Title); /*------------------------------------------------------------------------------------------------------------------------ | Get metadata attribute \-----------------------------------------------------------------------------------------------------------------------*/ var modelMetadata = aspFor.Metadata; var currentProperty = modelMetadata.ContainerType.GetProperty(modelMetadata.Name); var propertyAttributes = currentProperty.GetCustomAttributes(typeof(MetadataAttribute), true); var metadataAttribute = propertyAttributes.FirstOrDefault() as MetadataAttribute; var metadataKey = $"Configuration:Metadata:{metadataAttribute?.Key}:LookupList"; /*------------------------------------------------------------------------------------------------------------------------ | Set HTML field prefix \-----------------------------------------------------------------------------------------------------------------------*/ var templateInfo = ViewData.TemplateInfo; if (String.IsNullOrEmpty(templateInfo.HtmlFieldPrefix)) { templateInfo.HtmlFieldPrefix = htmlFieldPrefix; } if (!templateInfo.HtmlFieldPrefix.EndsWith(modelMetadata.Name, StringComparison.InvariantCulture)) { templateInfo.HtmlFieldPrefix = templateInfo.GetFullHtmlFieldName(modelMetadata.Name); } /*------------------------------------------------------------------------------------------------------------------------ | Lookup metadata values \-----------------------------------------------------------------------------------------------------------------------*/ var metadataList = _topicRepository.Load(metadataKey)?.Children?? new TopicCollection(); var selectList = new SelectList(metadataList, valueField, textField, aspFor.Model?.ToString()); /*------------------------------------------------------------------------------------------------------------------------ | Validate metadata \-----------------------------------------------------------------------------------------------------------------------*/ if (metadataAttribute == null) { throw new InvalidOperationException( $"The {aspFor.Metadata.PropertyName} must be decorated with the [Metadata()] attribute." ); } else if (metadataList.Count == 0) { throw new InvalidOperationException( $"The {aspFor.Metadata.PropertyName} is bound to the {metadataAttribute.Key} metadata, but the lookup list " + $"contains no topics." ); } /*------------------------------------------------------------------------------------------------------------------------ | Create view model \-----------------------------------------------------------------------------------------------------------------------*/ var model = new MetadataLookupViewModel() { Options = selectList, DefaultText = defaultText, Value = aspFor.Model?.ToString(), IsRequired = modelMetadata.IsRequired }; /*------------------------------------------------------------------------------------------------------------------------ | Return the corresponding view \-----------------------------------------------------------------------------------------------------------------------*/ return View(model); }
protected virtual async Task ProcessInputGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) { var abpInputTagHelper = _serviceProvider.GetRequiredService <AbpInputTagHelper>(); abpInputTagHelper.AspFor = model; abpInputTagHelper.ViewContext = TagHelper.ViewContext; abpInputTagHelper.DisplayRequiredSymbol = TagHelper.RequiredSymbols ?? true; await abpInputTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag).ConfigureAwait(false); }
public async Task ProcessAsync_WithItems_GeneratesExpectedOutput_DoesNotChangeSelectList( object model, Type containerType, Func <object> modelAccessor, NameAndId nameAndId, string expectedOptions) { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes) { { "id", nameAndId.Id }, { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent + expectedOptions; var expectedTagName = "select"; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var modelExpression = new ModelExpression(nameAndId.Name, modelExplorer); var tagHelperContext = new TagHelperContext( allAttributes: new ReadOnlyTagHelperAttributeList <IReadOnlyTagHelperAttribute>( Enumerable.Empty <IReadOnlyTagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test", getChildContentAsync: () => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); var output = new TagHelperOutput(expectedTagName, originalAttributes) { SelfClosing = true, }; output.PreContent.SetContent(expectedPreContent); output.Content.SetContent(expectedContent); output.PostContent.SetContent(originalPostContent); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = { { "valid", "from validation attributes" }, } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); var items = new SelectList(new[] { "", "outer text", "inner text", "other text" }); var savedDisabled = items.Select(item => item.Disabled).ToList(); var savedGroup = items.Select(item => item.Group).ToList(); var savedSelected = items.Select(item => item.Selected).ToList(); var savedText = items.Select(item => item.Text).ToList(); var savedValue = items.Select(item => item.Value).ToList(); var tagHelper = new SelectTagHelper(htmlGenerator) { For = modelExpression, Items = items, ViewContext = viewContext, }; // Act await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.True(output.SelfClosing); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, output.PostContent.GetContent()); Assert.Equal(expectedTagName, output.TagName); Assert.NotNull(viewContext.FormContext?.FormData); Assert.Single( viewContext.FormContext.FormData, entry => entry.Key == SelectTagHelper.SelectedValuesFormDataKey); Assert.Equal(savedDisabled, items.Select(item => item.Disabled)); Assert.Equal(savedGroup, items.Select(item => item.Group)); Assert.Equal(savedSelected, items.Select(item => item.Selected)); Assert.Equal(savedText, items.Select(item => item.Text)); Assert.Equal(savedValue, items.Select(item => item.Value)); }
public async Task ProcessAsync_GeneratesExpectedOutput( object model, Type containerType, Func <object> modelAccessor, string propertyPath, TagHelperOutputContent tagHelperOutputContent) { // Arrange var expectedTagName = "not-label"; var expectedAttributes = new TagHelperAttributeList { { "class", "form-control" }, { "for", tagHelperOutputContent.ExpectedId } }; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var htmlGenerator = new TestableHtmlGenerator(metadataProvider); var modelExpression = new ModelExpression(propertyPath, modelExplorer); var tagHelper = new LabelTagHelper(htmlGenerator) { For = modelExpression, }; var expectedPreContent = "original pre-content"; var expectedPostContent = "original post-content"; var tagHelperContext = new TagHelperContext( allAttributes: new TagHelperAttributeList(), items: new Dictionary <object, object>(), uniqueId: "test"); var htmlAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var output = new TagHelperOutput( expectedTagName, htmlAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml(tagHelperOutputContent.OriginalChildContent); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); output.PreContent.AppendHtml(expectedPreContent); output.PostContent.AppendHtml(expectedPostContent); // LabelTagHelper checks IsContentModified so we don't want to forcibly set it if // tagHelperOutputContent.OriginalContent is going to be null or empty. if (!string.IsNullOrEmpty(tagHelperOutputContent.OriginalContent)) { output.Content.AppendHtml(tagHelperOutputContent.OriginalContent); } var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); tagHelper.ViewContext = viewContext; // Act await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal( tagHelperOutputContent.ExpectedContent, HtmlContentUtilities.HtmlContentToString(output.Content)); Assert.Equal(expectedPostContent, output.PostContent.GetContent()); Assert.Equal(TagMode.StartTagAndEndTag, output.TagMode); Assert.Equal(expectedTagName, output.TagName); }
public async Task <IHtmlContent> Invoke(ModelExpression expression, O options, ContextualizedHelpers helpers, string overridePrefix = null, object data = null) { if (expression == null) { throw new ArgumentNullException(nameof(expression)); } if (options == null) { throw new ArgumentNullException(nameof(options)); } ModelExplorer model = expression.ModelExplorer; if (Type == TemplateType.Partial) { if (helpers == null) { throw new ArgumentNullException(nameof(helpers)); } var h = helpers.Html; var origVd = helpers.Context.ViewData; if (h == null) { throw new ArgumentNullException(nameof(h)); } var fatherPrefix = (origVd[RenderingScope.Field] as RenderingScope)?.FatherPrefix; var vd = new ViewDataDictionary <object>(origVd); vd.Model = model.Model; vd.ModelExplorer = model.GetExplorerForModel(model.Model); if (overridePrefix != null) { vd.TemplateInfo.HtmlFieldPrefix = combinePrefixes(overridePrefix, expression.Name); } else { vd.TemplateInfo.HtmlFieldPrefix = origVd.GetFullHtmlFieldName(combinePrefixes(fatherPrefix, expression.Name)); } vd["Options"] = options; vd["ContextualizedHelpers"] = helpers; vd["LocalizerFactory"] = helpers.LocalizerFactory; if (data != null) { vd["ExtraData"] = data; } vd.Remove(RenderingScope.Field); return(await h.PartialAsync(TemplateName, model.Model, vd)); } else if (Type == TemplateType.ViewComponent) { if (helpers == null) { throw new ArgumentNullException(nameof(helpers)); } var origVd = helpers.Context.ViewData; var fatherPrefix = (origVd[RenderingScope.Field] as RenderingScope)?.FatherPrefix; if (data != null) { return(await helpers.Component.InvokeAsync(TemplateName, new { model = model.Model, options = options, prefix = overridePrefix != null ? combinePrefixes(overridePrefix, expression.Name) : origVd.GetFullHtmlFieldName(combinePrefixes(fatherPrefix, expression.Name)), modelState = origVd.ModelState, extraData = data })); } else { return(await helpers.Component.InvokeAsync(TemplateName, new { model = model.Model, options = options, prefix = overridePrefix != null ? combinePrefixes(overridePrefix, expression.Name) : origVd.GetFullHtmlFieldName(combinePrefixes(fatherPrefix, expression.Name)), modelState = origVd.ModelState })); } } else if (Type == TemplateType.InLine) { var res = helpers.GetCachedTemplateResult(this); if (res != null) { return(res); } using (await Lock.LockAsync()) { originalContext.HttpContext = helpers.CurrentHttpContext; var origVd = originalContext.ViewData; using (new TagHelpersProviderContext(OriginalProvider, originalContext)) { using (new RenderingScope( expression.Model, overridePrefix != null ? combinePrefixes(overridePrefix, expression.Name) : helpers.Context.ViewData.GetFullHtmlFieldName(expression.Name), origVd, options)) { return(FTemplate(model.Model, default(O), helpers)); } } } } else { if (helpers == null) { throw new ArgumentNullException(nameof(helpers)); } var origVd = helpers.Context.ViewData; using (new RenderingScope( expression.Model, origVd, expression.Name, options)) { return(FTemplate(model.Model, options, helpers)); } } }
/// <summary> /// 初始化 /// </summary> /// <param name="expression">属性表达式</param> /// <param name="config">配置</param> public static void Init(ModelExpression expression, TextBoxConfig config) { new TextBoxExpressionResolver(expression, config).Init(); }
protected TagHelperOutput GenerateTagHelperCore(ModelExpression f, TagHelper tagHelper, string tagName, TagMode tagMode) => GenerateTagHelperCore(f, tagHelper, tagName, tagMode, "text", styles.FormControl);
public async Task ProcessAsyncInTemplate_WithItems_GeneratesExpectedOutput_DoesNotChangeSelectList( object model, Type containerType, Func <object> modelAccessor, NameAndId nameAndId, string expectedOptions) { // Arrange var originalAttributes = new TagHelperAttributeList { { "class", "form-control" }, }; var originalPostContent = "original content"; var expectedAttributes = new TagHelperAttributeList(originalAttributes) { { "id", nameAndId.Id }, { "name", nameAndId.Name }, { "valid", "from validation attributes" }, }; var expectedPreContent = "original pre-content"; var expectedContent = "original content"; var expectedPostContent = originalPostContent + expectedOptions; var expectedTagName = "select"; var metadataProvider = new TestModelMetadataProvider(); var containerMetadata = metadataProvider.GetMetadataForType(containerType); var containerExplorer = metadataProvider.GetModelExplorerForType(containerType, model); var propertyMetadata = metadataProvider.GetMetadataForProperty(containerType, "Text"); var modelExplorer = containerExplorer.GetExplorerForExpression(propertyMetadata, modelAccessor()); var modelExpression = new ModelExpression(name: string.Empty, modelExplorer: modelExplorer); var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()), items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( expectedTagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.AppendHtml("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }) { TagMode = TagMode.SelfClosing, }; output.PreContent.AppendHtml(expectedPreContent); output.Content.AppendHtml(expectedContent); output.PostContent.AppendHtml(originalPostContent); var htmlGenerator = new TestableHtmlGenerator(metadataProvider) { ValidationAttributes = { { "valid", "from validation attributes" }, } }; var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator, metadataProvider); viewContext.ViewData.TemplateInfo.HtmlFieldPrefix = nameAndId.Name; var items = new SelectList(new[] { "", "outer text", "inner text", "other text" }); var savedDisabled = items.Select(item => item.Disabled).ToList(); var savedGroup = items.Select(item => item.Group).ToList(); var savedSelected = items.Select(item => item.Selected).ToList(); var savedText = items.Select(item => item.Text).ToList(); var savedValue = items.Select(item => item.Value).ToList(); var tagHelper = new SelectTagHelper(htmlGenerator) { For = modelExpression, Items = items, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert Assert.Equal(TagMode.SelfClosing, output.TagMode); Assert.Equal(expectedAttributes, output.Attributes); Assert.Equal(expectedPreContent, output.PreContent.GetContent()); Assert.Equal(expectedContent, output.Content.GetContent()); Assert.Equal(expectedPostContent, HtmlContentUtilities.HtmlContentToString(output.PostContent)); Assert.Equal(expectedTagName, output.TagName); Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); Assert.Equal(savedDisabled, items.Select(item => item.Disabled)); Assert.Equal(savedGroup, items.Select(item => item.Group)); Assert.Equal(savedSelected, items.Select(item => item.Selected)); Assert.Equal(savedText, items.Select(item => item.Text)); Assert.Equal(savedValue, items.Select(item => item.Value)); }
public virtual TagBuilder GenerateCheckboxLabel(ModelExpression f) => generator.GenerateLabel(viewContext, f.ModelExplorer, f.Name, null, new { @class = styles.CheckLabel });
public async Task TagHelper_CallsGeneratorWithExpectedValues_RealModelType( Type modelType, object model, bool allowMultiple) { // Arrange var contextAttributes = new TagHelperAttributeList( Enumerable.Empty <TagHelperAttribute>()); var originalAttributes = new TagHelperAttributeList(); var propertyName = "Property1"; var tagName = "select"; var tagHelperContext = new TagHelperContext( tagName: "select", allAttributes: contextAttributes, items: new Dictionary <object, object>(), uniqueId: "test"); var output = new TagHelperOutput( tagName, originalAttributes, getChildContentAsync: (useCachedResult, encoder) => { var tagHelperContent = new DefaultTagHelperContent(); tagHelperContent.SetContent("Something"); return(Task.FromResult <TagHelperContent>(tagHelperContent)); }); var metadataProvider = new EmptyModelMetadataProvider(); var modelExplorer = metadataProvider.GetModelExplorerForType(modelType, model); var modelExpression = new ModelExpression(propertyName, modelExplorer); var htmlGenerator = new Mock <IHtmlGenerator>(MockBehavior.Strict); var viewContext = TestableHtmlGenerator.GetViewContext(model, htmlGenerator.Object, metadataProvider); var currentValues = new string[0]; htmlGenerator .Setup(real => real.GetCurrentValues( viewContext, modelExplorer, propertyName, // expression allowMultiple)) .Returns(currentValues) .Verifiable(); htmlGenerator .Setup(real => real.GenerateSelect( viewContext, modelExplorer, null, // optionLabel propertyName, // expression It.IsAny <IEnumerable <SelectListItem> >(), currentValues, allowMultiple, null)) // htmlAttributes .Returns((TagBuilder)null) .Verifiable(); var tagHelper = new SelectTagHelper(htmlGenerator.Object) { For = modelExpression, ViewContext = viewContext, }; // Act tagHelper.Init(tagHelperContext); await tagHelper.ProcessAsync(tagHelperContext, output); // Assert htmlGenerator.Verify(); var keyValuePair = Assert.Single( tagHelperContext.Items, entry => (Type)entry.Key == typeof(SelectTagHelper)); var actualCurrentValues = Assert.IsType <CurrentValues>(keyValuePair.Value); Assert.Same(currentValues, actualCurrentValues.Values); }
public TagBuilder GenerateValidation(ModelExpression f) => generator.GenerateValidationMessage(viewContext, f.ModelExplorer, f.Name, null, null, new { @class = styles.Validation });
/// <summary> /// 初始化 /// </summary> /// <param name="expression">属性表达式</param> /// <param name="config">配置</param> public static void Init(ModelExpression expression, IConfig config) { new LabelExpressionResolver(expression, config).Init(); }
/// <summary> /// 初始化 /// </summary> /// <param name="expression">属性表达式</param> /// <param name="config">配置</param> /// <param name="isTableEdit">是否表格编辑</param> public static void Init(ModelExpression expression, SelectConfig config, bool isTableEdit = false) { new SelectExpressionResolver(expression, config, isTableEdit).Init(); }
protected override Expression VisitModelCastExpression(ModelExpression.ModelCastExpression m) { // Visit the target of the method Visit(m.Expression.Object); // Process arguments to method calls to handle lambda expressions foreach (var argument in m.Expression.Arguments) { // Perform special logic for lambdas if (argument is LambdaExpression || argument is ModelExpression.ModelLambdaExpression) { // Get the target of the method, assuming for static methods it will be the first argument // This handles the common case of extension methods, whose first parameter must be the target instance var target = m.Expression.Object ?? m.Expression.Arguments.First(); // Determine if the target implements IEnumerable<T>, and if so, determine the type of T var listType = target.Type.IsGenericType && target.Type.GetGenericTypeDefinition() == typeof(IEnumerable<>) ? target.Type : target.Type.GetInterfaces().Where(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(IEnumerable<>)).FirstOrDefault(); // If the instance or first parameter to a static method is represented in the expression path, // the corresponding step is a reference list, and the lambda is an action or function accepting instances // from the list, assume that each instance in the list will be passed to the lambda expression ModelStep step; if (listType != null && steps.TryGetValue(target, out step) && step.Property is ModelReferenceProperty && step.Property.IsList) { // Find the parameter that will be passed elements from the list, and link it to the parent step var parameters = argument is LambdaExpression ? (IEnumerable<Expression>)((LambdaExpression)argument).Parameters : (IEnumerable<Expression>)((ModelExpression.ModelLambdaExpression)argument).Parameters; var element = parameters.FirstOrDefault(p => listType.GetGenericArguments()[0].IsAssignableFrom(p.Type)); if (element != null) steps.Add(element, step); // If the method return the original list, associate the step with the return value if (m.Type.IsAssignableFrom(target.Type)) steps.Add(m, step); } } Visit(argument); } return m; }
/// <summary> /// Allows or blocks the display of a textbox depending on user authorization level. /// </summary> /// <typeparam name="TModel"></typeparam> /// <typeparam name="TProperty"></typeparam> /// <param name="htmlHelper"></param> /// <param name="expression"></param> /// <param name="fieldRequiredPrivilege">Privilege needed to show the field</param> /// <param name="readOnlyBehaviour">Behavior of the field if not authorized</param> /// <param name="linkRequiredPrivilege">Privilege needed to navigate to the link destination</param> /// <param name="linkAuthFailedBehaviour">Behavior of the link text if not authorized</param> /// <param name="actionName">Action destination of the link</param> /// <param name="controllerName">Controller destination of the link</param> /// <param name="routeValues">Route values of the link</param> /// <param name="htmlAttributes"></param> /// <param name="forceReadOnly">(Optional) Force the field into read-only mode regardless of authorization</param> /// /// <param name="formatString">(Optional) String used to format the value of the control</param> /// <returns></returns> public static IHtmlContent TextBoxForAuth <TModel, TProperty>(this IHtmlHelper <TModel> htmlHelper, Expression <Func <TModel, TProperty> > expression, Enumerations.Role fieldRequiredPrivilege, Enumerations.ReadOnlyBehaviour readOnlyBehaviour, Enumerations.Role?linkRequiredPrivilege, Enumerations.AuthFailedBehaviour?linkAuthFailedBehaviour, string actionName, string controllerName, object routeValues, object htmlAttributes, string formatString = null, bool forceReadOnly = false) { // If user has no privileges refuse access bool fullAccess = !forceReadOnly && new UserSessionContext(htmlHelper.GetHttpContext()).UserHasAccess(fieldRequiredPrivilege); string controlId = htmlHelper.GetControlId(expression); ModelExpression modelExpression = htmlHelper.GetModelExpressionProvider().CreateModelExpression(htmlHelper.ViewData, expression); var expressionValue = modelExpression.Model; string stringValue = expressionValue == null ? "" : expressionValue.ToString(); if (formatString != null) { stringValue = string.Format(formatString, expressionValue); } string html = htmlHelper.TextBox(controlId, stringValue, htmlAttributes).ToString(); if (!fullAccess) { switch (readOnlyBehaviour) { case Enumerations.ReadOnlyBehaviour.Disabled: var htmlOptions = new RouteValueDictionary(htmlAttributes); if (!htmlOptions.ContainsKey("disabled")) { htmlOptions.Add("disabled", "disabled"); } else { htmlOptions["disabled"] = "disabled"; } html = htmlHelper.TextBox(controlId + "__text", stringValue, htmlOptions).ToString(); html += htmlHelper.HiddenFor(expression).ToString(); break; case Enumerations.ReadOnlyBehaviour.EmptyString: html = htmlHelper.HiddenFor(expression).ToString(); break; case Enumerations.ReadOnlyBehaviour.InnerHtml: html = htmlHelper.SpanFor(expression, htmlAttributes, formatString).ToString(); html += htmlHelper.HiddenFor(expression).ToString(); break; case Enumerations.ReadOnlyBehaviour.AuthorizationLink: if (!linkAuthFailedBehaviour.HasValue || !linkRequiredPrivilege.HasValue) { throw new ArgumentNullException("linkAuthFailedBehaviour", "linkAuthFailedBehaviour or linkRequiredPrivilege cannot be null"); } html = htmlHelper.ActionLinkAuth(linkRequiredPrivilege.Value, linkAuthFailedBehaviour.Value, stringValue, actionName, routeValues, htmlAttributes).ToString(); html += htmlHelper.HiddenFor(expression).ToString(); break; default: throw new ArgumentOutOfRangeException("readOnlyBehaviour"); } } return(new HtmlString(html)); }
protected override Expression VisitModelParameter(ModelExpression.ModelParameterExpression p) { // Add the root step if (rootStep == null) { rootStep = new ModelStep(path); steps.Add(p, rootStep); } return p; }
protected virtual async Task ProcessSelectGroupAsync(TagHelperContext context, TagHelperOutput output, ModelExpression model) { var abpSelectTagHelper = GetSelectGroupTagHelper(context, output, model); await abpSelectTagHelper.RenderAsync(new TagHelperAttributeList(), context, _htmlEncoder, "div", TagMode.StartTagAndEndTag).ConfigureAwait(false); }
public RangeRule(string rootType, string property, ModelExpression minimum, ModelExpression maximum, string errorMessage) : base(rootType, property, new Error(GetErrorCode(rootType, property, "Range"), errorMessage, null), RuleInvocationType.InitNew | RuleInvocationType.PropertyChanged, property) { Initialize += (s, e) => SetRange(minimum, maximum); }
void InitializeSource(string source, LambdaExpression expression) { // Store the source this.Source = source; // Initialize the source during the rule initialization phase Initialize += (s, e) => { var rootType = RootType; var property = Property; // First, see if an explicit expression was specified for the rule source if (expression != null) { this.expression = expression; var sourceExpression = new ModelExpression(rootType, expression); Path = sourceExpression.Path.Path; } // Then see if the source represents a simple model source path else if (ModelSource.TryGetSource(RootType, source, out modelSource)) Path = modelSource.IsStatic ? "" : modelSource.Path; // Then see if the source is a valid model expression else { sourceType = property is ModelValueProperty ? typeof(IEnumerable<>).MakeGenericType(((ModelValueProperty)property).PropertyType) : ((ModelReferenceProperty)property).PropertyType is IReflectionModelType ? typeof(IEnumerable<>).MakeGenericType(((IReflectionModelType)((ModelReferenceProperty)property).PropertyType).UnderlyingType) : typeof(IEnumerable); var sourceExpression = rootType.GetExpression(sourceType, source); Path = sourceExpression.Path.Path; } // Set the predicates based on the property and model path Predicates = String.IsNullOrEmpty(Path) ? new string[] { property.Name } : new string[] { property.Name, Path }; }; }