.NET MVC 学习笔记(五)

.NET MVC 学习笔记(五)——Data Validation

 在实际应用中,我们需要对数据进行增查改删业务,在添加和修改过程中,无论你编写什么样的网页程序,都需要对用户的数据进行验证,以确数据的有效性和完整性。目前我们可以使用Bootstrap Validation对画面进行前端验证,我们先来看一下这种验证方式。

一、Bootstrap Validation

使用方式:

1. 引用js库

    <link href="~/bower_components/bootstrap-validation/css/bootstrapValidator.min.css" rel="stylesheet" />

 <script src="~/bower_components/bootstrap-validation/js/bootstrapValidator.min.js"></script>

2. 在页面中对validation进行初始化

<div class="modal-content">
	<div class="modal-header">
		<button type="button" class="close" data-dismiss="modal" aria-hidden="true">
			×
		</button>
		<h4 class="modal-title" id="myModalLabel">
			新增
		</h4>
	</div>
	<div class="modal-body">
		<div class="row clearfix">
			@using (Html.BeginForm("Save", "Client", FormMethod.Post, new { @id = "frmClient" }))
			{
				<div class="form-group">
					@Html.Hidden("Id")
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="CardNo" class="control-label">卡号&nbsp<span style="color:red">*</span></label>
						</div>
						<div class="col-sm-8">
							<input type="text" class="form-control" name="CardNo" id="CardNo">
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="UserName" class="control-label">会员名&nbsp<span style="color:red">*</span></label>
						</div>
						<div class="col-sm-8">
							<input type="text" class="form-control" autocomplete="off" name="UserName" id="UserName">
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="Sex" class="control-label">性别&nbsp<span style="color:red">*</span></label>
						</div>
						<div class="col-sm-8">
							@Html.DropDownListFor(model => model.Sex, ViewBag.GenderList as IEnumerable<SelectListItem>, new { @class = "form-control textbox input-sm" })
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="BirthdateText" class="control-label">出生日期&nbsp<span style="color:red">*</span></label>
						</div>
						<div class="col-sm-8">
							<div class="input-group date">
								<div class="input-group-addon">
									<i class="fa fa-calendar"></i>
								</div>
								@Html.TextBoxFor(model => model.BirthdateText, new { @class = "form-control datepicker", @type = "text", @autocomplete = "off" })
							</div>
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="Phone" class="control-label">手机号&nbsp<span style="color:red">*</span></label>
						</div>
						<div class="col-sm-8">
							<input type="text" id="Phone" name="Phone" autocomplete="off" class="form-control input-sm span3">
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="Address" class="control-label">地址</label>
						</div>
						<div class="col-sm-8">
							<input type="text" id="Address" name="Address" autocomplete="off" class="form-control input-sm span3">
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="Score" class="control-label">积分</label>
						</div>
						<div class="col-sm-8">
							<input type="text" id="Score" name="Score" autocomplete="off" class="form-control input-sm span3">
						</div>
					</div>
					<div class="row edit-field-div">
						<div class="col-sm-3 input-label">
							<label for="GradeCode" class="control-label">等级</label>
						</div>
						<div class="col-sm-8">
							@Html.DropDownListFor(model => model.GradeCode, ViewBag.GradeList as IEnumerable<SelectListItem>, new { @class = "form-control textbox input-sm" })
						</div>
					</div>
				</div>
			}
		</div>
	</div>
	<div class="modal-footer">
		<button type="button" class="btn btn-default" data-dismiss="modal">
			关闭
		</button>
		<button type="button" class="btn btn-primary" id="btnSaveClient">
			保存
		</button>
	</div>
</div>
$('#frm').bootstrapValidator({
            message: 'This value is not valid',
            feedbackIcons: {
                valid: 'glyphicon glyphicon-ok',
                invalid: 'glyphicon glyphicon-remove',
                validating: 'glyphicon glyphicon-refresh'
            },
            fields: {
                CardNo: {
                    verbose: false,
                    validators: {
                        notEmpty: {
                            message: '卡号不能为空'
                        },
                        remote: {
                            type: 'POST',
                            url: '@Url.Content("~/Client/CheckCardNo")',
                            dataType: 'json',
                            data: {
                                ClientId: function () {
                                    return $('#Id').val()
                                },
                                CardNo: function () {
                                    return $('#CardNo').val()
                                }
                            },
                            message: '此卡号已存在',
                            delay: 200
                        }
                    }
                },
                UserName: {
                    validators: {
                        notEmpty: {
                            message: '会员名不能为空'
                        }
                    }
                },
                Phone: {
                    validators: {
                        notEmpty: {
                            message: '手机号码不能为空'
                        },
                        regexp: {
                            regexp: /^1[3|5|8]{1}[0-9]{9}$/,
                            message: '请输入正确的手机号码'
                        }
                    }
                },
                Score: {
                    validators: {
                        regexp: {
                            regexp: /^[\d]+$/,
                            message: '积分必须为数字'
                        }
                    }
                }
            }
        });

 如上代码所示,对frm表单进行验证初始化,CardNo,UserName等为控件的name属性

运行效果如下:

其中,对CardNo有重复性check,此时需要使用remote进行验证,后台代码如下:

/// <summary>
        /// 检查CardNo
        /// </summary>
        /// <param name="ClientId"></param>
        /// <param name="CardNo"></param>
        /// <returns></returns>
        public JsonResult CheckCardNo(String ClientId, String CardNo)
        {
            try
            {
                // 检索条件
                ClientFilter filter = new ClientFilter();
                filter.CardNo = CardNo;
                List<ClientDomain> clients = ClientBiz.GetDomainByExactFilter(filter) as List<ClientDomain>;
                ValidaResult resObj = new ValidaResult();
                resObj.valid = true;
                if (String.IsNullOrEmpty(ClientId) && clients.Count > 0)
                {
                    resObj.valid = false;
                }
                else if (!String.IsNullOrEmpty(ClientId))
                {
                    if (clients.Count > 1)
                    {
                        resObj.valid = false;
                    }
                    else if (clients.Count == 1 && !clients[0].Id.Equals(ClientId))
                    {
                        resObj.valid = false;
                    }
                }
                return Json(resObj, JsonRequestBehavior.AllowGet);
            }
            catch (Exception ex)
            {
                Log.SaveException(ex);
                return new JsonResult()
                {
                    JsonRequestBehavior = JsonRequestBehavior.AllowGet,
                    Data = new { ResultTitle = Constant.Result_Title_Error, ResultMessage = ex.Message }
                };
            }
        }

  

 /// <summary>
    /// Valid 结果
    /// </summary>
    [Serializable]
    [DataContract]
    public class ValidaResult
    {
        [DataMember]
        public Boolean valid { get; set; }
    }

验证效果如下:

regexp:是对字段进行正则表达式验证,可以根据自己的需要进行相应的验证。

还有密码确认密码验证

//密码确认
edit_passwd1: {
	message: '密码确认验证失败',
	validators: {
		notEmpty: {
			message: '密码确认不能为空'
		},
		identical: {
			field: 'edit_passwd',
			message: '两次密码不相同'
		}
	}
}

 长度验证

stringLength: {
	min: 5,
	max: 128,
	message: '显示名长度必须在6到18位之间'
}

 等等

在提交画面变更时,需要进行验证

//开启验证
$('#frm').data('bootstrapValidator').validate();
if ($('#frm').bootstrapValidator('validate').has('.has-error').length != 0) {
	return;
}

或者

var flag = $("#frm").data(“bootstrapValidator”).isValid();

验证通过之后进行页面数据提交

在画面初始化的时候,如果上次画面关闭前有验证消息,再次打开或许会出现验证消息依然存在的情况,这时候需要重置所有验证

$("frm").data("bootstrapValidator").resetForm();

 以上,就是相关前端验证的内容。

========================================================================

是不是到这里就结束了,一开始我也以为是的,源自于我对用户的信任,可是事实上大部分用户也完全值得我们的信任,但是作为开发者,我们不能允许有异常发生。

以此为例:

请看下面的画面

这是对【会员名】的验证

UserName: {
	validators: {
		notEmpty: {
			message: '会员名不能为空'
		}
	}
}

当我们修改会员名,设置为空时

看起来一切正常,只有输入会员名我们才能提交,但是当我们输入会员名,并点击【保存】

我们这时选择在代码中打入断点

 

此时我们看到,代码已经进行了正常的前端Validation验证,并且已经验证通过了,那么如果我们此时在调试窗口手动的去修改画面的值,那么验证将不再有效

可以看到,手动的将【会员名】改成了空值,运行结束后看最终结果值

此时【会员名】变成空了。

那么,我们就需要考虑一个问题,如何避免这个问题。

答案很简单,进行双重验证,客户端和服务器端都进行验证,由此我们还需要对模型进行验证。验证方法如下:

MVC 模型注解验证

在对应的实体类的字段上加注解,如

/// <summary>
/// UserName
/// </summary>
[DataMember]
[Required(ErrorMessage = "会员名不能空")]
public String UserName
{
	get
	{
		return this.userName;
	}
	set
	{
		this.userName = value;
	}
}
<div class="row edit-field-div">
<div class="col-sm-3 input-label">
	<label for="UserName" class="control-label">会员名&nbsp<span style="color:red">*</span></label>
</div>
<div class="col-sm-8">
	@Html.TextBoxFor(model => model.UserName, new { @class = "form-control", @autocomplete = "off" })
	@Html.ValidationMessageFor(model => model.UserName,"", new { @style="color:red"})
</div>
// 保存信息
$('#frm').submit();

Form 表单在提交的时候会做后台验证,也就是对实体类的验证

其他验证如下:

转自:https://www.cnblogs.com/dianshen520/p/4349229.html

1、模型注解,用来检查表单中元素的合法性,效果类似于前面学过的 formvalidate.js插件
命名空间: using System.ComponentModel; 下面存储了
1、DisplayName():标记属性要显示的名称 配合视图上面的 @Html.DisplayNameFor(c=>c.属性名称)来显示
命名空间: using System.ComponentModel.DataAnnotations; 下面存储了
1、Required :用来做非空验证检查,特点:在非字符串类型属性上会自动加上 Required 特性标签,如果是字符串类型必须手动添加
2、StringLength :用来检查字符串类型的属性的长度验证
3、Range:用来检查数值(int,decimal,double,float)类型的属性的范围验证
4、Compare:用来比较两个属性的值是否一致,一般用于确认密码属性上
5、[RegularExpression("\\d+", ErrorMessage="年龄必须是一个数值")]:约束此属性的值必须是一个数值

命名空间: using System.ComponentModel.DataAnnotations; 下面存储了
1、Remote("请求的action名称","控制器名称",HttpMethod = "post/get(一般推荐使用post请求来防止ajax的缓存)",ErrorMessage = "提示文本"):会发出一个ajax请求到某个控制器中的某个 action进行检查操作,如果存在则返回字符串的 false (注意不能使用大写的False,如果使用了则不能正常调用)
表示此值已经存在不能再使用,否则返回true(注意不能使用大写的True,如果使用了则不能正常调用) 表示可以使用
[System.Web.Mvc.Remote("CheckUserName" //代表的是请求的action名称
,"Home" //代表控制器名称
,HttpMethod="post" //表示发出post的ajax异步请求,主要是为了防止ajax请求的缓存,如果使用get可能出现结果不准确
,ErrorMessage="此值已经被使用,请重新跟换") //表示如果服务器返回的是false字符串,则提醒用户
]

eg:

/// <summary>
/// 员工信息
/// </summary>
public class StaffInfo
{
    public virtual int StaffInfoId { get; set; }

    [Required]
    [Display(Name = "登录账号")]
    public virtual string LogID { get; set; }

    [StringLength(10, MinimumLength = 4, ErrorMessage = "{0}的长度必须大于{2}个字符并小于{1}个字符")]
    [Display(Name = "密码")]
    public virtual string LogPassword { get; set; }

    [StringLength(10, ErrorMessage = "{0}的长度不能大于{1}个字符")]
    [Display(Name = "姓名")]
    public virtual string RealName { get; set; }

    [Display(Name = "出生日期")]
    //[Range(typeof(DateTime), "2011-12-31", "1950-1-1", ErrorMessage = "{0}的范围是{1}到{2}")]
    public virtual DateTime Birthday { get; set; }

    [RegularExpression(@"\d{17}[\d|X]|\d{15}", ErrorMessage = "{0}的格式不正确")]
    [Display(Name = "身份证号码")]
    public virtual string IdentityNo { get; set; }

    [RegularExpression(@"[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}", ErrorMessage = "{0}的格式不正确")]
    [Display(Name = "邮箱")]
    public virtual string Email { get; set; }

    [Display(Name = "逻辑删除标识")]
    public virtual int IsLogicDelete { get; set; }
}

总结如下:

使用Required 进行页面元素的合法性验证步骤:
1、在实体属性上打上[Required(ErrorMessage="Name属性非空")]
2、在视图页面上 利用@Html.TextBoxFor(c=>c.Name) :用来生产文本框,同时给文本框架加上 data-val="true" data-val-*......
3、在视图页面上 利用@Html.ValidationMessageFor(c=>c.Name) 用来显示提示文本的
4、引用三个js脚本
<script src="~/Scripts/jquery-1.7.1.js"></script>
<script src="~/Scripts/jquery.validate.js"></script>
<script src="~/Scripts/jquery.validate.unobtrusive.js"></script>
5、注意:元素必须放到表单中 <form> 标签才能起验证作用
6、检查MVC网站跟目录下面的web.config中的<appSettings>节点中的两个节点
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
的值必须为true,才能起验证作用,否则任何一个关闭都不起作用

7、最终表单的提交需要用form的submit()方法来进行验证(自己验证的结果)
什么叫做非嵌入式脚本(非侵入式脚本)~/Scripts/jquery.validate.unobtrusive.js
没有在视图上写一个验证的代码就完成表单元素的验证功能,仅仅只是利用了相关的脚本来完成,这个就叫做非嵌入式

OK,这样前端后后端的基本验证就做完了。

猜你喜欢

转载自www.cnblogs.com/byron-123/p/10431520.html