摘要
????? 本文將從完成“輸入數據驗證”這個功能出發,逐漸展開ASP.NET MVC與Ajax結合的方法。首先,本文將使用ASP.NET MVC提供的同步方式完成數據驗證。而后,將分別結合ASP.NET AJAX和JQuery將這個功能重構成異步形式。
數據驗證
????? 在上一篇文章中,我們完成了發布公告的功能。但是從健壯性角度看,這個功能并不完善,因為一般情況下,我們輸入的數據要符合一定的約束條件,例如,在我們的例子中,我們至少不能將空字符串作為標題或內容吧。下面,我們來為程序加入數據驗證功能,
????? ASP.NET MVC中提供了良好的數據驗證實現支持,下面我們來看實現過程。首先,我們要修改一下Release.aspx視圖,修改后的視圖如下。
Release.aspx:
- <%@?Page?Language= "C#" ?AutoEventWireup= "true" ?CodeBehind= "Release.aspx.cs" ?Inherits= "MVCDemo.Views.Announce.Release" ?%> ??
- <%@?Import?Namespace= "MVCDemo.Models.Entities" ?%> ??
- ??
- <!DOCTYPE?html?PUBLIC? "-//W3C//DTD?XHTML?1.0?Transitional//EN" ?? "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" ]]>?> ??
- ??
- <html?xmlns= "http://www.w3.org/1999/xhtml" ?> ??
- <head?runat= "server" > ??
- ????<title></title> ??
- </head> ??
- <body> ??
- ????<%?SelectList?categories?=?ViewData[ "Categories" ]? as ?SelectList;?%> ??
- ????<div> ??
- ????????<h1>MVC公告發布系統——發布公告</h1> ??
- ????????<%?Html.BeginForm( "DoRelease" , "Announce" ,FormMethod.Post);?%> ??
- ????????<dl> ??
- ????????????<dt>標題:</dt> ??
- ????????????<dd><%=?Html.TextBox( "Title" )?%></dd> ??
- ????????????<dd><%=?Html.ValidationMessage( "TitleValidator" )?%></dd> ??
- ????????????<dt>分類:</dt> ??
- ????????????<dd><%=?Html.DropDownList( "Category" ,categories)?%></dd> ??
- ????????????<dd></dd> ??
- ????????????<dt>內容:</dt> ??
- ????????????<dd><%=?Html.TextArea( "Content" )?%></dd> ??
- ????????????<dd><%=?Html.ValidationMessage( "ContentValidator" )?%></dd> ??
- ????????</dl> ??
- ????????<input?type= "submit" ?value= "發布" ?/> ??
- ????????<%?Html.EndForm();?%> ??
- ????</div> ??
- </body> ??
- </html>??
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs" Inherits="MVCDemo.Views.Announce.Release" %> <%@ Import Namespace="MVCDemo.Models.Entities" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"]]> > <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title></title> </head> <body> <% SelectList categories = ViewData["Categories"] as SelectList; %> <div> <h1>MVC公告發布系統——發布公告</h1> <% Html.BeginForm("DoRelease","Announce",FormMethod.Post); %> <dl> <dt>標題:</dt> <dd><%= Html.TextBox("Title") %></dd> <dd><%= Html.ValidationMessage("TitleValidator") %></dd> <dt>分類:</dt> <dd><%= Html.DropDownList("Category",categories) %></dd> <dd></dd> <dt>內容:</dt> <dd><%= Html.TextArea("Content") %></dd> <dd><%= Html.ValidationMessage("ContentValidator") %></dd> </dl> <input type="submit" value="發布" /> <% Html.EndForm(); %> </div> </body> </html>?
????? 可以看到,并沒有什么大的變動,只是多了兩個Html.ValidationMessage方法。可以這樣理解,這個方法相當于產生一個span標簽,而這個span就是要顯示錯誤信息的地方。這個方法接收一個參數,用來指明其在Controller中的名字。如果你對這個迷惑,不要緊,接下來看完 Controller的代碼,你就什么都清楚了。
AnnounceController.cs:
- using ?System; ??
- using ?System.Collections.Generic; ??
- using ?System.Linq; ??
- using ?System.Web; ??
- using ?System.Web.Mvc; ??
- using ?System.Web.Mvc.Ajax; ??
- using ?MVCDemo.Models; ??
- using ?MVCDemo.Models.Interfaces; ??
- using ?MVCDemo.Models.Entities; ??
- ??
- namespace ?MVCDemo.Controllers ??
- { ??
- ???? public ? class ?AnnounceController?:?Controller ??
- ????{ ??
- ???????? public ?ActionResult?Release() ??
- ????????{ ??
- ????????????ICategoryService?cServ?=?ServiceBuilder.BuildCategoryService(); ??
- ????????????List<CategoryInfo>?categories?=?cServ.GetAll(); ??
- ????????????ViewData[ "Categories" ]?=? new ?SelectList(categories,? "ID" ,? "Name" ); ??
- ???????????? return ?View( "Release" ); ??
- ????????} ??
- ???????? //?????http://www.my400800.cn ??
- ???????? public ?ActionResult?DoRelease() ??
- ????????{ ??
- ???????????? if ?(String.IsNullOrEmpty(Request.Form[ "Title" ])?||?String.IsNullOrEmpty(Request.Form[ "Content" ])) ??
- ????????????{ ??
- ???????????????? if ?(String.IsNullOrEmpty(Request.Form[ "Title" ])) ??
- ????????????????{ ??
- ????????????????????ViewData.ModelState.AddModelError( "TitleValidator" , "公告標題不能為空!" ); ??
- ????????????????} ??
- ???????????????? if ?(String.IsNullOrEmpty(Request.Form[ "Content" ])) ??
- ????????????????{ ??
- ????????????????????ViewData.ModelState.AddModelError( "ContentValidator" ,? "公告內容不能為空!" ); ??
- ????????????????} ??
- ??
- ???????????????? return ?Release(); ??
- ????????????} ??
- ??
- ????????????AnnounceInfo?announce?=? new ?AnnounceInfo() ??
- ????????????{ ??
- ????????????????ID?=?1, ??
- ????????????????Title?=?Request.Form[ "Title" ], ??
- ????????????????Category?=?Int32.Parse(Request.Form[ "Category" ]), ??
- ????????????????Content?=?Request.Form[ "Content" ], ??
- ????????????}; ??
- ??
- ????????????IAnnounceService?aServ?=?ServiceBuilder.BuildAnnounceService(); ??
- ????????????aServ.Release(announce); ??
- ??
- ????????????ViewData[ "Announce" ]?=?announce; ??
- ???????????? return ?View( "ReleaseSucceed" ); ??
- ????????} ??
- ????} ??
- }??
using System; using System.Collections.Generic; using System.Linq; using System.Web; using System.Web.Mvc; using System.Web.Mvc.Ajax; using MVCDemo.Models; using MVCDemo.Models.Interfaces; using MVCDemo.Models.Entities; namespace MVCDemo.Controllers { public class AnnounceController : Controller { public ActionResult Release() { ICategoryService cServ = ServiceBuilder.BuildCategoryService(); List<CategoryInfo> categories = cServ.GetAll(); ViewData["Categories"] = new SelectList(categories, "ID", "Name"); return View("Release"); } // http://www.my400800.cn public ActionResult DoRelease() { if (String.IsNullOrEmpty(Request.Form["Title"]) || String.IsNullOrEmpty(Request.Form["Content"])) { if (String.IsNullOrEmpty(Request.Form["Title"])) { ViewData.ModelState.AddModelError("TitleValidator","公告標題不能為空!"); } if (String.IsNullOrEmpty(Request.Form["Content"])) { ViewData.ModelState.AddModelError("ContentValidator", "公告內容不能為空!"); } return Release(); } AnnounceInfo announce = new AnnounceInfo() { ID = 1, Title = Request.Form["Title"], Category = Int32.Parse(Request.Form["Category"]), Content = Request.Form["Content"], }; IAnnounceService aServ = ServiceBuilder.BuildAnnounceService(); aServ.Release(announce); ViewData["Announce"] = announce; return View("ReleaseSucceed"); } } }?
?
????? 可以看到,我們的DoRelease這個Action方法多了不少東西。我們看多了什么:當從表單傳遞過來的標題或內容為空時,我們做了一定處理。注意,這個ViewData.ModelState.AddModelError方法,它就是往我們剛才說的由Html.ValidationMessage生成的span里加入錯誤信息的方法,它可以有兩個參數,第一個指明哪個span,這個參數Html.ValidationMessage中的參數是對應的。第二個參數就是要顯示的信息。
????? 相信結合視圖和控制器,已經很好理解了。最后,如果標題或內容有空值的話,我們不再調用業務邏輯組件處理了,而是調用了Release這個Action。為什么我們不用Redirect呢?因為我們要保持ViewData中的數據,剛才我們的錯誤信息可都放在里面的,而使用了 Redirect,ViewData的信息就傳不過去了。
????? 現在,我們再來發布
400電話
公告。我們故意什么都不填,提交,看結果:
????? 也許你有一個疑問,為什么第一次請求Release視圖時沒有顯示任何錯誤信息呢?因為那時ViewData中的ModelError是空的。而 Html.ValidationMessage生成的標簽會自動尋找ModelError中同名的錯誤信息,找不到,當然是空的了。而在提交空信息時,DoRelease這個Action為ViewData的ModelError添加了內容,于是當再次返回Release視圖時,相應信息就顯示在我們指定的位置了。
使用ASP.NET AJAX實現客戶端數據驗證
????? 上面的代碼運行起來沒問題,也達到了我們的要求。但是驗證標題內容是否為空這種行為在客戶端應該就可以完成。當然,為了放置惡意攻擊或瀏覽器將 JavaScript屏蔽的情況,我們應該在后臺進行驗證,但是我們不能每次都將這種請求發到后臺去驗證,這太費資源了,畢竟惡意攻擊者和 JavaScript被屏蔽的瀏覽器只是少數。所以,在數據被送到后臺前,我們應該先進行一遍驗證,這樣可以節約很多資源。
????? 下面,我們使用ASP.NET AJAX框架完成客戶端的數據驗證。
????? 說實話,在ASP.NET MVC中使用ASP.NET AJAX或JQuery實在太方便了,不信你展開Scripts文件夾,看到沒,微軟已經把這些庫放到里面了,所以,我們要做的只是直接引用。看我們修改后的Release.aspx。
Release.aspx:
- <%@?Page?Language= "C#" ?AutoEventWireup= "true" ?CodeBehind= "Release.aspx.cs" ?Inherits= "MVCDemo.Views.Announce.Release" ?%> ??
- <%@?Import?Namespace= "MVCDemo.Models.Entities" ?%> ??
- ??
- <!DOCTYPE?html?PUBLIC? "-//W3C//DTD?XHTML?1.0?Transitional//EN" ? "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" > ??
- ??
- <html?xmlns= "http://www.w3.org/1999/xhtml" ?> ??
- <head?runat= "server" > ??
- ????<title></title> ??
- ????<script?type= "text/javascript" ?src= "<%=?Url.Content(" ~/Scripts/MicrosoftAjax.debug.js ")?%>" ></script> ??
- ????<script?type= "text/javascript" ?src= "<%=?Url.Content(" ~/Scripts/MicrosoftAjaxValidate.js ")?%>" ></script> ??
- </head> ??
- <body> ??
- ????<%?SelectList?categories?=?ViewData[ "Categories" ]? as ?SelectList;?%> ??
- ????<div> ??
- ????????<h1>MVC公告發布系統——發布公告</h1> ??
- ????????<%?Html.BeginForm( "DoRelease" , "Announce" ,FormMethod.Post);?%> ??
- ????????<dl> ??
- ????????????<dt>標題:</dt> ??
- ????????????<dd><%=?Html.TextBox( "Title" )?%></dd> ??
- ????????????<dd><span?id= "TitleValidator" ></span></dd> ??
- ????????????<dt>分類:</dt> ??
- ????????????<dd><%=?Html.DropDownList( "Category" ,categories)?%></dd> ??
- ????????????<dd></dd> ??
- ????????????<dt>內容:</dt> ??
- ????????????<dd><%=?Html.TextArea( "Content" )?%></dd> ??
- ????????????<dd><span?id= "ContentValidator" ></span></dd> ??
- ????????</dl> ??
- ????????<input?id= "Submit" ?type= "submit" ?value= "發布" ?/> ??
- ????????<%?Html.EndForm();?%> ??
- ????</div> ??
- </body> ??
- </html>??
<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="Release.aspx.cs" Inherits="MVCDemo.Views.Announce.Release" %> <%@ Import Namespace="MVCDemo.Models.Entities" %> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" > <head runat="server"> <title></title> <script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjax.debug.js") %>"></script> <script type="text/javascript" src="<%= Url.Content("~/Scripts/MicrosoftAjaxValidate.js") %>"></script> </head> <body> <% SelectList categories = ViewData["Categories"] as SelectList; %> <div> <h1>MVC公告發布系統——發布公告</h1> <% Html.BeginForm("DoRelease","Announce",FormMethod.Post); %> <dl> <dt>標題:</dt> <dd><%= Html.TextBox("Title") %></dd> <dd><span id="TitleValidator"></span></dd> <dt>分類:</dt> <dd><%= Html.DropDownList("Category",categories) %></dd> <dd></dd> <dt>內容:</dt> <dd><%= Html.TextArea("Content") %></dd> <dd><span id="ContentValidator"></span></dd> </dl> <input id="Submit" type="submit" value="發布" /> <% Html.EndForm(); %> </div> </body> </html>?
????? 改動有兩處,首先我們在頁頭引用了兩個js文件,第一個是ASP.NET AJAX的庫文件,第二個就是我們一會要實現的包含驗證代碼的js文件了。你可能注意到那個Url.Content了,Url是ViewPage的一個對象,它最常用的一個方法就是Content,它的功能是返回某個文件的路徑。一般情況下,在使用了ASP.NET MVC后,目錄結構變得有點詭異,像js、css、圖片等與路徑(即使是相對路徑)引用相關的地方可能會出現問題,但是,只要你在這些地方用 Url.Content生成路徑,而不是直接將路徑寫在頁面里,一般就沒什么問題了。所以,凡是引用js、css、圖片等除,請一定使用 Url.Content生成路徑,其參數只有一個,就是文件原始的相對路徑。
????? 下一個改動就是顯示錯誤信息的span不再是Html.ValidationMessage生成的了,而是普通的span。
????? 下面我們在Scripts目錄下新建MicrosoftAjaxValidate.js文件。
MicrosoftAjaxValidate.js:
- function ??onPageInit()??{ ??
- ?????$addHandler($get(? "?Submit?" ?),?? "?click?" ?,?validate); ??
- } ??
- ??
- function ??validate()??{ ??
- ????? if ??($get(? "?Title?" ?).value??==??? "" ???||??$get(? "?Content?" ?).value??==??? "" ?)??{ ??
- ????????? if ??($get(? "?Title?" ?).value??==??? "" ?)??{ ??
- ????????????$get(? "?TitleValidator?" ?).innerHTML??=??? "?標題不能為空!?" ?; ??
- ????????} ??
- ????????? if ??($get(? "?Content?" ?).value??==??? "" ?)??{ ??
- ????????????$get(? "?ContentValidator?" ?).innerHTML??=??? "?內容不能為空!?" ?; ??
- ????????} ??
- ??
- ????????? return ??? false ?; ??
- ????} ??
- ??
- ????? return ??? true ?; ??
- }???
function onPageInit() { $addHandler($get( " Submit " ), " click " , validate); } function validate() { if ($get( " Title " ).value == "" || $get( " Content " ).value == "" ) { if ($get( " Title " ).value == "" ) { $get( " TitleValidator " ).innerHTML = " 標題不能為空! " ; } if ($get( " Content " ).value == "" ) { $get( " ContentValidator " ).innerHTML = " 內容不能為空! " ; } return false ; } return true ; }?
????? 關于這段代碼我不多說了,對ASP.NET AJAX有興趣的可以參看《ASP.NET AJAX客戶端編程之旅》系列文章。
????? 現在運行,將標題和內容留空,提交。OK!效果和剛才很像,只不過這次是在客戶端驗證了,并沒有提交到服務器端。
整合JQuery
????? 下面我們再使用JQuery實現這個功能。
????? 其實看懂上面的實現后,我想你已經想到怎么整合JQuery了,無非也是引入相應庫和js文件,然后使用JQuery編寫驗證代碼。修改后的 Release.aspx就沒必要看了,無非是引入Scripts目錄下的JQuery庫,然后再引入一個自定義驗證js文件,我們姑且叫 JQueryValidate.js吧。
????? 下面在Scripts目錄下新建JQueryValidate.js,代碼如下。
JQueryValidate.js:
- $(document).ready(function(){ ??
- ????$( "#Submit" ).click(function()?{ ??
- ???????? if ?($( "#Title" ).attr( "value" )?==? "" ?||?$( "#Content" ).attr( "value" )?==? "" )?{ ??
- ???????????? if ?($( "#Title" ).attr( "value" )?==? "" )?{ ??
- ????????????????$( "#TitleValidator" ).attr( "innerHTML" ,? "標題不能為空!" ); ??
- ????????????} ??
- ???????????? if ?($( "#Content" ).attr( "value" )?==? "" )?{ ??
- ????????????????$( "#ContentValidator" ).attr( "innerHTML" ,? "內容不能為空!" ); ??
- ????????????} ??
- ??
- ???????????? return ? false ; ??
- ????????} ??
- ??
- ???????? return ? true ; ??
- ????} ??
- ????); ??
- } ??
- );??
$(document).ready(function(){ $("#Submit").click(function() { if ($("#Title").attr("value") == "" || $("#Content").attr("value") == "") { if ($("#Title").attr("value") == "") { $("#TitleValidator").attr("innerHTML", "標題不能為空!"); } if ($("#Content").attr("value") == "") { $("#ContentValidator").attr("innerHTML", "內容不能為空!"); } return false; } return true; } ); } );?
小結
????? 從本文可以看出,在MVC框架中整合Ajax和普通應用差別不大,唯一就是注意在引用外部js時使用Url.Content方法處理一下相對路徑。其實在本文中我們并沒有使用到Ajax,而僅僅是整合了JavaScirpt,但是這已經足夠了,因為Ajax無非就是在這些JavaScript里包含了異步后臺調用。
????? 其實,ASP.NET MVC有專門針對ASP.NET AJAX的擴展,放在MicrosoftMvcAjax.js里。而在ViewPage里有個叫Ajax的AjaxHelper對象,可以實現一些簡單的異步調用。但是這個擴展的功能很有限,有興趣的可以自己研究一下。我個人還是建議大家自己寫JS代碼,當然可以使用ASP.NET AJAX或JQeury這樣優秀的框架。
????? 這篇文章先到這里,下一篇中我們討論一下攔截器的使用。^_^
from:http://ljl-xyf.iteye.com/blog/
更多文章、技術交流、商務合作、聯系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號聯系: 360901061
您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對您有幫助就好】元
