2012-07-23 27 views
10

Estoy publicando json con nombres de variables con guiones bajos (like_this) y tratando de enlazar a un modelo que está encasillado (LikeThis), pero los valores no se pueden enlazar.Vinculación del modelo MVC 3 con guiones bajos

Sé que podría escribir un encuadernador de modelo personalizado, pero dado que la convención subrayada es tan común, esperaría que ya existiera una solución.

La acción/modelo que estoy tratando de colocar a es:

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

y los datos JSON es como:

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

(por desgracia no puedo cambiar ni el nombramiento de cualquiera el JSON o el modelo)

+2

muéstranos el código – Shyju

+0

añadido, realmente no es nada emocionante ... –

+0

¿por qué no cambiar el JSON para que coincida con los nombres de las propiedades del modelo? – Shyju

Respuesta

10

puede empezar a escribir un 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()); 
    } 
} 

Esto es para su caso particular, becase necesita un snake caseContractResolver:

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

entonces usted puede escribir un atributo personalizado para decorar sus acciones del controlador:

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

Y por último:

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

Buscando algo así por algún tiempo. ¡¡¡Gracias!!! – MilkyWayJoe

+1

Encontrará que la serialización de PropertyNames como DOBProperty se resolverá como d_o_b_property - [esta respuesta] (http://stackoverflow.com/a/7275039/159341) ofrece mejores resultados si necesita atender este caso de uso. – Tr1stan

Cuestiones relacionadas