예제 #1
0
        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();
        }
예제 #2
0
 /// <summary>
 /// 初始化
 /// </summary>
 /// <param name="expression">属性表达式</param>
 /// <param name="config">配置</param>
 public static void Init(ModelExpression expression, SelectConfig config)
 {
     new SelectExpressionResolver(expression, config).Init();
 }
예제 #3
0
        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);
        }
예제 #4
0
        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));
        }
예제 #5
0
        public static PropertyInfo GetProperty(this ModelExpression model)
        {
            var metadata = model.Metadata;

            return(metadata.ContainerType.GetProperty(metadata.PropertyName));
        }
예제 #6
0
 protected virtual bool IsSelectGroup(TagHelperContext context, ModelExpression model)
 {
     return(IsEnum(model.ModelExplorer) || AreSelectItemsProvided(model.ModelExplorer));
 }
예제 #7
0
 protected virtual AbpTagHelper GetSelectGroupTagHelper(TagHelperContext context, TagHelperOutput output, ModelExpression model)
 {
     return(IsRadioGroup(model.ModelExplorer) ?
            GetAbpRadioInputTagHelper(model) :
            GetSelectTagHelper(model));
 }
예제 #8
0
파일: RangeRule.cs 프로젝트: vc3/ExoRule
 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);
     }
 }
예제 #9
0
        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();
        }
예제 #10
0
        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);
        }
예제 #11
0
 protected StringLengthAttribute GetStringLengthAttribute(ModelExpression modelExpression)
 {
     return(modelExpression.Metadata.ValidatorMetadata.FirstOrDefault(vm => vm is StringLengthAttribute) as StringLengthAttribute);
 }
예제 #12
0
 protected RequiredAttribute GetRequiredAttribute(ModelExpression modelExpression)
 {
     return(modelExpression.Metadata.ValidatorMetadata.FirstOrDefault(vm => vm is RequiredAttribute) as RequiredAttribute);
 }
예제 #13
0
 /// <summary>
 /// 初始化
 /// </summary>
 /// <param name="expression">属性表达式</param>
 /// <param name="config">配置</param>
 public static void Init(ModelExpression expression, Config config)
 {
     new CheckBoxExpressionResolver(expression, config).Init();
 }
예제 #14
0
 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]);
        }
예제 #16
0
파일: ModelPath.cs 프로젝트: vc3/ExoModel
            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;
            }
예제 #17
0
        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();
        }
예제 #18
0
        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));
        }
예제 #19
0
    /*==========================================================================================================================
    | 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);

    }
예제 #20
0
        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);
        }
예제 #21
0
        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));
        }
예제 #22
0
        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);
        }
예제 #23
0
        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();
 }
예제 #25
0
 protected TagHelperOutput GenerateTagHelperCore(ModelExpression f, TagHelper tagHelper, string tagName, TagMode tagMode) =>
 GenerateTagHelperCore(f, tagHelper, tagName, tagMode, "text", styles.FormControl);
예제 #26
0
        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));
        }
예제 #27
0
 public virtual TagBuilder GenerateCheckboxLabel(ModelExpression f) =>
 generator.GenerateLabel(viewContext, f.ModelExplorer, f.Name, null, new { @class = styles.CheckLabel });
예제 #28
0
        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);
        }
예제 #29
0
 public TagBuilder GenerateValidation(ModelExpression f) =>
 generator.GenerateValidationMessage(viewContext, f.ModelExplorer, f.Name, null, null, new { @class = styles.Validation });
예제 #30
0
 /// <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();
 }
예제 #32
0
파일: ModelPath.cs 프로젝트: vc3/ExoModel
            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;
            }
예제 #33
0
        /// <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));
        }
예제 #34
0
파일: ModelPath.cs 프로젝트: vc3/ExoModel
            protected override Expression VisitModelParameter(ModelExpression.ModelParameterExpression p)
            {
                // Add the root step
                if (rootStep == null)
                {
                    rootStep = new ModelStep(path);
                    steps.Add(p, rootStep);
                }

                return p;
            }
예제 #35
0
        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);
        }
예제 #36
0
파일: RangeRule.cs 프로젝트: vc3/ExoRule
 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);
 }
예제 #37
0
        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 };
            };
        }