惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
腾讯CDC
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
L
LINUX DO - 热门话题
D
Darknet – Hacking Tools, Hacker News & Cyber Security
Project Zero
Project Zero
V
Vulnerabilities – Threatpost
Cisco Talos Blog
Cisco Talos Blog
P
Palo Alto Networks Blog
C
Cisco Blogs
A
Arctic Wolf
月光博客
月光博客
The GitHub Blog
The GitHub Blog
T
The Blog of Author Tim Ferriss
量子位
小众软件
小众软件
Latest news
Latest news
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
T
The Exploit Database - CXSecurity.com
Security Latest
Security Latest
N
Netflix TechBlog - Medium
K
Kaspersky official blog
人人都是产品经理
人人都是产品经理
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
博客园_首页
Y
Y Combinator Blog
P
Proofpoint News Feed
H
Hackread – Cybersecurity News, Data Breaches, AI and More
M
MIT News - Artificial intelligence
T
Threat Research - Cisco Blogs
S
Schneier on Security
D
Docker
Scott Helme
Scott Helme
MyScale Blog
MyScale Blog
Spread Privacy
Spread Privacy
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
GbyAI
GbyAI
有赞技术团队
有赞技术团队
Google DeepMind News
Google DeepMind News
The Hacker News
The Hacker News
H
Help Net Security
Simon Willison's Weblog
Simon Willison's Weblog
J
Java Code Geeks
C
Cyber Attacks, Cyber Crime and Cyber Security
T
Tenable Blog
B
Blog
Know Your Adversary
Know Your Adversary
IT之家
IT之家

博客园 - 五味果

.net Core 调用微信Jsapi接口,H5解析二维码 Dapper Vs Dbentry 外地手机号码,请在号码前加拨0 Sql 2012 远程数据库连接 DbEntry在Vs2012里的配置 终点,也是新的起点! 天气预报数据查询接口 关于浏览器账号的一个愿望 关于移动,联通,电信的区分。 - 五味果 - 博客园 被#号折腾了。 Orm 请别让数据库中的默认值形同虚设!! 利用反射,泛型,静态方法快速获取表单值到Model。 subsonic sqlite 路径问题 - 五味果 ORM是工具,工具是用来提高开发速度的。 基于XML的后台管理系统--设想 项模板的使用--提高编程速度 C#开发编码规范 基于Jquery的内容显示模块 - 五味果 - 博客园 IIS7下运行Access+Asp的解决方法
TextBoxFor控件的扩展---Bootstrap在mvc上的应用
五味果 · 2015-04-24 · via 博客园 - 五味果

TextBoxFor控件的问题:

1:自带了样式,再用bootstrap样式会有冲突。

2:要加水印,js事件,限制输入长度比较麻烦。

因此需要对textboxfor控件进行扩展。

目标:

1:能使用bootstrap样式。

2:能复用mvc的验证。

3:可以方便的添加水印。

4:能限制输入字符的长度。

5:采用一些命名约定,使用扩展控件。(说白了,就是日期类型的直接给上边加上调用日期控件的调用。)

解决方案

最容易想到的解决办法就是直接写个扩展方法,进行字符串拼接生成控件。使用的时候:@BootStrap.TextBoxFor(u=>u.Email)

最终生成:

 <input class="form-control" data-val="true" data-val-length="字段 邮箱 必须是最大长度为 50 的字符串。" data-val-length-max="50" data-val-regex="字段 邮箱 必须与正则表达式“.+”匹配。" data-val-regex-pattern=".+" data-val-required="邮箱 字段是必需的。" id="Email" maxlength="50" name="Email" type="text" value="taibaizhou@163.com"></input>
                <span class="field-validation-valid help-block" data-valmsg-for="Email" data-valmsg-replace="true"></span>

实现时候,悲催了。发现很难直接获取属性的验证信息,难道要自己再写反射,读取特性。生成对应的验证信息。

另一条路,借助mvc的htmlhelper来完成了。

        public static MvcHtmlString BsTextBoxFor<TModel, TProperty>(this HtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TProperty>> expression,string css="", string placeholder="")
        {
            TagBuilder tagBuilder = new TagBuilder("input");
            ModelMetadata metadata = ModelMetadata.FromLambdaExpression<TModel, TProperty>(expression, htmlHelper.ViewData);
            //tagBuilder.MergeAttributes(htmlHelper.GetUnobtrusiveValidationAttributes(ExpressionHelper.GetExpressionText(expression), metadata));
            string name = ExpressionHelper.GetExpressionText(expression);
            //var vas = htmlHelper.GetUnobtrusiveValidationAttributes(name, metadata);
            htmlHelper.ValidateFor(expression);
            tagBuilder.MergeAttribute("name",name);
            tagBuilder.GenerateId(name);
            tagBuilder.MergeAttribute("type","text");
       //核心代码,直接通过这个方法可以获取属性上的验证信息,如:“data-val= ....”。有一点要注意,在一个属性上,调用了这个方法完成后。mvc底层代码会自动释放这个验证对象。也就是说,一个属性的输入文本框只会第一个上边会生成相关的验证。
var vas = htmlHelper.GetUnobtrusiveValidationAttributes(name,metadata); 
if (!string.IsNullOrEmpty(placeholder)) { tagBuilder.MergeAttribute("placeholder",placeholder); }
       //string类型,看有没长度限制,如果有,增加maxlength,minlength
if (metadata.ModelType == typeof (string)) { var len = metadata.ContainerType.GetProperty(name).GetCustomAttribute(typeof(StringLengthAttribute)); if (len != null) { var stringlength = (StringLengthAttribute) len; if (stringlength.MaximumLength > 0) { tagBuilder.MergeAttribute("maxlength", stringlength.MaximumLength.ToString()); } if (stringlength.MinimumLength > 0) { tagBuilder.MergeAttribute("minlength", stringlength.MinimumLength.ToString()); } } }
       //如果model值不为,null,进行赋值。
if (metadata.Model != null) {
          todo:还要完善。 tagBuilder.MergeAttribute(
"value",metadata.Model.ToString()); } tagBuilder.MergeAttributes(vas); tagBuilder.AddCssClass("form-control"); if (!string.IsNullOrEmpty(css)) { tagBuilder.AddCssClass(css); }
       //约定,属性名以day或者date结束的属性为日体,为其增加日期选择功能。
if (name.ToLower().EndsWith("day") || name.ToLower().EndsWith("date")) { tagBuilder.MergeAttribute("onclick", "WdatePicker()"); } return new MvcHtmlString(tagBuilder.ToString()); }

最终实现效果:

View部分代码:

  <div class="form-group">
            @Html.BsLabelFor(model => model.Email)
            <div class="col-xs-10">
                @*@Html.TextBoxFor(model => model.Email, new { @class = "form-control" })*@
                @Html.BsTextBoxFor(model=>model.Email)
                @Html.ValidationMessageFor(model => model.Email, "", new { @class = "help-block" })
                
            </div>
        </div>
        <div class="form-group">
            @Html.BsLabelFor(model => model.Salary)
            <div class="col-xs-2 input-group" >
                <div class="input-group-addon">$</div>
            @Html.BsTextBoxFor(model => model.Salary)
                <div class="input-group-addon">.00</div>
            </div><div class="col-xs-8">
                @Html.ValidationMessageFor(model => model.Salary, "", new { @class = "help-block" })
            </div>
        </div>
        <div class="form-group">
            @Html.BsLabelFor(model => model.Code)
            <div class="col-xs-2">
                @Html.BsTextBoxFor(model => model.Code)
            </div><div class="col-xs-8">
                @Html.ValidationMessageFor(model => model.Code, "", new { @class = "help-block" })
            </div>
        </div>
        <div class="form-group">
            @Html.BsLabelFor(model => model.BirthDay)
            <div class="col-xs-2 input-group">
                @Html.BsTextBoxFor(model => model.BirthDay)<div class="input-group-addon" onclick="WdatePicker({ el: 'BirthDay' })">
                                                               <span class="glyphicon glyphicon-th"></span>
</div>
            </div><div class="col-xs-8">
                      @Html.ValidationMessageFor(model => model.BirthDay)
                  </div>
        </div>

viewModel代码:

  public class VerifyModel
    {
        public Guid Id { get; set; }
        [DisplayName("用户名")]
        [Required]
        [StringLength(15)]
        [Remote("CheckName", "Form")]
        public string UserName { get; set; }
        [DisplayName("密码")]
        [Required]
        [StringLength(20,MinimumLength = 4)]
        [DataType(DataType.Password)]
        public string PassWord { get; set; }
        [DataType(DataType.Password)]
        [System.ComponentModel.DataAnnotations.Compare("PassWord", ErrorMessage = "两次输入密码不一致")]
        [DisplayName("确认密码")]
        public virtual string ConfirmPassWord { get; set; }
        [StringLength(50)]
        [DisplayName("邮箱")]
        [Required]
        [DataType(DataType.EmailAddress)]
        [RegularExpression(@".+")]
        public string Email { get; set; }
        [RegularExpression(@"1\d{10}", ErrorMessage = "请输入正确的手机号码")]
        [DisplayName("手机")]
        [Required]
        public string Phone { get; set; }
        [DisplayName("薪水")]
        [Required]
        public decimal Salary { get; set; }
         [RegularExpression(@"d{6}", ErrorMessage = "邮编为六位数字")]
        [DisplayName("邮编")]
        [Required]
        public string Code { get; set; }
        [DisplayName("生日")]
        [Required]
        public DateTime BirthDay { get; set; }
    }

最后:

配合T4模板,采用一些命名约定能更快捷的生成各种表单页面。