回顧
《前端基于easyui的mvc擴充》、《前端基于easyui的mvc擴充(續)》前兩篇介紹了mvc内如何基于easyui進行擴充,在mvc裡面有很多簡化的文法可以讓開發人員快速開發,既然我們已經對mvc進行了擴充,那麼當然也不能漏掉了基礎的web form了。首先我們來比較一下mvc和web form,如果前端不使用razor,都是用aspx頁面的話,使用的文法是一樣的,隻是mvc内提供了HtmlHelper、Model、ViewData等來簡化開發。
也就是說,如果我們使用如下的方式,其實在web form裡面也是可行的,但是與mvc不同的是,web form内并沒有像HtmlHelper的對象可以直接進行擴充,是以我們隻能重新建立一個類來實作這些功能,既然無法使用類似HtmlHelper的對象擴充,那麼model對象也就必須在編碼标簽的時候手動傳入了,大緻代碼如下:
<% User user = new User { Name = "測試", StateId = 2 }; %>
<%=EasyUIHelper.ValidateText(u => u.Name, user)%>
<%=EasyUIHelper.Datebox(u => u.Name, user)%>
<%=EasyUIHelper.Combobox<User>(u => u.StateId, user, "States", "{ id: 'myCob', 'data-options': 'width: 100, editable: false' }")%>
實作
那麼要達到以上的效果其實也不難,因為我們在前兩篇已經進行了實作了,隻要将其重構一下,使其可以支援在web form内工作便可以了,那麼首先我們遇到的問題便是如何把表達式樹轉化為屬性,這個主題我在《擷取Lambda表達式内表達式的值》該文章中已經進行了講解,調整後代碼大緻如下:
public static string ValidateText<TModel>(Expression<Func<TModel, object>> expression, TModel model, string attributeJson, Dictionary<string, string> attributes)
{
string propertyName = PropertyHelper.ResloveName(expression);//關于擷取表達式值的文章
PropertyInfo property = typeof(TModel).GetProperty(propertyName);
TagBuilder tag = new TagBuilder("input");
//增加name、type屬性
ValidationAttribute[] validationAttrs;
if (property.TryGetAttributes(out validationAttrs))
{
//請閱讀轉換規則代碼
}
var extraAttributes = string.IsNullOrEmpty(attributeJson) ? attributes : JsonHelper.Deserialize<IDictionary<string, string>>(attributeJson);//基于Newtonsoft轉化json的公用方法
//添加屬性
return tag.ToString();
}
這樣前端的代碼就順利轉換完成了,剩下的便是如何讓表單送出到服務端後,怎麼樣進行驗證呢,大概的流程如下:
- 将送出到服務端的表單直接轉化為對應的實體類
- 讀取實體類各個屬性以及屬性内的驗證特性,一一進行進行驗證
- 如果中間沒有驗證失敗的話,那麼就說明實體是符合驗證要求的,可進行其他操作
第一步其實就是利用反射将屬性相對應的值一一指派給相應的屬性而已,這裡我們就不重複去實作了。
擷取屬性驗證特性,我們可以通過擴充MemberInfo(因為PropertyInfo和MethodInfo都是MemberInfo的派生類)來擷取特性,大緻代碼如下:
public static bool TryGetAttributes(this MemberInfo member, out TAttribute[] attributes, bool inherit = false) where TAttribute : Attribute
{
attributes = null;
var objs = member.GetCustomAttributes(typeof(TAttribute), inherit);
if (objs.Length == 0)
return false;
attributes = Array.ConvertAll(objs, obj => obj as TAttribute);
return true;
}
對驗證特性進行驗證的代碼大緻如下:
//周遊屬性
ValidationAttribute[] validationAttributes = //擷取驗證特性
foreach (var validation in validationAttributes)
{
if (validation is RegularExpressionAttribute)
{
var regularAttr = validation as RegularExpressionAttribute;
var reg = new Regex(regularAttr.Pattern);
if (value != null && !reg.IsMatch(value.ToString()))
return false;
}
else
{
ValidationResult result = validation.GetValidationResult(value, new ValidationContext(instance, null, null));
if (result != ValidationResult.Success)
return false;
}
}
這裡之是以要将RegularExpressionAttribute單獨抽出來判斷是因為System.ComponentModel.DataAnnotations.dll(v4.0.0.0)内的實作有BUG,沒有根據正則正确的實作GetValidationResult方法。
效果
//實體
public class User
{
private string m_Name = null;
[Required(ErrorMessage = "使用者名不能為空!")]
[StringLength(10, MinimumLength = 4, ErrorMessage = "使用者名長度必須在4-10之間")]
[DisplayName("使用者名:")]
public string Name
{
get { return m_Name; }
set { m_Name = value; }
}
//略
}
//前端
<%
FormBuilder form = new FormBuilder();
User user = new User { Name = "測試", StateId = 2 }; %>
<%=form.CreateBeginHtml("/Handlers/MvcHandler.ashx", "fmTest")%>
<%=EasyUIHelper.ValidateText(u => u.Name, user)%>
<br />
<%=EasyUIHelper.Combobox(u => u.StateId, user, "States", "{ id: 'myCob', 'data-options': 'width: 100, editable: false'}")%>
<br />
<input type="submit" value="送出" />
<%=form.CreateEndHtml() %>
<script type="text/javascript">
$('#fmTest').easyuiForm();
</script>
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLicmbw5SZwgTN3kDZ4cTYlRGOlFGOzYzN0EGZykTZkhjNyMTNk1yN1cTMyITOx8CX4AzMxAjMvw1N1kzN4EzLcd2bsJ2Lc12bj5ycn9Gbi52YuAzcldWYtl2Lc9CX6MHc0RHaiojIsJye.png)
結尾
謝謝大家,如文章有任何問題和錯誤請指出,謝謝!