zoukankan      html  css  js  c++  java
  • ASP.NET MVC局部验证及相关问题

    在上一篇“asp.net mvc常用的数据注解和验证以及entity framework数据映射”话题中,有的博友提到

    ‘“同一个实体在3-4个地方会发生修改,每个修改需要验证的方式都不一样,后端就不能写固定验证。”

    此博友的言论我是很赞同的,在基于asp.net mvc上,我有对应的策略,并且,你只需几行代码,就解决了所有的事情。

    还是举上次的Model,如下:

    [Table("AdminInfo")]
        public partial class AdminInfo
        {
            [Key]
            [Display(Name = "编号:")]
            [Column("Id")]
            public int Id { get; set; }
    
            [Required(ErrorMessage = "*不能为空!")]
            [RegularExpression(@"^[u4E00-u9FA5uf900-ufa2dw.s]{6,18}$", ErrorMessage = "*6-18位拼音或数字")]
            [Column(TypeName = "nvarchar")]
            [MaxLength(50)]
            [Display(Name = "用户名:")]
            ///[Remote("CheckUserName","Account")]
            public string UserName { get; set; }
    
            [Required(ErrorMessage = "*不能为空!")]
            [RegularExpression(@"^[u4E00-u9FA5uf900-ufa2dw.s]{6,18}$", ErrorMessage = "*6-18位拼音或数字")]
            [Column(TypeName = "nvarchar")]
            [MaxLength(50)]
            [MinLength(6)]
            [Display(Name = "密码:")]
            [DataType(DataType.Password)]
            public string PassWord { get; set; }
    
            [Column(TypeName = "nvarchar")]
            [Display(Name = "真实姓名:")]
            [MaxLength(20)]
            public string TrueName { get; set; }
    
            [Display(Name = "是否可用:")]
            public bool? IsUseFul { get; set; }
    
            [ReadOnly(true)]
            [Display(Name = "创建时间:")]
            [DatabaseGenerated(DatabaseGeneratedOption.Computed)]
            public DateTime CreatTime { get; set; }
    
            [Display(Name = "等级")]
            public int? Orders { get; set; }
    
            [NotMapped]
            [Required(ErrorMessage = "*不能为空!")]
            [RegularExpression(@"^[u4E00-u9FA5uf900-ufa2dw.s]{6,18}$", ErrorMessage = "*6-18位拼音或数字")]
            [Display(Name = "新密码")]
            [DataType(DataType.Password)]
            public virtual string PassWord1 { get; set; }
    
            [NotMapped]
            [Compare("PassWord1", ErrorMessage = "新密码和确认密码不一致!")]
            [Required(ErrorMessage = "*不能为空!")]
            [RegularExpression(@"^[u4E00-u9FA5uf900-ufa2dw.s]{6,18}$", ErrorMessage = "*6-18位拼音或数字")]
            [Display(Name = "确认密码")]
            [DataType(DataType.Password)]
            public virtual string PassWord2 { get; set; }
        }

    在基于这个Model上,我们做一些业务,比如:添加,页面如下:

    @{
        Layout = null;
    }
    @model SnsModels.AdminInfo
    
    <!DOCTYPE html>
    
    <html>
    <head>
        <meta name="viewport" content="width=device-width" />
        <title>Index</title>
        <link href="/css/demo.css"  rel="stylesheet"/>
        <script type="text/javascript" src="/Scripts/jquery-1.7.2.min.js"></script>
        <script src="/Scripts/jquery.validate.min.js" type="text/javascript"></script>
        <script src="/Scripts/jquery.validate.unobtrusive.min.js" type="text/javascript"></script>
        <script src="/Scripts/jquery.unobtrusive-ajax.min.js" type="text/javascript"></script>
    </head>
    <body>
        <div class="web">
    
            @using (Ajax.BeginForm("AddSubmit", "AdminInfo", new AjaxOptions { HttpMethod = "post" }))
            {
                <table class="table">
                    <tr>
                        <td colspan="2" class="TableTitle">创建管理员</td>
                    </tr>
                    <tr>
                        <td>@Html.LabelFor(m => m.UserName)</td>
                        <td class="td2">@Html.TextBoxFor(m => m.UserName)</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td class="td2">@Html.ValidationMessageFor(m => m.UserName)</td>
                    </tr>
    
                    <tr>
                        <td>@Html.LabelFor(m => m.PassWord)</td>
                        <td class="td2">@Html.PasswordFor(m => m.PassWord)</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td class="td2">@Html.ValidationMessageFor(m => m.PassWord)</td>
                    </tr>
    
                    <tr>
                        <td>@Html.LabelFor(m => m.TrueName)</td>
                        <td class="td2">@Html.TextBoxFor(m => m.TrueName)</td>
                    </tr>
                    <tr>
                        <td>&nbsp;</td>
                        <td class="td2">@Html.ValidationMessageFor(m => m.TrueName)</td>
                    </tr>
    
                    <tr>
                        <td>&nbsp;</td>
                        <td class="td2">
                            <input type="submit" value="提交" /></td>
                    </tr>
                </table>
            }
        </div>
    </body>
    </html>

    在这里,我只用到了3个字段,但是Model上有很多字段,并且还有需要验证的字段,我们上面的业务中是没有显示出来的。

    那么我们在控制器中做一些改动,如下:

    [HttpPost]
            public ActionResult AddSubmit([Bind(Include = "UserName,PassWord,TrueName")] SnsModels.AdminInfo Model)
            {
                try
                {
                    if (Request.IsAjaxRequest())
                    {
                        ModelState.Remove("PassWord1");
                        ModelState.Remove("PassWord2"); if (ModelState.IsValid) { if (Repository.Create<SnsModels.AdminInfo>(Model)) { return JavaScript("alert('添加成功...');"); } else { return JavaScript("alert('添加失败...');"); } } else { return JavaScript("alert('数据验证未通过...');"); } } else { return Content("<script>alert('请求不通过...');window.location='/AdminInfo/Add';</script>"); } } catch (Exception ex) { return JavaScript("alert('"+ex.Message.ToString()+"');"); } }

     ModelState.Remove("PassWord1");

    ModelState.Remove("PassWord2");

    上面2行,表示这字段,在本控制器中我们不需要验证。

    然后我们体检Model到DAL层。如下:

    /// <summary>
            /// 创建一条记录
            /// </summary>
            /// <typeparam name="T"></typeparam>
            /// <param name="model"></param>
            /// <returns></returns>
            public int Create<T>(T model) where T : class
            {
                int Result = 0;
                using (SnsLearningLogManagerDB db = new SnsLearningLogManagerDB())
                {
                    db.Configuration.ValidateOnSaveEnabled = false;
                    db.Set<T>().Add(model);
                    Result = db.SaveChanges();
                    db.Configuration.ValidateOnSaveEnabled = true;
                    return Result;
                } }
    db.Configuration.ValidateOnSaveEnabled = false;
    db.Configuration.ValidateOnSaveEnabled = true;

    这2个地方需要注意,如果没有,你插入的时候会一直显示操作异常。

    在业务逻辑中我们已经验证过Model,在这里其实是不需要再进行验证的。

    如果你一定要加上这个的话,我个人的解决方案是:
    新建一个ViewModel针对此业务逻辑,然后数据验证通过之后把ViewModel传递给Model,这样就搞定了。

    在控制器层有一段这样的代码 [Bind(Include = "UserName,PassWord,TrueName")]
    这个是什么意思呢? 指定你的Model从View层接受到的属性,这个主要是防止攻击所用,因为别人可以仿造表单传递一些其他的参数进来,导致项目受损。
    比如:我在伪造一个表单,包含orders字段,次字段如果表示管理员身份的话,而0表示高级管理员,那么我直接给orders赋值0,这样传递到控制器上还是能验证通过的,这将导致往数据库插入错误数据。
    当然,我们有办法防止这些的,但是,加入[Bind(Include = "UserName,PassWord,TrueName")]如此简单,我们何乐不为呢!

    本来也是菜鸟级别,如言论和代码有什么错误之处,还望大牛们指点。

    自上次博客附带QQ群招人信息,不少博友都申请加入,小弟不慎感激。
    以下为QQ群广告:
    本群提供ASP.NET MVC,EF,LINQ,WEB API技术支持,不在乎人多,在乎人精。

    ASP.NET MVC群 171560784  

    诚邀各路高手、初学者加入。
     
  • 相关阅读:
    Salesforce LWC学习(三十七) Promise解决progressindicator的小问题
    Salesforce Consumer Goods Cloud 浅谈篇三之 行动计划(Action Plan)相关配置
    python 3.7环境安装并使用csv
    分享数据库优化文章
    php 5.4 var_export的改进
    CentOS7 启动 firewalld 防火墙失败,查看日志提示超时
    使用 SSL 加密的 JDBC 连接 SAP HANA 数据库
    CAS学习笔记一:CAS 授权服务器简易搭建
    202110期自考总结
    自定义 OpenShift s2i 镜像与模板——OracleJDK8
  • 原文地址:https://www.cnblogs.com/kezhiping/p/3868255.html
Copyright © 2011-2022 走看看