7

MVC3帶有JsonValueProviderFactory()方法,這對於將傳入的JSON綁定到模型非常方便。不幸的是,我無法弄清楚如何使用與傳入的JSON不同的名稱來設置模型合約。例如:DataContract模型綁定到ASP.NET MVC中的JSON Action方法參數

[DataContract(Name = "session")] 
public class FacebookSession 
{ 
    [DataMember(Name = "access_token")] 
    public string AccessToken { get; set; } 

    [DataMember(Name = "expires")] 
    public int? Expires { get; set; } 

    [DataMember(Name = "secret")] 
    public string Secret { get; set; } 

    [DataMember(Name = "session_key")] 
    public string Sessionkey { get; set; } 

    [DataMember(Name = "sig")] 
    public string Signature { get; set; } 

    [DataMember(Name = "uid")] 
    public string UserId { get; set; } 
} 
路過時在JSON對象代表Facebook的會議上,性能和祕密綁定到期正確,但其餘的不要因爲屬性名稱是不是json的鍵名不同

。我期望datacontract序列化程序會嘗試綁定到屬性中提供的名稱,但似乎並非如此。有沒有人有任何解決方法建議?

編輯

的我怎麼會用這種模式的一個例子:

public ActionResult Log(int? custId, FacebookSession response) 
    {  
      ViewBag.Id = response.UserId;       
      return View(); 
    } 

回答

6

最後我用gt124的鏈接model binder examplea better model binder一起寫我自己的模型綁定邏輯。它結束了看起來像這樣:

public interface IFilteredModelBinder : IModelBinder 
    { 
     bool IsMatch(Type modelType); 
    } 

public class SmartModelBinder : DefaultModelBinder 
{ 
    private readonly IFilteredModelBinder[] _filteredModelBinders; 

    public SmartModelBinder(IFilteredModelBinder[] filteredModelBinders) 
    { 
     _filteredModelBinders = filteredModelBinders; 
    } 

    public override object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     foreach (var filteredModelBinder in _filteredModelBinders) 
     { 
      if (filteredModelBinder.IsMatch(bindingContext.ModelType)) 
      { 
       return filteredModelBinder.BindModel(controllerContext, bindingContext); 
      } 
     } 

     return base.BindModel(controllerContext, bindingContext); 
    } 
} 

public class NewtonsoftJsonModelBinder : IFilteredModelBinder 
{ 
    public object BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) 
    { 
     if (!controllerContext.HttpContext.Request.ContentType.StartsWith("application/json", StringComparison.OrdinalIgnoreCase)) 
     { 
      // not JSON request 
      return null; 
     } 

     var request = controllerContext.HttpContext.Request; 
     request.InputStream.Position = 0; 
     var incomingData = new StreamReader(request.InputStream).ReadToEnd(); 

     if (String.IsNullOrEmpty(incomingData)) 
     { 
      // no JSON data 
      return null; 
     } 
     object ret = JsonConvert.DeserializeObject(incomingData, bindingContext.ModelType); 
     return ret; 
    } 

    public bool IsMatch(Type modelType) 
    { 
     var ret = (typeof(JsonModel).IsAssignableFrom(modelType)); 
     return ret; 
    } 
} 

然後我用JSON.net屬性映射到對模型中的不同對象的屬性(而不是DataContracts)。模型都從一個空的基類JsonModel繼承。

+2

確保你替換了默認的綁定:Application_Start:ModelBinders.Binders.DefaultBinder = new SmartModelBinder(new [] {new NewtonsoftJsonModelBinder()} );' – TodK 2012-03-16 14:51:07

1

你可以把它作爲一個字符串,並手動調用datacontractdeserializer,除非你自己寫ModelBinder的。我相信默認聯編程序使用javascriptserializer,而不是datacontractjsserializer。

Model Binder Example

+0

這不起作用,響應是=爲空。我的意思是,我可以在js調用中做JSON.Stringify(),但這會讓我感到難過。 – 2011-04-08 19:37:58

+0

上面的例子可能會給你足夠的寫一個使用datacontractjsonserializer的modelbinder ... – gt124 2011-04-08 19:55:16

0

您不需要替換默認的粘結劑,只寫這樣

public class DataContractJsonModelBinderAttribute : CustomModelBinderAttribute 
{ 
    public override IModelBinder GetBinder() 
    { 
     return new DataContractJsonModelBinder(); 
    } 
} 
的使用

屬性是簡單

[DataContract(Name = "session")] 
[DataContractJsonModelBinder] 
public class FacebookSession 
{ 
    [DataMember(Name = "access_token")] 
    public string AccessToken { get; set; } 

    [DataMember(Name = "expires")] 
    public int? Expires { get; set; } 

    [DataMember(Name = "secret")] 
    public string Secret { get; set; } 

    [DataMember(Name = "session_key")] 
    public string Sessionkey { get; set; } 

    [DataMember(Name = "sig")] 
    public string Signature { get; set; } 

    [DataMember(Name = "uid")] 
    public string UserId { get; set; } 
} 

UPDATE現在Y可以簡單地使用內置的Json.NET功能如下:

[JsonObject] 
public class FacebookSession 
{ 
    [JsonProperty("access_token")] 
    public string AccessToken { get; set; } 
} 

並且如果需要的話

var facebokSession = JsonConvert.DeserializeObject<FacebookSession>(facebookSessionJsonString); 
+1

看起來很有前途。但我在哪裏可以找到'DataContractJsonModelBinder'? – 2014-06-20 21:28:21

+0

@Simon_Weaver,更新了答案 – mumu2 2014-06-23 11:23:34