Estou usando uma API da web MVC 4 e formulários da web asp.net 4.0 para criar uma API restante. Está funcionando muito bem:
[HttpGet]
public HttpResponseMessage Me(string hash)
{
HttpResponseMessage httpResponseMessage;
List<Something> somethings = ...
httpResponseMessage = Request.CreateResponse(HttpStatusCode.OK,
new { result = true, somethings = somethings });
return httpResponseMessage;
}
Agora preciso impedir que algumas propriedades sejam serializadas. Sei que posso usar algum LINQ na lista e obter apenas as propriedades necessárias, e geralmente é uma boa abordagem, mas no cenário atual o something
objeto é muito complexo e preciso de um conjunto diferente de propriedades em métodos diferentes, por isso é mais fácil marcar, em tempo de execução, cada propriedade a ser ignorada.
Existe uma maneira de fazer isso?
c#
asp.net
asp.net-mvc
asp.net-web-api
user1330271
fonte
fonte
Respostas:
A API da Web do ASP.NET usa
Json.Net
como formatador padrão; portanto, se seu aplicativo usar apenas JSON como formato de dados, você poderá usar[JsonIgnore]
para ignorar a propriedade para serialização:Mas, dessa maneira, não suporta o formato XML. Portanto, caso seu aplicativo precise suportar mais o formato XML (ou apenas o XML), em vez de usar
Json.Net
, você deve usar o[DataContract]
que suporta JSON e XML:Para mais compreensão, você pode ler o artigo oficial .
fonte
De acordo com a página de documentação da API da Web JSON e XML Serialization na API da Web do ASP.NET para impedir explicitamente a serialização em uma propriedade, você pode usar
[JsonIgnore]
o serializador Json ou[IgnoreDataMember]
o serializador XML padrão.No entanto, no teste, notei que isso
[IgnoreDataMember]
impede a serialização para solicitações XML e Json, portanto, recomendo usá-la em vez de decorar uma propriedade com vários atributos.fonte
[IgnoreDataMember]
parece não funcionar com objetos de proxy EF 6 carregados com preguiça (propriedades virtuais).[DataContract]
e[DataMember]
faça, no entanto.Em vez de permitir que tudo seja serializado por padrão, você pode adotar a abordagem "aceitar". Nesse cenário, apenas as propriedades que você especificar podem ser serializadas. Você faz isso com o
DataContractAttribute
eDataMemberAttribute
, encontrado no espaço para nome System.Runtime.Serialization .O
DataContactAttribute
é aplicado à classe e oDataMemberAttribute
é aplicado a cada membro que você deseja que seja serializado:Ouso dizer que essa é uma abordagem melhor, porque força você a tomar decisões explícitas sobre o que a fará ou não por meio da serialização. Também permite que suas classes de modelo morem em um projeto por si mesmas, sem depender do JSON.net, apenas porque em outro lugar você as serializa com o JSON.net.
fonte
Isso funcionou para mim: Crie um resolvedor de contrato personalizado que tenha uma propriedade pública chamada AllowList do tipo de matriz de string. Em sua ação, modifique essa propriedade dependendo do que a ação precisa retornar.
1. crie um resolvedor de contrato personalizado:
2. use o resolvedor de contrato personalizado em ação
Essa abordagem me permitiu permitir / não permitir solicitações específicas em vez de modificar a definição de classe. E se você não precisar de serialização XML, não se esqueça de desativá-lo
App_Start\WebApiConfig.cs
ou sua API retornará propriedades bloqueadas se o cliente solicitar xml em vez de json.fonte
Mostrarei duas maneiras de realizar o que você deseja:
Primeira maneira: Decore seu campo com o atributo JsonProperty para ignorar a serialização desse campo, se ele for nulo.
Segunda maneira: se você estiver negociando com alguns cenários complexos, poderá usar a convenção de API da Web ("ShouldSerialize") para ignorar a serialização desse campo, dependendo de alguma lógica específica.
O WebApi usa JSON.Net e usa reflexão para serialização; assim, quando detectar (por exemplo) o método ShouldSerializeFieldX (), o campo com o nome FieldX não será serializado.
fonte
Estou atrasado para o jogo, mas um objeto anônimo faria o truque:
fonte
Tente usar a
IgnoreDataMember
propriedadefonte
Quase o mesmo que a resposta de greatbear302, mas eu crio ContractResolver por solicitação.
1) Crie um ContractResolver personalizado
2) Use o resolvedor de contrato personalizado em ação
Editar:
Não funcionou como esperado (isolar o resolvedor por solicitação). Vou usar objetos anônimos.
fonte
Você pode usar o AutoMapper e usar o
.Ignore()
mapeamento e, em seguida, enviar o objeto mapeadofonte
Funciona bem apenas adicionando o: [IgnoreDataMember]
No topo do propertyp, como:
Isso funciona com o ApiController. O código:
fonte
Por alguma razão
[IgnoreDataMember]
, nem sempre funciona para mim, e às vezes receboStackOverflowException
(ou similar). Então, em vez disso (ou além disso), comecei a usar um padrão parecido com este quandoPOST
acessandoObjects
minha API:Então, basicamente eu passo um
JObject
e o converto depois de ter sido recuperado para aviod problemas causados pelo serializador interno que às vezes causam um loop infinito ao analisar os objetos.Se alguém souber por que isso é uma má ideia, entre em contato.
Vale a pena notar que é o código a seguir para uma propriedade de classe EntityFramework que causa o problema (se duas classes se referirem uma à outra):
fonte