Pergunta

Tenho um contrato de serviço que define um método com um parâmetro do tipo System.Object (xs:anyType no WSDL).Quero poder passar tipos simples e também tipos complexos neste parâmetro.Tipos simples funcionam bem, mas quando tento passar um tipo complexo definido em meu WSDL, recebo este erro:

Elemento 'http://tempuri.org/:valor' contém dados do 'http://schemas.datacontract.org/2004/07/MyNamespace:MyClass'contrato de dados.O desserializador não tem conhecimento de nenhum tipo mapeado para este contrato.Adicione o tipo correspondente a 'MyClass' à lista de tipos conhecidos - por exemplo, usando o atributo KnownTypeAttribute ou adicionando-o à lista de tipos conhecidos passados ​​para DataContractSerializer.

Adicioná-lo como um tipo conhecido não ajuda porque já está no meu WSDL.Como posso passar um objeto de tipo complexo por meio de um parâmetro "xs:anyType"?

Mais informações:

Acredito que isso funcione ao usar o NetDataContract, mas não posso usar porque meu cliente é o Silverlight.

Tenho visto referências a tipos complexos que estendem explicitamente xs:anyType, mas não tenho ideia de como fazer o WCF gerar um WSDL que faça isso, e não tenho ideia se isso ajudaria ou não.

Obrigado

Foi útil?

Solução 3

Resolvi esse problema usando o atributo ServiceKnownType.Simplesmente adiciono meu tipo complexo como um tipo conhecido de serviço em meu contrato de serviço e o erro desaparece.Não sei por que isso não funcionou da última vez que tentei.

Parece não afetar o WSDL de forma alguma, então suspeito que o fluxo serializado deva ter alguma diferença que informe ao desserializador que o objeto pode ser desserializado usando meu tipo.

Outras dicas

O NetDataContract funciona porque o NetDataContractSerializer inclui informações de tipo.

O atributo KnownType instrui o DataContractSerializer como desserializar a mensagem.Sendo específico da implementação, esta é uma informação que vai além daquela definida pelo contrato público e não pertence ao WSDL.

Você nunca conseguirá passar nenhum tipo de dados antigo porque o desserializador precisa identificar o tipo apropriado e criar uma instância.

Você pode derivar seus tipos conhecidos em tempo de execução, em vez de tê-los codificados no DataContract.Dê uma olhada aqui para uma amostra.

Espero que isso ajude.Vi um colega meu usando esse código para enviar tipos de dados complicados e para mim isso é bem simples.Isso foi usado com basicHttpBinding e funciona muito bem com MOSS BDC, bem como com outros aplicativos que usam a ligação básica.

  1. Crie um contrato de dados baseado em uma classe genérica
  2. Use o contrato de dados quando as informações precisarem ser enviadas

    [DataContract(Namespace = "http://Service.DataContracts", Name =" ServiceTAcTractBase ")] Classe pública ServiedAtAcontract {

    public ServiceDataContract() { }
    
    public ServiceDataContract(TValueType Value)
    {
        this.m_objValue = Value;
    }
    
    private TValueType m_objValue;
    
    [DataMember(IsRequired = true, Name = "Value", Order = 1)]
    public TValueType Value
    {
        get { return m_objValue; }
        set { m_objValue = value; }
    }
    

    }

Use este contrato de dados sempre que for necessário nas funções WCF que retornam o tipo de dados complicado.Por exemplo:

public ServiceDataContract<string[]> GetStrings()
{
    string[] temp = new string[10];
    return new ServiceDataContract<string[]>(temp);
}

Atualizar:ServiceDataContract é uma classe genérica que usa TValueType.Não está aparecendo devido a algo errado com a renderização do HTML.

Tente usar substitutos de contrato de dados para mapear objetos não suportados que sejam específicos do ponto net ou de tipos não interoperáveis.Ver MSDN

Por enquanto, resolvi isso criando um novo tipo de contrato de dados que pode agrupar outro tipo de contrato de dados ou um tipo simples.Em vez de passar o tipo Object, agora passo esta classe wrapper.Isso funciona bem, mas ainda gostaria de saber se existe uma solução para o problema original.

Tentei adicionar o atributo ServiceKnownType, especificando o tipo que estou tentando passar, mas ainda recebo o mesmo erro. Também tentei adicionar o atributo KnownType ao meu contrato de dados (o que parecia bobo porque era do mesmo tipo do contrato de dados).Eu acho que adicioná-los em tempo de execução não ajudará se adicioná-los em tempo de compilação não ajudar.

Se eu estivesse estendendo outro tipo complexo, parece-me que gostaria de adicionar o atributo KnownType a esse tipo base.Mas como meu tipo base é Object, não vejo nenhuma maneira de fazer isso.

Quanto aos substitutos, parece-me que são utilizados para tipos de empacotamento que não possuem contrato definido.No meu caso, porém, tenho o contrato definido.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top