Estoy usando una API web MVC 4 y formularios web asp.net 4.0 para construir una API de descanso. Funciona muy bien:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Ahora necesito evitar que algunas propiedades se serialicen. Sé que puedo usar algo de LINQ en la lista y obtener solo las propiedades que necesito, y generalmente es un buen enfoque, pero en el escenario actual el something
objeto es demasiado complejo y necesito un conjunto diferente de propiedades en diferentes métodos, por lo que es más fácil de marcar, en tiempo de ejecución, cada propiedad a ignorar.
¿Hay una manera de hacer eso?
c#
asp.net
asp.net-mvc
asp.net-web-api
usuario1330271
fuente
fuente
Respuestas:
La API web ASP.NET usa
Json.Net
como formateador predeterminado, por lo que si su aplicación solo usa JSON como formato de datos, puede usar[JsonIgnore]
para ignorar la propiedad para la serialización:Pero, de esta manera no es compatible con el formato XML. Entonces, en caso de que su aplicación tenga que admitir más el formato XML (o solo admitir XML), en lugar de usar
Json.Net
, debe usar el[DataContract]
que admite JSON y XML:Para una mejor comprensión, puede leer el artículo oficial .
fuente
De acuerdo con la página de documentación de la API web JSON y la serialización XML en la API web ASP.NET para evitar explícitamente la serialización en una propiedad que puede usar
[JsonIgnore]
para el serializador Json o[IgnoreDataMember]
para el serializador XML predeterminado.Sin embargo, en las pruebas, he notado que
[IgnoreDataMember]
evita la serialización de las solicitudes XML y Json, por lo que recomendaría usar eso en lugar de decorar una propiedad con múltiples atributos.fuente
[IgnoreDataMember]
, no parece funcionar con objetos proxy EF 6 con carga lenta (propiedades virtuales).[DataContract]
y[DataMember]
hacer, sin embargo.En lugar de permitir que todo se serialice de forma predeterminada, puede adoptar el enfoque de "suscripción". En este escenario, solo las propiedades que especifique se pueden serializar. Puede hacer esto con
DataContractAttribute
yDataMemberAttribute
, que se encuentra en el espacio de nombres System.Runtime.Serialization .Se
DataContactAttribute
aplica a la clase yDataMemberAttribute
se aplica a cada miembro que desea serializar:Me atrevo a decir que este es un mejor enfoque porque te obliga a tomar decisiones explícitas sobre lo que se hará o no a través de la serialización. También permite que sus clases modelo vivan en un proyecto por sí mismas, sin depender de JSON.net solo porque en algún otro lugar las está serializando con JSON.net.
fuente
Esto funcionó para mí: crear un solucionador de contratos personalizado que tenga una propiedad pública llamada AllowList de tipo de matriz de cadena. En su acción, modifique esa propiedad según lo que la acción necesite devolver.
1. cree un solucionador de contratos personalizado:
2. use el solucionador de contratos personalizado en acción
Este enfoque me permitió permitir / rechazar solicitudes específicas en lugar de modificar la definición de clase. Y si no necesita la serialización XML, no olvide desactivarlo en
App_Start\WebApiConfig.cs
su API o su API devolverá propiedades bloqueadas si el cliente solicita xml en lugar de json.fuente
Te mostraré 2 formas de lograr lo que quieres:
Primera forma: decore su campo con el atributo JsonProperty para omitir la serialización de ese campo si es nulo.
Segunda forma: si está negociando con algunos escenarios complejos, entonces podría usar la convención Web Api ("ShouldSerialize") para omitir la serialización de ese campo dependiendo de alguna lógica específica.
WebApi utiliza JSON.Net y utiliza la reflexión para la serialización, por lo que cuando haya detectado (por ejemplo) el método ShouldSerializeFieldX (), el campo con el nombre FieldX no se serializará.
fuente
Llego tarde al juego, pero un objeto anónimo sería suficiente:
fuente
Intenta usar la
IgnoreDataMember
propiedadfuente
Casi lo mismo que la respuesta de greatbear302, pero creo ContractResolver por solicitud.
1) Crear un ContractResolver personalizado
2) Use el solucionador de contratos personalizado en acción
Editar:
No funcionó como se esperaba (aislar resolución por solicitud). Usaré objetos anónimos.
fuente
Es posible que pueda usar AutoMapper y usar la
.Ignore()
asignación y luego enviar el objeto asignadofuente
Funciona bien simplemente agregando: [IgnoreDataMember]
En la parte superior de la propiedad p, como:
Esto funciona con ApiController. El código:
fuente
Por alguna razón
[IgnoreDataMember]
, no siempre funciona para mí, y a veces me daStackOverflowException
(o algo similar). Entonces, en cambio (o además) comencé a usar un patrón que se parecía a esto cuandoPOST
ingreséObjects
a mi API:Básicamente, paso una
JObject
y la convierto después de que ha sido recibida en problemas de aviod causados por el serializador incorporado que a veces causa un bucle infinito al analizar los objetos.Si alguien sabe una razón por la cual esto es de alguna manera una mala idea, hágamelo saber.
Vale la pena señalar que es el siguiente código para una propiedad de clase EntityFramework que causa el problema (si dos clases se refieren entre sí):
fuente