zoukankan      html  css  js  c++  java
  • asp.net core高级应用:TagHelper+Form

      上一篇博客我讲解了TagHelper的基本用法和自定义标签的生成,那么我就趁热打铁,和大家分享一下TagHelper的高级用法~~,大家也可以在我的博客下随意留言。

      对于初步接触asp.net core的骚年可以看看我对TagHelper的了解和看法:

      《asp.net core新特性(1):TagHelper》

      之后,我也会继续撰写博文,继续分享asp.net core的一些新特性,比如DI,ViewComponent以及bower等asp.net mvc中没有的新东西。

      ok,咱们就开始吧~~

      在之前我对TagHelper的分享当中提及了,TagHelper能够去替代原来在@Html帮助类中的一些功能,比如form,a等标签,而且写在html代码中更加的舒服,符合html的语法。

    <!--标签助手版form-->
    <form asp-controller="Home" asp-action="Index" class="form-horizontal" method="post">
    
    </form>
    <!--Html帮助类版form-->
    @using (Html.BeginForm("Index", "Home", FormMethod.Post,, new { Class = "form-horizontal" }))
    {
    
    }

      那么,在Html帮助类中最有用的Model与Tag的转换,自动表单的生成,微软是否也给出了解决方案呢?答案是肯定的。Microsoft还专门分出了单独的说明页面来讲述TagHelper的自动表单生成,英文功底好的同学可以直接查看MS的官方文档《Introduction to using tag helpers in forms in ASP.NET Core》

      文档中提及了对于表单控件,我们可以直接在asp-for属性中直接填写Model中的属性名,即可自动生成对应的控件类型和填入默认值。

      ok,我们来尝试一下。

      (1)创建ViewModel类

        public class SignUpViewModel
        {
            [Required]
            [Display(Name ="用户名")]
            [MaxLength(30,ErrorMessage = "用户名不能超过30")]
            public string UserName { get; set; }
    
            [Required]
            [DataType(DataType.Password)]
            [RegularExpression(@"((?=.*d)(?=.*D)|(?=.*[a-zA-Z])(?=.*[^a-zA-Z]))^$",ErrorMessage ="密码至少包含两种以上字符")]
            [Display(Name ="密码")]
            public string Password { get; set; }
    
            [DataType(DataType.MultilineText)]
            public string Description { get; set; }
        }

      对于写过asp.net mvc的开发者肯定不会陌生这种验证方式~~

      (2)编写TagHelper标签

      为了与Html区分,我写了两者的比较版本

    <form asp-controller="Home" asp-action="SignUp" method="post" class="form-horizontal">
        <div class="form-group">
            <label asp-for="UserName"></label>
            <input asp-for="UserName" />
            <span asp-validation-for="UserName"></span>
        </div>
        <div class="form-group">
            @Html.LabelFor(m=>m.Password)
            @Html.PasswordFor(m=>m.Password)
            @Html.ValidationMessageFor(m=>m.Password)
        </div>
        <div class="form-group">
            <label asp-for="Description"></label>
            <textarea asp-for="Description"></textarea>
            <span asp-validation-for="Description"></span>
        </div>
        <div class="form-group">
            <input type="submit" value="提交" />
            <input type="reset" value="重置" />
        </div>
    </form>

      (3)验证表单

            public IActionResult SignUp(SignUpViewModel model)
            {
                if (ModelState.IsValid)
                {
                    return RedirectToAction("Index");
                }
                else
                {
                    return RedirectToAction("Index",model);
                }
            }

      (4)结果

      

      ok,如果觉得这样就结束了,那么就不算TagHelper高级应用,那只能充其量在翻译MS的文档罢了。

      那么,重点来了,既然MS能让我们创建自定义TagHelper,那我为什么不能在TagHelper当中使用Model的值呢?于是我开始在asp.net core开源github项目中寻找,终于是找到了ImputTagHelper的源码。

      在源码中,由三个对象一起来完成标签的生成

            protected IHtmlGenerator Generator { get; }
    
            [HtmlAttributeNotBound]
            [ViewContext]
            public ViewContext ViewContext { get; set; }
    
            /// <summary>
            /// An expression to be evaluated against the current model.
            /// </summary>
            [HtmlAttributeName(ForAttributeName)]
            public ModelExpression For { get; set; }

      三个对象均是通过依赖注入的方式来实现对象的生成。

      (1)其中Generator为发生器,负责生成各种类型的标签

      (2)ViewContext为视图上下文,获取视图上下文相关信息

      (3)For获取到当前Model的相关信息,包括Required等关键信息

      有了这三个标签,我们也可以在自定义的标签助手中获取你想要的Model信息,比如我可以向form中填入Model信息,让标签助手自动生成form表单中的所有内容;也可以向ul标签中填入树信息,让其自动生成树列表等等

      如下就是我编写的自动生成表单

        //自定义标签助手名为bg-form
        [HtmlTargetElement("bg-form")]
        public class FormTagHelper : TagHelper
        {
            [ViewContext]
            [HtmlAttributeNotBound]
            public ViewContext ViewContext { get; set; }
    
            [HtmlAttributeName("asp-for")]
            public ModelExpression For { get; set; }
    
            protected IHtmlGenerator Generator { get; }
    
            public FormTagHelper(IHtmlGenerator generator)
            {
                Generator = generator;
            }
    
            [HtmlAttributeName("asp-controller")]
            public string Controller { get; set; }
    
            [HtmlAttributeName("asp-action")]
            public string Action { get; set; }
    
            //异步方法
            public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
            {
                output.TagName = "form";
                if (!string.IsNullOrWhiteSpace(Controller))
                {
                    output.Attributes.Add("action", "/" + Controller + "/" + Action);
                }
    
                output.Attributes.Add("class", "form-horizontal");
    
                //获取子属性
                var props = For.ModelExplorer.Properties;
                foreach (var prop in props)
                {
                    //生成表单
                    var div = new TagBuilder("div");
                    div.AddCssClass("form-group");
                    var label = Generator.GenerateLabel(ViewContext, prop, null, prop.Metadata.DisplayName, null);
                    var input = Generator.GenerateTextBox(ViewContext, prop, prop.Metadata.PropertyName, null, null, null);
                    var span = Generator.GenerateValidationMessage(ViewContext, prop, prop.Metadata.PropertyName, null, ViewContext.ValidationMessageElement, null);
                    div.InnerHtml.AppendHtml(label);
                    div.InnerHtml.AppendHtml(input);
                    div.InnerHtml.AppendHtml(span);
                    output.Content.AppendHtml(div);
                }
                //添加按钮
                var btn = new TagBuilder("div");
                btn.AddCssClass("form-group");
                var submit = new TagBuilder("input");
                submit.Attributes.Add("type", "submit");
                submit.Attributes.Add("value", "提交");
                var reset = new TagBuilder("input");
                reset.Attributes.Add("type", "reset");
                reset.Attributes.Add("value", "重置");
                btn.InnerHtml.AppendHtml(submit);
                btn.InnerHtml.AppendHtml(reset);
                output.Content.AppendHtml(btn);
                //将原有的内容添加到标签内部
                output.Content.AppendHtml(await output.GetChildContentAsync());
    
            }
        }

      只要在html加入

    <bg-form asp-controller="Home" asp-action="SignUp" asp-for="@Model">
    
    </bg-form>

    即可自动生成表单

      Over,今天关于TagHelper就分享到这~~

  • 相关阅读:
    (OK) VirtualBox 5.0.10 中 Fedora 23 在安装了增强工具后无法自动调节虚拟机分辨率的问题
    (OK) install-fedora23—gnome classic—dnf—gdm—multi-user—graphical
    (OK) fedora23——add “opening terminal” in the menu of right click
    (OK) Install Docker on Fedora 23
    (OK) 运行cBPM in Fedora23
    错误:‘bOS::SQL::SQLCommand::SQLOperation’既不是类也不是命名空间
    My enum is not a class or namespace
    【t049】&&【u001】足球
    【u002】数列排序(seqsort)
    【u003】计算概率
  • 原文地址:https://www.cnblogs.com/billming/p/7148226.html
Copyright © 2011-2022 走看看