2012-07-23 14 views
10

Zamieszczam json z nazwami zmiennych z podkreśleniami (like_this) i próbuję powiązać z modelem, który jest camelcased (LikeThis), ale wartości nie można powiązać.Wiązanie modelu MVC 3 z podkreśleniami

Wiem, że mógłbym napisać niestandardowy segregator, ale ponieważ ta podkreślona konwencja jest tak powszechna, spodziewałbym się, że rozwiązanie już istnieje.

Akcja/modelu Próbuję odpowiedzieć na to:

/* 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; } 
} 

a dane json jest jak:

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

(Niestety nie mogę zmienić albo nazywanie albo JSON lub model)

+2

pokaż nam kod – Shyju

+0

dodano, to naprawdę nic ciekawego ... –

+0

dlaczego nie zmienić JSON, aby pasował do nazw właściwości Modelu? – Shyju

Odpowiedz

10

można rozpocząć pisanie 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()); 
    } 
} 

To jest dla konkretnego przypadku, becase potrzebny jest snake caseContractResolver:

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

Następnie można napisać niestandardowy atrybut ozdobić swoje działania kontrolera:

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; 
     } 
    } 
} 

i wreszcie:

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

Szukam czegoś takiego od jakiegoś czasu. Dzięki!!! – MilkyWayJoe

+1

Przekonasz się, że serializacja nazw właściwości takich jak DOBProperty zostanie rozwiązana jako d_o_b_property - [ta odpowiedź] (http://stackoverflow.com/a/7275039/159341) daje lepszy wynik, jeśli potrzebujesz uwzględnić ten przypadek użycia. – Tr1stan

Powiązane problemy