ASP.NET MVC3 自定驗證 Remote 驗證遇到根 Area 的解決方式
- 2012-05-24
- 20193
- 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)








Roslyn 魔法工坊:打造你的 Source Generator [2025-12-20]開課 共7H
回應討論