SpecExpress là một Fluent validation framework, trong bài viết này, tôi xin giới thiệu cách validate Winform bằng SpecExpress và Error provider.
Xem giới thiệu về SpecExpress.
Trước hết tạo một Entity kế thừa từ IDataErrorInfo interface.
Sau đó tạo một dictionary đẻ lưu lại các message lỗi của các Property trong Entity đó.
1: /// <summary>
2: /// Dictionary of validation errors, it contains Property and Error messages...
3: /// </summary>
4: public Dictionary<string, string> Errors
5: {
6: get;
7: set;
8: }
Việc tiếp theo là implement interface IDataError: index this và thuộc tính Error:
1: public string Error
2: {
3: get
4: {
5: return lastError;
6: }
7:
8: }
index this[propertyName] trả về Error message cho Error Provider
1: /// <summary>
2: /// Gets the error of a specific property
3: /// </summary>
4: /// <param name="propertyName">The property name</param>d
5: /// <returns>The error message</returns>
6: public string this[string propertyName]
7: {
8: #region Doan Manh Ha commented for write new Error validation method by Specexpress
9: //get { return _propError[propertyName]; }
10: //set
11: //{
12: // _propError[propertyName] = value;
13: // PropertyHasChanged();
14: //}
15: #endregion
16:
17: get
18: {
19: if (!IsNeedValidation)
20: {
21: if (Errors!=null && Errors.ContainsKey(propertyName))
22: return Errors[propertyName];
23: else
24: return string.Empty;
25: }
26:
27: var notification = this.ValidateProperty(propertyName);
28:
29:
30:
31: if (notification==null || notification.IsValid)
32: {
33: lastError = string.Empty;
34:
35: }
36: else
37: {
38: // TODO: aggregate notification messages in readable form and assign to lastError
39: lastError = this.BuildErrorMessages(notification.ErrorSummary());
40: }
41:
42: AddError(propertyName, lastError);
43: return lastError;
44: }
45: set
46: {
47: AddError(propertyName, value);
48: }
49:
50: }
– IsNeedValidation là một thuộc tính xác định xem có cần phải validate không.
– Validate chính là Virtual method để validate property đó, trả về ValidationNotification
1: protected virtual ValidationNotification ValidateProperty(string propertyName)
2: {
3: throw new NotImplementedException();
4: }
– AddError là hàm add nội dung Error vào Error dictionary:
1: private void AddError(string propertyName, string error)
2: {
3: //lastError = value;
4: if (Errors == null)
5: Errors = new Dictionary<string, string>();
6:
7: if (Errors.ContainsKey(propertyName))
8: Errors[propertyName] = error;
9: else
10: Errors.Add(propertyName, error);
11: }
Tiếp theo ta viết Entity cho User, kế thừa từ AbstractBaseData:
1: public class User:AbstractBaseData<int>
2: {
3:
4: private int id;
5: private string name;
6: private string password;
7: private string rules;
8:
9: #region Public properties
10:
11: public int Id
12: {
13: get
14: {
15: return this.id;
16: }
17: set
18: {
19: if ((this.id != value))
20: {
21: this.id = value;
22: this.OnPropertyChanged("Id");
23:
24: }
25: }
26: }
27:
28: public string Name
29: {
30: get
31: {
32: return this.name;
33: }
34: set
35: {
36: if ((this.name != value))
37: {
38: this.name = value;
39: this.OnPropertyChanged("Name");
40:
41: }
42: }
43: }
44:
45: public string Password
46: {
47: get
48: {
49: return this.password;
50: }
51: set
52: {
53: if ((this.password != value))
54: {
55: this.password = value;
56: this.OnPropertyChanged("Password");
57:
58: }
59: }
60: }
61:
62: public string Rules
63: {
64: get
65: {
66: return this.rules;
67: }
68: set
69: {
70: if ((this.rules != value))
71: {
72: this.rules = value;
73: this.OnPropertyChanged("Rules");
74:
75: }
76: }
77: }
78:
79: public IList<Role> Roles
80: {
81: get;
82: set;
83: }
84:
85: #endregion
86:
87: #region Validations
88:
89: UserSpecification spec = new UserSpecification();
90:
91: protected override ValidationNotification ValidateProperty(string propertyName)
92: {
93:
94: try
95: {
96:
97: return ValidationCatalog.ValidateProperty(this, propertyName, spec);
98: }
99: catch (Exception)
100: {
101: return null;
102: }
103: }
104:
105: public override bool Validate()
106: {
107:
108: this.IsNeedValidation = true;
109:
110: this.PropertyHasChanged();
111: this.IsNeedValidation = false;
112: return this.IsValid;
113: }
114: #endregion
115: }
Và Specification cho User entity:
1: public class UserSpecification:Validates<User>
2: {
3: public UserSpecification()
4: {
5: Check(user => user.Name).Required(ValidationConstants.USER_NAME_REQ);
6:
7: Check(user => user.Password).Required(ValidationConstants.PASSWORD_REQ)
8: .MinLength(6);
9:
10: Check(user => user.Roles).Required(ValidationConstants.USER_ROLE_REQ);
11: }
12: }
Xử lý ở Winform UI
Sự kiện cho button Cập nhật:
1: private void btnUpdate_Click(object sender, EventArgs e)
2: {
3: string typeOfUserViewData = typeof(UserViewData).Name;
4: UserViewData userViewData = this.GetSessionData(typeOfUserViewData) as UserViewData;
5:
6: var isValid = userViewData.User.Validate();
7:
8: //Récupération de la VSD
9: if (!isValid)
10: {
11: epUserView.DataSource = userViewData.User;
12: return;
13: }
14:
15:
16: userViewData.IsCreation = false;
17: //Transfert de l'exécution vers le controleur
18: //this.InvokeController(ControllerConstants.USER_CONTROLLER, ControllerActionConstants.SAVE_ACTION);
19: }
Và đây là kết quả: