asp.net core高级应用:TagHelper+Form

上一篇博客《asp.net core新特性(1):TagHelper》我讲解了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就分享到这~~

原文地址:http://www.cnblogs.com/billming/p/7148226.html


.NET社区新闻,深度好文,微信中搜索dotNET跨平台或扫描二维码关注

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324679.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

爸妈没多大本事……

本文原创&#xff1a;王晓丹世界上什么都不公平&#xff0c;唯独时间最公平&#xff0c;你是懒惰还是勤奋&#xff0c;时间都会给出结果。每个人都是孤独的&#xff0c;你的人生不会辜负你的。那些流下的泪和那些辛苦的汗水 全都让你成为一个独一无二的自己。把懒惰放一边 &…

我终于搞清楚了和String有关的那点事儿

转载自 我终于搞清楚了和String有关的那点事儿 String&#xff0c;是Java中除了基本数据类型以外&#xff0c;最为重要的一个类型了。很多人会认为他比较简单。但是和String有关的面试题有很多&#xff0c;下面我随便找两道面试题&#xff0c;看看你能不能都答对&#xff1a…

SpringMVC的拦截器

文章目录SpringMVC的拦截器学习SpringMVC的拦截器学习 [1] SpringMVC拦截器的介绍 问题: 在之前学习Servlet的时候&#xff0c;我们学习了过滤器的知识。过滤器的作用是保护 请求的服务器资源&#xff0c;在请求资源被执行之前&#xff0c;如果请求地址符合拦截范围&#xff…

考研英语二大纲22年考研

全国硕士研究生招生考试英语(二)考试大纲(非英语专业)(2022年版)   I.考试性质   英语(一)考试是为高等学校和科研院所招收硕士研究生而设置的具有选拔性质的全国统一入学考试科目&#xff0c;其目的是科学、公平、有效地测试考生对英语语言的运用能力&#xff0c;评价的标…

ssl1763-观光旅游【最小环,Floyd,dijkstra】

正题 就是给出一个无向图&#xff0c;求最小环。 输入输出&#xff08;需要自取&#xff09; Input 每组数据的第一行包含两个正整数&#xff1a;十字路口的个数N(N<100)&#xff0c;另一个是道路的 数目M(M<10000)。接下来的每一行描述一条路&#xff1a;每一行有三个…

物联网模式下的多活数据中心架构认识与实践

做互联网应用很重要的一点是要保证服务可用性&#xff0c;特别是某些业务更是需要7*24小时不间断的对外提供服务&#xff0c;任何停机、宕机都会引起大面积的用户不满。持续可用性是把业务服务化时一个需要考虑的重要指标&#xff0c;很多时候我们都会牺牲一些功能来换取可用性…

subList?? subString???

今天看到了java中List中有个subList方法&#xff0c;感觉很熟悉有没有&#xff1f;没错&#xff0c;在Stirng类中&#xff0c;也有个类似的方法&#xff1a;subString。1String类的subStringString中的subString方法&#xff0c;官方解释是&#xff1a;返回字符串的子字符串&am…

互联网级监控系统必备-时序数据库之Influxdb集群及踩过的坑

上篇博文中&#xff0c;我们介绍了做互联网级监控系统的必备-Influxdb的关键特性、数据读写、应用场景&#xff1a;互联网级监控系统必备-时序数据库之Influxdb 本文中&#xff0c;我们介绍Influxdb数据库集群的搭建&#xff0c;同时分享一下我们使用集群遇到的坑&#xff01;…

考研数学二大纲22年考研

考试科目&#xff1a;高等数学、线性代数   考试形式和试卷结构   一、试卷满分及考试时间   试卷满分为150分&#xff0c;考试时间为180分钟.   二、答题方式   答题方式为闭卷、笔试.   三、试卷内容结构   高等教学 约80%   线性代数 约20%   四、试卷题…

ssl1500-最短路上的统计【Floyd】

正题 个无向图上&#xff0c;没有自环&#xff0c;所有边的权值均为1&#xff0c;对于一个点对&#xff08;a,b&#xff09;,我们要把所有a与b之间所有最短路上的点的总个数输出。 输入输出&#xff08;需要自取&#xff09; Input 第一行n,m,表示n个点&#xff0c;m条边 接…

Java中的subList方法

Java中的subList方法 今天看到了java中List中有个subList的方法&#xff0c;感觉很熟悉有没有&#xff1f;没错&#xff0c;在Stirng类中&#xff0c;也有个类似的方法&#xff1a;subString。 Stirng中的subString方法&#xff0c;官方解释是&#xff1a;返回字符串的子字符串…

考研408大纲22年考研

I 考试性质   计算机学科专业基础综合考试是为高等院校和科研院所招收计算机科学与 技术学科的硕士研究生而设置的具有选拔性质的联考科目&#xff0c;其目的是科学、公平、 有效地测试考生掌握计算机科学与技术学科大学本科阶段专业知识、基本理论、 基本方法的水平和分析问…

在Apworks数据服务中使用基于Entity Framework Core的仓储(Repository)实现

《在ASP.NET Core中使用Apworks快速开发数据服务》一文中&#xff0c;我介绍了如何使用Apworks框架的数据服务来快速构建用于查询和管理数据模型的RESTful API&#xff0c;通过该文的介绍&#xff0c;你会看到&#xff0c;使用Apworks框架开发数据服务是何等简单快捷&#xff0…

再有人问你Java内存模型是什么,就把这篇文章发给他

转载自 再有人问你Java内存模型是什么&#xff0c;就把这篇文章发给他 前几天&#xff0c;发了一篇文章&#xff0c;介绍了一下JVM内存结构、Java内存模型以及Java对象模型之间的区别。有很多小伙伴反馈希望可以深入的讲解下每个知识点。Java内存模型&#xff0c;是这三个知识…

SpringMVC对Ajax请求的处理

SpringMVC对Ajax请求的处理 [1] 问题: 当浏览器发起一个ajax请求给服务器&#xff0c;服务器调用对应的单元方法处理ajax请求。 而ajax的请求在被处理完成后&#xff0c;其处理结果需要直接响应。而目前我们在单元方 法中响应ajax请求&#xff0c;使用的是response对象&#x…

ssl2344P2835-刻录光盘【Floyd,联通块数,图论】

正题 洛谷题目 就是给出一个图&#xff0c;求最小联通块数。 输入输出&#xff08;需要自取&#xff09; Input 先是一个数N&#xff0c;接下来N行&#xff0c;分别表示各个营员愿意把自己获得的资料拷贝给其他哪些营员。即输入数据的第N1行表示第i个营员愿意把资料拷贝给那…

为了金秋那沉甸甸的麦穗,我绝不辜负春天

本文原创&#xff1a;焦文宇我可以一落千丈&#xff0c;但我就是要一鸣惊人。——题记01 没有谁的一生是一帆风顺的&#xff0c;也没有谁的一生是充满坎坷的。人生就像是一场游戏“玩”的好坏全都在于自己&#xff0c;我们没有任何理由去抱怨生活中的点滴&#xff0c;我们应当对…

BigDecimal丢失精度的坑

问题&#xff1a;new BigDecimal(double d)的数值居然还是不精确的 double d 0.09; BigDecimal bigDecimalnew BigDecimal(d); System.out.println(bigDecimal); System.out.println(d); 输出结果&#xff1a; 0.0899999999999999966693309261245303787291049957275390625 …

编译型语言VS解释型语言

编译型语言人类代码 ————》一次性把代码给 翻译官&#xff08;编译器&#xff09;————》汇编--》机器语言代表 &#xff1a; c,c,golang优点&#xff1a;执行速度快缺点&#xff1a;跨平台可移植性差硬件 &#xff0c; cpu , 有自己指令规则 0000000001 打印&#xf…

P1236-Network of Schools(学校网络)【最强联通块,Kosaraju】

正题 POJ题目链接 给出一个图&#xff0c;求联通块数量和加入多少条边后会将全图变为一个最强联通块。 机翻输入输出&#xff08;需要自取&#xff09; 输入 第一行包含整数N&#xff1a;网络中的学校数量&#xff08;2 < N < 100&#xff09;。学校由前N个正整数标识…