ASP.NET MVC3 自定驗證 Remote 驗證遇到根 Area 的解決方式
- 2012-05-24
- 18258
- 0
- ASP.NET MVC3 驗證介紹實作與擴充
demo 在【ASP.NET MVC3 如何使用內建驗證功能達到前端與後端的同時驗證】有介紹過 Remote 驗證這種大絕形式的前端驗證使用方式,但是如果你的 MVC 專案有用到 Area 機制,那你很可能會發現爆炸了,這篇文章就簡單的介紹一下怎麼處理掉這塊事情。
.立刻簡單回顧一下 Remote 驗證的方式,使用 ASP.NET MVC3 的模版來改造一下
開啟 \Models\AccountModels.cs
public class LogOnModel { [Required] [Display(Name = "User name")] [Remote("CheckUserName", "Validate", ErrorMessage = "遠端驗證失敗")] public string UserName { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [Display(Name = "Remember me?")] public bool RememberMe { get; set; } }
建立一個驗證專用的 Controller (一般來說我會建議各位將 Remote 驗證專用的 Controller 統一起來)
建立 ValidateController.cs
namespace MvcApplication1.Controllers { public class ValidateController : Controller { public JsonResult CheckUserName(string userName) { bool isValidate = false; if (Url.IsLocalUrl(Request.Url.AbsoluteUri)) { //利用 IsLocalUrl檢查是否為網站呼叫的 //借此忽略一些不必要的流量 if (userName != "demoshop") { //因連資料庫麻煩 //所以假裝示範不可以註冊某一名字 isValidate = true; } } // Remote 驗證是使用 Get 因此要開放 return Json(isValidate, JsonRequestBehavior.AllowGet); } } }
馬上來到登入畫面就可以看到驗證效果了
以上是快速的複習,用起來是相當的簡單方便,但是當你的 MVC 架構開始大了起來需要使用 Area 機制的時候就會發現為什麼遠端驗證的功能不正常,再來模擬一個 名稱為 Test 的 Area 要呼叫相同的遠端驗證邏輯來看看。
建立完成的 Test 如下圖:
- Controller 就是 Default1Controller 內容是空的,我什麼都沒放。
- 依據 Controller 預設的 Index action 建立出對應的 View,View 的 ViewModel 使用了和 LogOn.cshtml 一樣的 ,完整 HTML 如下。
@model MvcApplication1.Models.LogOnModel @{ ViewBag.Title = "Log On"; Layout = "~/Views/Shared/_Layout.cshtml"; } <h2>我是仿的</h2> <script src="@Url.Content("~/Scripts/jquery.validate.min.js")" type="text/javascript"></script> <script src="@Url.Content("~/Scripts/jquery.validate.unobtrusive.min.js")" type="text/javascript"></script> @Html.ValidationSummary(true, "Login was unsuccessful. Please correct the errors and try again.") @using (Html.BeginForm()) { <div> <fieldset> <legend>Account Information</legend> <div class="editor-label"> @Html.LabelFor(m => m.UserName) </div> <div class="editor-field"> @Html.TextBoxFor(m => m.UserName) @Html.ValidationMessageFor(m => m.UserName) </div> <div class="editor-label"> @Html.LabelFor(m => m.Password) </div> <div class="editor-field"> @Html.PasswordFor(m => m.Password) @Html.ValidationMessageFor(m => m.Password) </div> <div class="editor-label"> @Html.CheckBoxFor(m => m.RememberMe) @Html.LabelFor(m => m.RememberMe) </div> <p> <input type="submit" value="Log On" /> </p> </fieldset> </div> }
重複作業完成後進入頁面(記得先 Build)馬上再輸入 demoshop 卻發現了錯誤
看圖說故事,我們的遠端驗證位置不是放在 Area 內,但是看得出來他去 Call 的網址包含了 Area name 所以很自然的找不到,而發生了 404 ,這時候你或許會馬上修改成這樣
自己明確的告訴他 Area 是空的
編譯後再來測試,你會發現結果是一樣的...........
經過一番輾轉難眠就反組譯了ASP.NET MVC 3原本的 Code 來看看
看到特別框起來的地方了嗎?被濾掉了.....,還有其實不用反組譯,因為 ASP.NET MVC 是 Open Source 的【線上直接看】
既然知道了原因如此單純,那就動手改 Code 吧,建立一個新的 Class
public class RemotePlus : RemoteAttribute { public RemotePlus(string action, string controller, string area) : base(action, controller, area) { this.RouteData["area"] = area; } }
把 Area 確實的傳過去,再把 Medadata 的部份改用新寫的這個
[Required] [Display(Name = "User name")] //[Remote("CheckUserName", "Validate", "", ErrorMessage = "遠端驗證失敗")] [RemotePlus("CheckUserName", "Validate", "", ErrorMessage = "新遠端驗證失敗")] public string UserName { get; set; }
這次再測試就會正常拉(記得編譯....
寫完這篇以後跑去看了一下目前 ASP.NET MVC 4 Beta 的版本依然是沒有改變,可能有什麼考量在吧
(感謝小朱提供我 MVC 4 的 dll)
回應討論