Dada la siguiente clase,
public class Result
{
public bool Success { get; set; }
public string Message { get; set; }
}
Estoy devolviendo uno de estos en una acción de controlador como ese,
return Json(new Result() { Success = true, Message = "test"})
Sin embargo, mi marco del lado del cliente espera que estas propiedades sean éxito y mensaje en minúsculas. Sin tener que tener nombres de propiedad en minúsculas, ¿es esa una forma de lograr este pensamiento, la llamada normal a la función Json?
asp.net-mvc
json
James Hughes
fuente
fuente
Cambiar el serializador es simple si está usando la API web, pero desafortunadamente MVC sí lo usa
JavaScriptSerializer
sin opción para cambiar esto para usar JSON.Net.La respuesta de James y la respuesta de Daniel le brindan la flexibilidad de JSON.Net, pero significa que en todos los lugares donde normalmente lo haría
return Json(obj)
, debe cambiar areturn new JsonNetResult(obj)
o similar, lo que si tiene un gran proyecto podría resultar un problema, y tampoco es muy flexible si cambia de opinión sobre el serializador que desea utilizar.Decidí seguir la
ActionFilter
ruta. El siguiente código le permite realizar cualquier acción usandoJsonResult
y simplemente aplicarle un atributo para usar JSON.Net (con propiedades en minúsculas):[JsonNetFilter] [HttpPost] public ActionResult SomeJson() { return Json(new { Hello = "world" }); } // outputs: { "hello": "world" }
Incluso puede configurar esto para que se aplique automáticamente a todas las acciones (con solo el menor impacto de rendimiento de una
is
verificación):FilterConfig.cs
// ... filters.Add(new JsonNetFilterAttribute());
El código
public class JsonNetFilterAttribute : ActionFilterAttribute { public override void OnActionExecuted(ActionExecutedContext filterContext) { if (filterContext.Result is JsonResult == false) return; filterContext.Result = new CustomJsonResult((JsonResult)filterContext.Result); } private class CustomJsonResult : JsonResult { public CustomJsonResult(JsonResult jsonResult) { this.ContentEncoding = jsonResult.ContentEncoding; this.ContentType = jsonResult.ContentType; this.Data = jsonResult.Data; this.JsonRequestBehavior = jsonResult.JsonRequestBehavior; this.MaxJsonLength = jsonResult.MaxJsonLength; this.RecursionLimit = jsonResult.RecursionLimit; } public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); if (this.JsonRequestBehavior == JsonRequestBehavior.DenyGet && String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase)) throw new InvalidOperationException("GET not allowed! Change JsonRequestBehavior to AllowGet."); var response = context.HttpContext.Response; response.ContentType = String.IsNullOrEmpty(this.ContentType) ? "application/json" : this.ContentType; if (this.ContentEncoding != null) response.ContentEncoding = this.ContentEncoding; if (this.Data != null) { var json = JsonConvert.SerializeObject( this.Data, new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver() }); response.Write(json); } } } }
fuente
Con mi solución, puede cambiar el nombre de cada propiedad que desee.
Encontré parte de la solución aquí y en SO
public class JsonNetResult : ActionResult { public Encoding ContentEncoding { get; set; } public string ContentType { get; set; } public object Data { get; set; } public JsonSerializerSettings SerializerSettings { get; set; } public Formatting Formatting { get; set; } public JsonNetResult(object data, Formatting formatting) : this(data) { Formatting = formatting; } public JsonNetResult(object data):this() { Data = data; } public JsonNetResult() { Formatting = Formatting.None; SerializerSettings = new JsonSerializerSettings(); } public override void ExecuteResult(ControllerContext context) { if (context == null) throw new ArgumentNullException("context"); var response = context.HttpContext.Response; response.ContentType = !string.IsNullOrEmpty(ContentType) ? ContentType : "application/json"; if (ContentEncoding != null) response.ContentEncoding = ContentEncoding; if (Data == null) return; var writer = new JsonTextWriter(response.Output) { Formatting = Formatting }; var serializer = JsonSerializer.Create(SerializerSettings); serializer.Serialize(writer, Data); writer.Flush(); } }
Para que en mi controlador, pueda hacer eso
return new JsonNetResult(result);
En mi modelo, ahora puedo tener:
[JsonProperty(PropertyName = "n")] public string Name { get; set; }
Tenga en cuenta que ahora, debe configurar el
JsonPropertyAttribute
para cada propiedad que desee serializar.fuente
Aunque es una pregunta antigua, espero que el siguiente fragmento de código sea útil para otros.
Lo hice a continuación con MVC5 Web API.
public JsonResult<Response> Post(Request request) { var response = new Response(); //YOUR LOGIC IN THE METHOD //....... //....... return Json<Response>(response, new JsonSerializerSettings() { ContractResolver = new CamelCasePropertyNamesContractResolver() }); }
fuente
Puede agregar esta configuración a
Global.asax
, y funcionará en todas partes.public class Global : HttpApplication { void Application_Start(object sender, EventArgs e) { //.... JsonConvert.DefaultSettings = () => { var settings = new JsonSerializerSettings { ContractResolver = new CamelCasePropertyNamesContractResolver(), PreserveReferencesHandling = PreserveReferencesHandling.None, Formatting = Formatting.None }; return settings; }; //.... } }
fuente