如何利用ASP.NET MVC保存電子商務(wù)網(wǎng)站用戶信息
電子商務(wù)網(wǎng)站支付功能頁面往往會(huì)有很多信息,對(duì)于這些信息的保存,往往是分步完成的,那么使用Ajax最合適不過了,比如其中的收貨人信息模塊。這些信息的新建和編輯保存都是用Ajax來完成的。那么有幾種方式完成這個(gè)操作呢,我想到如下幾種。
先來看看該功能的截圖:
一般情況下這些信息會(huì)對(duì)應(yīng)一個(gè)實(shí)體類,就命名為:ReceiverInfo,簡(jiǎn)單起見,我定義ReceiverInfo如下:
1、將需要的值拼接成json文本,再Action里面處理
首先您需要將要保存的值拼接成一個(gè)json文本,類似:
- var test = "{ ReceiverId: 5, ReceiverName: 'will', Sex: 'F', CreateDate: '2011-02-21' }";
然后用Jquery保存到數(shù)據(jù)庫,代碼如下:
- $.ajax({
- url: "/Home/test1",
- type: "post",
- cache: false,
- data: test});
然后您在Action里面這樣操作:
- StreamReader reader = new StreamReader(Request.InputStream);
- string bodyText = reader.ReadToEnd();
- JavaScriptSerializer js = new JavaScriptSerializer();
- ReceiverInfo receiver = js.Deserialize<ReceiverInfo>(bodyText);
- //保存。。。
2、利用自定義的ModelBinder實(shí)現(xiàn)
JsonBinder
- public class JsonBinder<T> : IModelBinder
- {
- public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
- {
- StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
- string json = reader.ReadToEnd();
- if (string.IsNullOrEmpty(json))
- return json;
- JavaScriptSerializer serializer = new JavaScriptSerializer();
- object jsonData = serializer.DeserializeObject(json);
- return serializer.Deserialize<T>(json);
- }
- }
我們繼承IModelBinder接口,實(shí)現(xiàn)其 方法:
- public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
即可。我們可以在Action里面這樣使用:
- public ActionResult Test1([ModelBinder(typeof(JsonBinder<ReceiverInfo>))] ReceiverInfo receiverInfo)
這樣我們自定義的 IModelBinder就會(huì)取代DefaultModelBinder完成數(shù)據(jù)綁定。
3、直接傳遞一個(gè)Json對(duì)象
上面兩種方法并沒有利用MVC的System.ComponentModel.DataAnnotations進(jìn)行有效的數(shù)據(jù)驗(yàn)證。您可能需要自己手動(dòng)驗(yàn)證,無疑增加了工作量。
我們?cè)囋囘@種方式。
前端的寫法
- var b = {
- ReceiverId: 5,
- ReceiverName: "will",
- Sex: "F",
- CreateDate: "2011-02-21"};$.ajax({
- url: "/Home/test1",
- type: "post",
- cache: false,
- data: b,
- success: function(data) { alert(data.message); },
- error: function(xhr, a, b) { alert
- (xhr.responseText); }});
Action的寫法:
- public ActionResult Test1(ReceiverInfo receiverInfo)
我們能正常的得到綁定后的數(shù)據(jù)。而且我們還能利用System.ComponentModel.DataAnnotations進(jìn)行數(shù)據(jù)驗(yàn)證。我們?yōu)镽eceiverInfo做如下改動(dòng):
- [System.ComponentModel.DataAnnotations.Required
- (ErrorMessage = "收貨人必須填寫")]public string ReceiverName { get; set; }
并在前端為ReceiverName賦值為空字符串,再次執(zhí)行,得到提示:
很好,不過我們有新的要求了,那就是傳遞更復(fù)雜的對(duì)象,比如對(duì)象套嵌對(duì)象,對(duì)象有集合屬性,這種方式不能勝任了。
4、利用MvcFutures的JsonValueProviderFactory
每一版的MVC都有一個(gè)MvcFutures,里面會(huì)有一些額外的功能,這些功能有些會(huì)加入下一個(gè)版本中,而這些功能在某些時(shí)候很有用處。我查看了里面的類,發(fā)現(xiàn)有一個(gè)類JsonValueProviderFactory正是處理復(fù)雜對(duì)象的提交和數(shù)據(jù)驗(yàn)證。由于json對(duì)象需要特定解析才能使用默認(rèn)的DefaultModelBinder,而這個(gè)解析過程需要在ValueProvider階段完成,所以需要實(shí)現(xiàn)特定的ValueProvider給DefaultModelBinder。我們需要實(shí)現(xiàn)一個(gè)ValueProviderFactory和IValueProvider,而MVC里面的DictionaryValueProvider<TValue>(繼承了IValueProvider)已經(jīng)足夠使用了,所以只需要繼承ValueProviderFactory實(shí)現(xiàn)其方法:public override IValueProvider GetValueProvider(ControllerContext controllerContext)即可,具體代碼您可以看JsonValueProviderFactory。
我們定義另一個(gè)類:
ReceiverInfoChild
- public class ReceiverInfoChild{
- [System.ComponentModel.DataAnnotations.Required
- (ErrorMessage = "ChildId必須填寫")]
- public string ChildId { get; set; }}
并為類ReceiverInfo增加一個(gè)屬性public List<ReceiverInfoChild> ReceiverInfoChild { get; set; }
我們把JsonValueProviderFactory拿出來放在項(xiàng)目里面,然后在Global.asax里面注冊(cè)一下,就可以使用了。
- protected void Application_Start(){
- AreaRegistration.RegisterAllAreas();
- RegisterRoutes(RouteTable.Routes);
- ValueProviderFactories.Factories.Add(new
- JsonValueProviderFactory());}
因?yàn)镴sonValueProviderFactory中有:if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))來判斷進(jìn)來的請(qǐng)求是不是json對(duì)象,所以我們提交數(shù)據(jù)的時(shí)候需要這樣寫:
- var ReceiverInfo = [
- {
- ReceiverInfoChild: [{ ChildId: "1" }, { ChildId: "11"}],
- ReceiverId: 5,
- ReceiverName: "will",
- Sex: "F",
- CreateDate: "2011-02-21"
- },
- {
- ReceiverInfoChild: [{ ChildId: "2" }, { ChildId: "22"}],
- ReceiverId: 5,
- ReceiverName: "will",
- Sex: "F",
- CreateDate: "2011-02-21" }
- ];$.ajax({
- url: "/Home/test1",
- type: "post",
- cache: false,
- contentType: "application/json;charset=utf-8",
- data: JSON.stringify(ReceiverInfo),
- success: function(data) { alert(data.message); },
- error: function(xhr, a, b) { alert(xhr.responseText); }});
其中JSON.stringify(ReceiverInfo)是將json對(duì)象轉(zhuǎn)換成字符串,您可以到這里下載該類庫。
在Action里面,我們這樣寫就可以了:
- public ActionResult Test1(List<ReceiverInfo> receiverInfo)
看一下調(diào)試的結(jié)果:
完全正常綁定了值。我們?cè)倏纯磾?shù)據(jù)驗(yàn)證:
至此,我們實(shí)驗(yàn)了四種方案:
第一種方案,最麻煩,而且容易出錯(cuò)(可能跟我個(gè)人不喜歡拼接字符串有關(guān)系);
第二種方案,有一定的通用性,但是不利于數(shù)據(jù)驗(yàn)證;
第三種方案,通用,可以進(jìn)行有效的數(shù)據(jù)驗(yàn)證,應(yīng)對(duì)一般的需求夠用了,但是處理更復(fù)雜的對(duì)象不行;
第四種方案,幾乎可以處理我們遇到的所有情況
另外,這是在ASP.NET MVC2中的使用,到了ASP.NET MVC3,微軟已經(jīng)把JsonValueProviderFactory作為內(nèi)置的功能了。
原文鏈接:http://www.cnblogs.com/WillMeng/archive/2011/03/01/json_binding_validate.html
【編輯推薦】
- 詳解ASP.NET MVC 3 beta新特性
- ASP.NET MVC 3讓依賴注入實(shí)現(xiàn)得更簡(jiǎn)單
- 詳解ASP.NET MVC 3 beta新特性
- ASP.NET MVC 3新特性與NuPack功能詳解
- .NET開發(fā)人員應(yīng)該關(guān)注的七個(gè)開源項(xiàng)目