2012-07-23 33 views
10

我使用带下划线的变量名称(like_this)发布json并试图绑定到camelcased模型(LikeThis),但这些值无法绑定。带下划线的MVC 3模型绑定

我知道我可以编写一个自定义的模型绑定器,但由于下划线约定如此常见,所以我期望解决方案已经存在。

动作/模型我想张贴的是:

/* in controller */ 
[HttpPost] 
public ActionResult UpdateArgLevel(UserArgLevelModel model) { 
    // do something with the data 
} 

/* model */ 
public class UserArgLevelModel { 
    public int Id { get; set; } 
    public string FirstName { get; set; } 
    public string Surname { get; set; } 
    public int ArgLevelId { get; set; } 
} 

和JSON数据是这样的:

{ 
    id: 420007, 
    first_name: "Marc", 
    surname: "Priddes", 
    arg_level_id: 4 
} 

(不幸的是我无法改变的任何命名要么JSON或模型)

+2

告诉我们一些代码 – Shyju 2012-07-23 13:13:36

+0

增加了,它真的没有什么令人兴奋的,但... – 2012-07-23 13:20:17

+0

为什么不改变JSON来匹配模型属性名称? – Shyju 2012-07-23 13:24:30

回答

10

您可以开始编写customJson.NETContractResolver

public class DeliminatorSeparatedPropertyNamesContractResolver : 
    DefaultContractResolver 
{ 
    private readonly string _separator; 

    protected DeliminatorSeparatedPropertyNamesContractResolver(char separator) 
     : base(true) 
    { 
     _separator = separator.ToString(); 
    } 

    protected override string ResolvePropertyName(string propertyName) 
    { 
     var parts = new List<string>(); 
     var currentWord = new StringBuilder(); 

     foreach (var c in propertyName) 
     { 
      if (char.IsUpper(c) && currentWord.Length > 0) 
      { 
       parts.Add(currentWord.ToString()); 
       currentWord.Clear(); 
      } 
      currentWord.Append(char.ToLower(c)); 
     } 

     if (currentWord.Length > 0) 
     { 
      parts.Add(currentWord.ToString()); 
     } 

     return string.Join(_separator, parts.ToArray()); 
    } 
} 

这是你的具体情况,becase的你需要一个snake caseContractResolver

public class SnakeCasePropertyNamesContractResolver : 
    DeliminatorSeparatedPropertyNamesContractResolver 
{ 
    public SnakeCasePropertyNamesContractResolver() : base('_') { } 
} 

然后,你可以写一个自定义属性来装饰您的控制器操作:

public class JsonFilterAttribute : ActionFilterAttribute 
{ 
    public string Parameter { get; set; } 
    public Type JsonDataType { get; set; } 
    public JsonSerializerSettings Settings { get; set; } 

    public override void OnActionExecuting(ActionExecutingContext filterContext) 
    {  
     if (filterContext.HttpContext.Request.ContentType.Contains("application/json")) 
     { 
      string inputContent; 
      using (var reader = new StreamReader(filterContext.HttpContext.Request.InputStream)) 
      { 
       inputContent = reader.ReadToEnd(); 
      } 

      var result = JsonConvert.DeserializeObject(inputContent, JsonDataType, Settings ?? new JsonSerializerSettings()); 
      filterContext.ActionParameters[Parameter] = result; 
     } 
    } 
} 

最后:

[JsonFilter(Parameter = "model", JsonDataType = typeof(UserArgLevelModel), Settings = new JsonSerializerSettings { ContractResolver = new SnakeCasePropertyNamesContractResolver() })] 
public ActionResult UpdateArgLevel(UserArgLevelModel model) { 
{ 
    // model is deserialized correctly! 
} 
+1

现在寻找类似的东西。谢谢!!! – MilkyWayJoe 2012-12-31 20:23:50

+1

你会发现像DOBProperty这样的PropertyNames的序列化会解析为d_o_b_property - [这个答案](http://stackoverflow.com/a/7275039/159341)给出了一个更好的结果,如果你需要迎合这个用例的话。 – Tr1stan 2014-06-24 07:55:09