如何避免在MVC Web应用程序的模型和视图中进行约束验证的重复代码? [英] How to avoid duplicate code for constraint validation in the model and view of a MVC web app?

查看:317
本文介绍了如何避免在MVC Web应用程序的模型和视图中进行约束验证的重复代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

应该在MVC应用程序的 模型类 中定义完整性约束,因为它们是模型类(表示业务对象类型)的语义的一部分。但是,必须在应用的基于HTML5格式的 视图代码 中的用户输入(以及表单提交按钮点击)上验证约束。我们如何避免重复验证码并将其保留在JavaScript MVC应用程序的模型代码中?

解决方案

不幸的是,许多MVC应用程序开发框架没有提供任何支持来维护模型中的完整性约束代码,并在视图(输入和表单提交)和模型中(在保存之前将其用于数据验证)。



我将尝试提供我开发的解决这个 多重验证问题的方法草图 与HTML5表单API及其 setCustomValidity checkValidity 方法。因为它需要在视图和模型中执行相同的代码,它只适用于一个JavaScript MVC Web应用程序,我们在应用程序的两个部分都有相同的编程语言(JavaScript),与其他应用程序不同(例如PHP od Java)网络应用程序,后端模型代码不在JavaScript中。



通常我们只需要验证属性约束。因此,编写一个类级别检查函数是很自然的,该函数验证模型类的每个属性的所有约束。例如,以下检查功能确保 Book 对象的ISBN属性的值为10位字符串或9位字符串,后跟X :

  Book.checkIsbn = function(isbn){
if(typeof(isbn)!==string || isbn.trim()===){
返回新的RangeConstraintViolation(ISBN必须是非空字符串!);
} else if(!/ \b\d {9}(\d | X)\b / .test(isbn)){
返回新的PatternConstraintViolation(
' ISBN必须是10位字符串或9位数字字符串,后跟X!');
} else {
return new NoConstraintViolation();
}
};

检查函数返回一个 ConstraintViolation class,它有一个字符串值的message属性。在提供视图(或UI)的HTML5表单中,我们为输入事件添加一个事件监听器到有关的表单输入字段,以处理用户输入的验证:

  isbnInpEl.addEventListener(input,function(){
isbnInpEl.setCustomValidity(Book.checkIsbn(isbnInpEl.value))。消息);
});

此事件侦听器调用 setCustomValidity 它有一个字符串参数。我们提供由我们的属性检查功能创建的消息作为调用 setCustomValidity 的参数。如果为空,则表示用户输入有效。否则,如果它包含一个非空限制违例消息,则HTML5浏览器将会照顾向用户指示约束冲突(例如,通过显示输入字段的红色边框并显示消息)。



为了处理表单提交按钮上的验证单击,我们通过调用表单元素上的HTML5 checkValidity 方法来检查表单的所有输入字段对象:

  if(formEl.checkValidity()){
// save
formEl.reset );
}

最后,为了在保存任何新数据之前检查模型类中的约束,我们可以调用属性设置器中的检查函数,如

  Book.prototype.setIsbn = function(isbn){
var validationResult = Book.checkIsbn(isbn);
if(validationResult instanceof NoConstraintViolation){
this.isbn = isbn;
} else {
throw validationResult;
}
};

您可以在我的书中找到完整的示例代码使用简单的JavaScript构建前端Web应用程序


Integrity constraints should be defined in the model classes of a MVC application since they are part of the semantics of a model class (representing a business object type). However, constraints also have to be validated on user input (and on form submission button click) in the HTML5-form-based view code of the app. How can we avoid to duplicate the validation code and keep it in the model code of a JavaScript MVC app?

解决方案

Unfortunately, many MVC application development frameworks do not provide any support for maintaining the integrity constraints code in the model and use it for data validation both in the view (on input and on form submission) and in the model (before save).

I'll try to provide a sketch of the approach that I've developed to solve this multiple validation problem with the HTML5 forms API, and its setCustomValidity and checkValidity methods. Since it requires to execute the same code both in the view and in the model, it only works in a JavaScript MVC web app, where we have the same programming language (JavaScript) in both parts of the app, unlike in other (e.g. PHP od Java) web apps, where the backend model code is not in JavaScript.

Normally we have to validate property constraints only. It's natural, therefore, to write a class-level check function that validates all constraints for each property of a model class. For instance, the following check function makes sure that a value for the ISBN property of a Book object is a 10-digit string or a 9-digit string followed by "X":

Book.checkIsbn = function (isbn) {
  if (typeof(isbn) !== "string" || isbn.trim() === "") {
    return new RangeConstraintViolation("The ISBN must be a non-empty string!");
  } else if (!/\b\d{9}(\d|X)\b/.test( isbn)) {
    return new PatternConstraintViolation(
        'The ISBN must be a 10-digit string or a 9-digit string followed by "X"!');
  } else {
    return new NoConstraintViolation();
  }
};

The check function returns an instance of a ConstraintViolation class, which has a string-valued message property. In the HTML5 form providing the view (or UI), we add an event listener for input events to the form input field concerned for handling the validation on user input:

isbnInpEl.addEventListener("input", function () { 
  isbnInpEl.setCustomValidity( Book.checkIsbn( isbnInpEl.value).message);
});

This event listener invokes the setCustomValidity method, which has a string parameter. We provide the message created by our property check function as the argument for the invocation of setCustomValidity. If it's empty, this means the user input is valid. Otherwise, if it contains a non-empty constraint violation message, the HTML5 browser will take care of indicating the constraint violation to the user (e.g. by showing a red border for the input field and displaying the message).

For handling the validation on form submission button click, we check all input fields of the form by invoking the HTML5 checkValidity method on the form element object:

if (formEl.checkValidity()) {
  // save
  formEl.reset();
}

Finally, for checking the constraints in the model class before saving any new data, we may invoke the check functions in the property setters, as in

Book.prototype.setIsbn = function (isbn) {
  var validationResult = Book.checkIsbn( isbn);
  if (validationResult instanceof NoConstraintViolation) {
    this.isbn = isbn;
  } else {
    throw validationResult;
  }
};

You can find the full example code in my book Building Front-End Web Apps with Plain JavaScript.

这篇关于如何避免在MVC Web应用程序的模型和视图中进行约束验证的重复代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆