La serialización del método .Json del controlador ASP.NET MVC 3 no tiene en cuenta la atribución del nombre del miembro de datos

En mi clase tengo:

[DataMember(Name = "jsonMemberName", EmitDefaultValue = false, 
    IsRequired = false)]
public List<string> Member { get; set; }

Después de pasar el objeto a través del controlador Json (obj) que devuelve System.Web.Mvc.JsonResult: tengo json serializado: {Member: ...} pero no {jsonMemberName: ...}, por lo que no se ve en DataMember (Nombre = "jsonMemberName").

Si uso la serialización de System.Runtime.Serialization.Json, Everithing funciona bien como se esperaba.

¿Qué puede estar mal?

preguntado el 16 de mayo de 11 a las 17:05

2 Respuestas

La JsonResult acción que está regresando de la acción del controlador (usando return Json(...)) se basa internamente en el JavaScriptSerializer clase. Esta clase no tiene en cuenta ninguna DataMember atributos en su modelo.

Puede escribir un ActionResult personalizado que utilice el serializador en el System.Runtime.Serialization.Json espacio de nombres

Por ejemplo:

public class MyJsonResult : JsonResult
{
    public override void ExecuteResult(ControllerContext context)
    {
        var response = context.HttpContext.Response;
        if (!string.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = this.ContentEncoding;
        }
        if (Data != null)
        {
            var serializer = new DataContractJsonSerializer(Data.GetType());
            serializer.WriteObject(response.OutputStream, Data);
        }
    }
}

y luego en la acción de su controlador:

public ActionResult Foo()
{
    var model = ...
    return new MyJsonResult { Data = model };
}

contestado el 16 de mayo de 11 a las 21:05

Entonces, ¿hay una solución? Sin cambiar el nombre de los miembros en la clase, porque es feo. - EL COLOR BLANCO

@WHITECOLOR, claro, escribe un personalizado ActionResult. - Darin Dimitrov

Sería bueno votar por una solicitud de cambio o similar en MVC. ¿Cuál sería el inconveniente si el JSONResult predeterminado usara DataContractJsonSerializer. ¿Rompería algo? - Konstantin

System.Web.Mvc.JsonResult usa el viejo JavaScriptSerializer class, que no sabe nada sobre el ensamblado DataAnnotiations. Necesitas usar el DataContractJsonSerializer en vez.

Puede usar esto en su lugar en JsonResult si así lo desea:

public class DataContractJsonResult : JsonResult
{
    public DataContractJsonResult(object data)
    {
        Data = data;
    }

    public DataContractJsonResult()
    {
    }

    public override void ExecuteResult(ControllerContext context)
    {
        if (context == null)
        {
            throw new ArgumentNullException("context");
        }
        if (JsonRequestBehavior == JsonRequestBehavior.DenyGet &&
            String.Equals(context.HttpContext.Request.HttpMethod, "GET", StringComparison.OrdinalIgnoreCase))
        {
            throw new InvalidOperationException("This request has been blocked because sensitive information could be disclosed to third party web sites when this is used in a GET request. To allow GET requests, set JsonRequestBehavior to AllowGet.");
        }

        HttpResponseBase response = context.HttpContext.Response;

        if (!string.IsNullOrEmpty(ContentType))
        {
            response.ContentType = ContentType;
        }
        else
        {
            response.ContentType = "application/json";
        }
        if (ContentEncoding != null)
        {
            response.ContentEncoding = ContentEncoding;
        }
        if (Data != null)
        {
            var serializer = new DataContractJsonSerializer(Data.GetType());
            var ms = new MemoryStream();
            serializer.WriteObject(ms, Data);
            string json = Encoding.UTF8.GetString(ms.ToArray());
            response.Write(json);
        }
    }
}

(Hice referencia al código fuente de ASP.NET MVC para crear esto. No estoy seguro si tengo que acreditarlo de alguna manera. Bueno, más que esto ya es, claro. :))

También puede agregar esto a una clase base de la que heredan sus controladores:

protected JsonResult DataContractJson(object data)
{
    return new DataContractJsonResult(data);
}

contestado el 16 de mayo de 11 a las 21:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.