zoukankan      html  css  js  c++  java
  • ASP.NET全栈开发验证模块之将前后台校验结合

    前五篇博文分别介绍并实现了前端校验和服务器校验,这篇博文主要是介绍如何将两者结合起来使用,并总结。

    之前,我们在ASP.NET MVC中集成了基于FluentValidator的验证器,并通过扩展Controller,在ControllEx中 使用 OnActionExecuting 进行统一校验。最后将所有错误信息存放在ViewData["Error"]内部后返回视图。

    在视图呈现方面,我们使用了HtmlHelper的扩展方法来帮呈现,这样有效避免了Null的尴尬局面。

            /// <summary>
            /// 显示指定属性的错误消息
            /// </summary>
            /// <param name="htmlHelper">HtmlHelper</param>
            /// <param name="property">指定的属性</param>
            /// <param name="error">ViewData["Error"]</param>
            /// <param name="tagType">标签类型</param>
            /// <param name="htmlAttribute">标签属性</param>
            /// <returns></returns>
            public static MvcHtmlString ValidatorMessageFor(this HtmlHelper htmlHelper, string property, object error, string tagType = "p", object htmlAttribute = null)
            {
                var dicError = error as Dictionary<string, string>;
    
                if (dicError != null)  //没有错误
                {
                    if (dicError.ContainsKey(property))
                    {
                        StringBuilder sb = new StringBuilder();
                        if (htmlAttribute != null)
                        {
                            htmlAttribute.GetType().GetProperties().ToList().ForEach((p) =>
                            {
                                string key = p.Name;
                                string value = p.GetValue(htmlAttribute).ToString();
                                sb.AppendFormat(" {0}='{1}' ", key, value);
                            });
                        }
                        return new MvcHtmlString(string.Format("<{0} {2}>{1}</{0}>", tagType, dicError[property], sb.ToString()));
                    }
                }
                return new MvcHtmlString("");
            }

    如今我对HtmlHelper做了一定修改,使它支持自定义标签类型和定义Html的属性,这会让我们好的管理呈现效果。比方为他加一个样式。

    通过以上步骤我们就实现了服务端的验证。

    在前端,与前几章说讲的一样,我们使用Vue,并自编写了基于Vue的验证插件vuefluentvalidator,为什么叫它vuefluentvalidator,因为编写它的时候就是借鉴的咱们后台验证框架FluentValidator的使用方式。

    @using ValidationWebTest.Mvc.MvcHelperEx
    @{
        ViewBag.Title = "ValidatorTest";
    }
    <h2>ValidatorTest</h2>
    <div id="box">
        @using (Html.BeginForm())
        {
            @Html.AntiForgeryToken()
    
            <div class="form-horizontal">
                <h4>Person</h4>
                <hr />
                @Html.ValidationSummary(true, "", new { @class = "text-danger" })
                <div class="form-group">
                    <label for="Name" class="control-label col-md-2">姓名</label>
                    <div class="col-md-10">
                        <input type="text" name="Name" class="form-control" v-model="model.name" />
                        <p v-text="model.error.name"></p>
                        @Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" })
                    </div>
                </div>
    
                <div class="form-group">
                    <label for="Age" class="control-label col-md-2">年龄</label>
                    <div class="col-md-10">
                        <input type="text" name="Age" class="form-control" v-model="model.age" />
                        <p v-text="model.error.age"></p>
                        @Html.ValidatorMessageFor("Age", ViewData["Error"], "strong")
                    </div>
                </div>
    
                <div class="form-group">
                    <label for="Home" class="control-label col-md-2">住址</label>
                    <div class="col-md-10">
                        <input type="text" name="Address.Home" class="form-control" v-model="model.address.home" />
                        <p v-text="model.error.address.home"></p>
                        @Html.ValidatorMessageFor("Address.Home", ViewData["Error"])
                    </div>
                </div>
    
                <div class="form-group">
                    <label for="Phone" class="control-label col-md-2">电话</label>
                    <div class="col-md-10">
                        <input type="text" name="Address.Phone" class="form-control" v-model="model.address.phone" />
                        <p v-text="model.error.address.phone"></p>
                        @Html.ValidatorMessageFor("Address.Phone", ViewData["Error"])
                    </div>
                </div>
    
                <div class="form-group">
                    <div class="col-md-offset-2 col-md-10">
                        <input type="submit" value="Create" class="btn btn-default" v-on:click="formSubmit($event)" />
                    </div>
                </div>
            </div>
        }
    </div>
    
    @section scripts{
        <script src="~/Content/vue.js"></script>
        <script src="~/Content/vuefluentvalidator.js"></script>
        <script>
            let vm = new Vue({
                el: '#box',
                data: {
                    validator: new Validator({
                        model: {
                            name: undefined,
                            age: undefined,
                            address: {
                                home: undefined,
                                phone: undefined
                            },
                        },
                        rule: function (than) {
                            than.ruleFor("name")
                                .NotEmpty()
                                .WithMessage("姓名不能为空")
                                .MinimumLength(5)
                                .WithMessage("最短长度为5");
    
                            than.ruleFor("age")
                                .NotEmpty()
                                .WithMessage("年龄不能为空");
    
                            than.ruleFor("address.home")
                                .NotEmpty()
                                .WithMessage("家庭地址不能为空");
    
                            than.ruleFor("address.phone")
                                .NotEmpty()
                                .WithMessage("电话不能为空");
                        }
                    }),
                },
                methods: {
                    formSubmit: function (ev) {
                        if (this.validator.passValidation()) {
                            return;
                        }
                        ev.preventDefault();
    
                        this.validator.validation(ev.target);
                    }
                },
                computed: {
                    model: function () {
                        return this.validator.model;
                    }
                }
            });
        </script>
    }

    使用方式和之前前端验证所讲的都一模一样,只是在验证下边加了一行

     @Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" })

    为什么我会这样写?因为在正常情况下,我们前端会进行校验,如果前端校验不通过的时候,请求不会发送到后台,所以这一行在正常情况下是用不到的。

    那在什么时候会用到他?在前端校验失效时或伪造请求时。

    首先分析第一种

    前端校验失效,也就意味着javascript失效,这种情况下我们的

    <p v-text="model.error.name"></p>

    什么都显示不出来。

    而在验证失败的时候 @Html.ValidatorMessageFor("Name", ViewData["Error"], "span", new { @class = "text-info" }) 就会起作用了,由于我们对标签的呈现效果控制的灵活性,在视觉体验上,没有任何区别。

    如果在第二种情况下,他都不是一个正常的请求,我管它干什么?阻止就是了。

    如果你认为既然使用Vue,那为什么不将错误信息绑定到我们的验证器上呢?

    事实上我也想过这么做,一是它的工作量比现在这种方式更大(原谅我偷了个懒),二是,如果javascript失效的话,那岂不是根本显示不出来?

    综上所述,于是我决定就让它这样简单而愉快的结束吧。到此我们的前后端校验功能就算全部实现。

    由于博文是前五篇的延续,在一些重复的内容上,不过多介绍,如果您在阅读时,有任何疑问,请从前面开始阅读。

  • 相关阅读:
    文件上传、下载测试点总结
    selenium+Python(Page Object 设计模式实例)
    Python面向对象
    Python内置函数
    Python异常处理
    Python文件的I/o
    vue-router 二级路由
    vue中如何获取后台数据
    移动端适配问题
    vue中钩子函数的用法
  • 原文地址:https://www.cnblogs.com/Gxqsd/p/9345678.html
Copyright © 2011-2022 走看看