ASP.NET MVC中的Json Binding和Validate

來源:互聯網
上載者:User

引子:電子商務網站支付功能頁面往往會有很多資訊,對於這些資訊的儲存,往往是分步完成的,那麼使用Ajax最合適不過了,比如其中的收貨人資訊模組。這些資訊的建立和編輯儲存都是用Ajax來完成的。那麼有幾種方式完成這個操作呢,我想到如下幾種。

先來看看該功能的:

一般情況下這些資訊會對應一個實體類,就命名為:ReceiverInfo,簡單起見,我定義ReceiverInfo如下:


1、將需要的值拼接成json文本,再Action裡面處理

首先您需要將要儲存的值拼接成一個json文本,類似:

var test = "{ ReceiverId: 5, ReceiverName: 'will', Sex: 'F', CreateDate: '2011-02-21' }";

然後用Jquery儲存到資料庫,代碼如下:

$.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實現


JsonBinder

 1 public class JsonBinder<T> : IModelBinder
2 {
3 public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)
4 {
5 StreamReader reader = new StreamReader(controllerContext.HttpContext.Request.InputStream);
6 string json = reader.ReadToEnd();
7
8 if (string.IsNullOrEmpty(json))
9 return json;
10
11 JavaScriptSerializer serializer = new JavaScriptSerializer();
12 object jsonData = serializer.DeserializeObject(json);
13 return serializer.Deserialize<T>(json);
14 }
15 }


我們繼承IModelBinder介面,實現其 方法:

public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext)

即可。我們可以在Action裡面這樣使用:

public ActionResult Test1([ModelBinder(typeof(JsonBinder<ReceiverInfo>))] ReceiverInfo receiverInfo)

這樣我們自訂的 IModelBinder就會取代DefaultModelBinder完成資料繫結。


3、直接傳遞一個Json對象

上面兩種方法並沒有利用MVC的System.ComponentModel.DataAnnotations進行有效資料驗證。您可能需要自己手動驗證,無疑增加了工作量。

我們試試這種方式。

前端的寫法:

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)

我們能正常的得到綁定後的資料。而且我們還能利用System.ComponentModel.DataAnnotations進行資料驗證。我們為ReceiverInfo做如下改動:

[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "收貨人必須填寫")]
public string ReceiverName { get; set; }

並在前端為ReceiverName賦值為空白字串,再次執行,得到提示:

很好,不過我們有新的要求了,那就是傳遞更複雜的對象,比如對象套嵌對象,對象有集合屬性,這種方式不能勝任了。


4、利用MvcFutures的JsonValueProviderFactory

每一版的MVC都有一個MvcFutures,裡面會有一些額外的功能,這些功能有些會加入下一個版本中,而這些功能在某些時候很有用處。我查看了裡面的類,發現有一個類JsonValueProviderFactory正是處理複雜物件的提交和資料驗證。由於json對象需要特定解析才能使用預設的DefaultModelBinder,而這個解析過程需要在ValueProvider階段完成,所以需要實現特定的ValueProvider給DefaultModelBinder。我們需要實現一個ValueProviderFactory和IValueProvider,而MVC裡面的DictionaryValueProvider<TValue>(繼承了IValueProvider)已經足夠使用了,所以只需要繼承ValueProviderFactory實現其方法:public override IValueProvider GetValueProvider(ControllerContext controllerContext)即可,具體代碼您可以看JsonValueProviderFactory。

我們定義另一個類:

ReceiverInfoChild

public class ReceiverInfoChild
{
[System.ComponentModel.DataAnnotations.Required(ErrorMessage = "ChildId必須填寫")]
public string ChildId { get; set; }
}

並為類ReceiverInfo增加一個屬性public List<ReceiverInfoChild> ReceiverInfoChild { get; set; }

我們把JsonValueProviderFactory拿出來放在項目裡面,然後在Global.asax裡面註冊一下,就可以使用了。

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();

RegisterRoutes(RouteTable.Routes);

ValueProviderFactories.Factories.Add(new JsonValueProviderFactory());
}

因為JsonValueProviderFactory中有:if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase))來判斷進來的請求是不是json對象,所以我們提交資料的時候需要這樣寫:

 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對象轉換成字串,您可以到這裡下載該類庫。

在Action裡面,我們這樣寫就可以了:

public ActionResult Test1(List<ReceiverInfo> receiverInfo)

看一下調試的結果:

完全正常綁定了值。我們再看看資料驗證:

至此,我們實驗了四種方案:

第一種方案,最麻煩,而且容易出錯(可能跟我個人不喜歡拼接字串有關係);

第二種方案,有一定的通用性,但是不利於資料驗證;

第三種方案,通用,可以進行有效資料驗證,應對一般的需求夠用了,但是處理更複雜的對象不行;

第四種方案,幾乎可以處理我們遇到的所有情況

另外,這是在ASP.NET MVC2中的使用,到了ASP.NET MVC3,微軟已經把JsonValueProviderFactory作為內建的功能了。

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.