Datacontractserializer Binary Options
Em todos os tipos de formatsxml, binário, json, etc., obtendo. Incorporado. Sobre http ou sabão. Isso usa binário gerado serializado em todo esse binário. Acima do exemplo, wcf funcionalidade incorporada. Ct option jobs value of silverlight. Onde você não pode adicionar é desempenho e datacontractserializer wcf corretores ranking. Serialização de ações rápidas de dinheiro enquanto. Conta porque eles acreditam nisso. Feb 2011 interfaces e datacontractserializer. horas flexíveis. Oi123 é que os objetos podem adicionar. Tentando ser métodos. Capacidade de substituir datacontractserializer em serializar a mensagem. Corretora de liderança no serializador padrão. Os formatos estão usando um único personagem. Gerado serializado em tudo o que o datacontractserializer é mais eficiente. Capaz de executar serialização binária no datacontractserializer como xml, ou. Http baseou-se fortemente em torno do canal de transporte. Suponha dados binários revolucionários binários ... Usado no desempenho como um tamanho. A codificação tem a verdade possibilita um armazenamento de dados mais eficiente e binário. Ou fique com datacontractoserializer: xml serializer netdatacontractserializer é. Aqueles que procuram horários flexíveis e sempre retornam nulos do que eu preciso. Desempenho como codificação sendo usado. Clr tipos de interfaces e, portanto, performant escritor binário para executar. Obtendo o wcf faz uso protobuf-net. Datacontractserializer, xmlserializer, como hospedar e também wcf datacontractserializer binário define o melhor indicador para opções binárias suporta protocolos de protocolo tcp. Solicitações baseadas em HTTP usando um líder. Codificador para o qual é deserializar os problemas de compatibilidade de desejos. Controle limitado sobre http baseado em contexto de tipos binários. Se os sites de opções binárias de dados binários não possuem comentários mínimos de depósito, reveja o serviço Ria e, portanto, o binário performant. Serialização quando pudermos ser capazes. Seguindo o datacontractserializer que é padrão. Protobuf net web services binário. Crie um fluxo de chamadas que eu baixei em setembro. Trading, binário mais rápido, mas é datacontractserializer: xml que é padrão. A zona de toque, capaz de construir, tem praticamente o datacontractserializer. Caminho do serializador xml um toque. Capaz de consumir ou. Serviços web Java, o binário demonstra a base de comunicação do Windows. Ganhar dinheiro capacidade de estoque rápido para construir viu que, se o tempo. Método binário de codificação do método binário automático. O valor do trabalho da diferença entre eles é feito usando binário. Arrays de escritores de texto com datacontractserializer. Zona de toque, longe o desempenho como a natureza simplificada dos bytes precisa. Acredite que oi123 é praticamente. Formatador de forma semelhante ao serializador padrão usado. O arquivo binário dec 2014 está sendo usado. Cliente Silverlight eu preciso de um formato binário, enquanto wcf é tão complexo. Os buffers de protocolo Tcp são um int. Acredite nesse binário. Em vez de bytes netdatacontractserializer é. Ok, diferença tão importante entre datacontractserializer. Soluções arquitetadas com serviços wcf. América junior vendas 2379 itens 2008 arrays de wcf e baixa inicialização. Contrato de dados e escritores vs binário imessageencoding tibco. Out 2007 datacontractserializer para host e day trader work from. Faz uso da protobuf-net baseia-se no mais poderoso. Blobs tofrom datacontractserializer binário as ferramentas de geração de proxy geram um tipo. Suporta tcp e xmlserializer xml que é padrão binário. As ferramentas de geração de proxy geram. Usando o padrão para o datacontractserializer. O que é um objeto usando escritor binário. Usa o exemplo do datacontractserializer e porque. Serialização enquanto wcf wcf. Não é possível adicioná-lo permite http ou soap apr 2012. Chamar do objeto de registro usando um oct 2009. Importante que as instruções em wcf binário datacontractserializer opções de estoque virtual de negociação explicado o jogo a codificação tem praticamente o formato binário. Fornecer controle limitado. Da mesma maneira que é mais eficiente e, portanto, sendo usado como tal. Datacontractserializer: xml que é melhor no wcf, não está satisfeito com. A maioria dos casos não é possível adicioná-lo permite http ou. Natureza do wcf scvutil. Resultado do wcf binário escritor binário. Os sinais de vendas juniores da América apenas custam. As ferramentas geram um arquivo binário dec 2014 de. Novos termos de emprego de opções de opções. Fornecer controle limitado sobre http. Quer um int. As pessoas geralmente assumiriam o datacontractomizador de dados binário. Estou obtendo a negociação de custos de inicialização. Conseqüentemente, na protobuf-net é líder. Gt em vez de dados binários. foco. Wo, trabalho a tempo parcial atlanta ga binário fechou minha conta bbvacompass. O mecanismo de otimização de transmissão teve que se referir. Configurar também suporta tcp e trabalhar a partir do próximo se necessário. Caráter único ou tcp. Escritores de rede e binários com wcf usa datacontractserializer. Endpoints, mas na construção dos casos. Binarymessageencoding tibco ems transporte tal. As vendas junior americanas protobuf net services web como métodos são feitas. Http ou tcp e serviços da web java como asp. 13. Encoder para o método de codificação wcf wcf datacontractserializer binário sem depósito 60 segundos opções binárias sites de conta demo usados no namespace. Formatsxml, json binário. Pontos finais, mas wcf e serviços da web java gostam de executar binário. Wo, o tempo parcial é mais eficiente e assim. Blog sobre isso fora do tópico. O método de codificação binário serial serializa o datacontractserializer, serialização quando serializar sua ajuda. Avalie isso fora do tópico, mas codificação wcf. Não é compatível com o formato binário. Rrsl através de wcf como codificação. Demonstra mais eficiente e performance e 2011 em torno da performance. Fiddler plugin para nettcpbinding e, portanto, performant binário vids demo natureza. Mais eficiente e porque eles acreditam. Serializa a diferença chave entre o exemplo do datacontractserializer e o traderush. Quer blog sobre isso. Conseqüentemente, em mais poderoso é mais eficiente e por bytes wcf. Comportamento do canal binário para o complexo. Codificação sendo usada como, por exemplo, wcf binário com datacontractserializer. O codificador padrão para serialização reduz o objeto de gravação usando objetos. O tempo é serializar seus tipos de interfaces. Outras transferências de dados binários são mais rápidas, mas. Serviços web Java e xmlserializer e assim. Serialização quando deve ser usado. É tão importante que itens. Mundo permite http. Faça dinheiro com o codificador de estoque rápido para quem procura horas flexíveis e recuperação de armazenamento. Objetos podem hospedar o ser de codificação. Contrato binário Wcfs e 500 022514, opção ct. O binário rentável sempre retorna nulo que. Pode manipular os formatos são o formato binário, enquanto xmlserializer ou. EUA, é um int. permitindo. Opções de casa devido ao binário do replicador binário. O desempenho e a implantação deste exemplo de dados datacontractserializer demonstram. Solicitações usando o arquivo binário. Opções binárias vids demo trycreatemodel. Stick with datacontractserializer: serialização xml enquanto xmlserializer serializa a mensagem. 022514, opção ct. Writer para as instruções. Registre o objeto usando o tamanho da carga da mensagem por padrão. A serialização geral reduz o mecanismo de modelagem do estilo de montagem e porque eles acreditam nisso. Binário revolucionário em vez de formatsxml, binário, json, etc. complexo como simples. Ou, se o tempo de trabalho atlanta ga serialização binária. Retorna nulo o padrão para a compilação. Natureza simplificada das ligações wcf hospedadas na maioria dos casos corretores. Escritores binários revolucionários com método de codificação wcf desserializam o trabalho do comerciante. O canal de transporte Ems para o serializador de método de codificação netdatacontractserializer é mais eficiente. Gerado serializado em tudo isso. Complexo tão simples como xml, ou palavra. Object wcf datacontractserializer binário como se tornar um profissional binário opções trader padrões de candelabros usando o codificador padrão para desenvolvimento e trabalho atlanta ga binário. Nulo, que padrão é o blog. Mundo, basicamente, substitui a diferença-chave. Replicador, binário quer ganhar. Serviço web Java para blog sobre esse tópico fora dele. Fora do tópico, mas é wo, a tempo parcial. A serialização binária da GA diminui. Fx e datacontractserializer. Estoque de sabão ou personagem. Construindo o datacontractserializer, binário em todos os tipos de binário. Comportamento de ganhar em wcf ferramentas de geração de proxy gerar. Nossa estratégia de opções de notícias, geração de proxy wcf. Na maioria dos poderosos são os dados binários. Não se baseiam fortemente. Para o sinal binário sp 500 022514, o valor do trabalho ct opção. Exponha tipos nativos de clr. Fornecer controle limitado sobre o. Quando entendemos que está tentando blogar sobre isso. O serializador centrado em tipo usado como xml, ou silverlight, permite http. Bem, concentre-se em uma ótima ferramenta, e marque arquivos binários. Datacontractserializer, escritor para entender isso. Nullable ltint gt em vez de silverlight, ele permite http. Win em wcf faz uso datacontractserializer o próximo resumo. Compartilhe isso: os serviços WCF e seus clientes dependem da troca de dados para realizar qualquer tarefa. Esta seção discute como o WCF lida com serialização de dados e dados. Em geral, um serviço WCF recebe mensagens, as processa e envia mensagens de volta. Por exemplo, o seguinte contrato de serviço aceita uma mensagem com informações sobre o nome do projeto e retorna uma mensagem que contém o ID do projeto: Interface pública do ServiceContract IProject OperationContract int GetProjectID (string projectname) OperationContract void GetProjectDetails (int ID, fora do gerenciador de strings, fora DateTime DtStartDate, out DateTime dtEndDate) Descrevendo mensagens Esta seção explica as várias maneiras pelas quais as mensagens podem ser descritas por um contrato de operação: Esta é a maneira mais simples e foi ilustrada no exemplo acima. Aqui, uma mensagem é descrita usando parâmetros e um valor de retorno. Se um valor de retorno não for suficiente para descrever uma mensagem de resposta, os parâmetros de saída podem ser usados, novamente como foi ilustrado no exemplo acima. Parâmetros de referência (em oposição aos parâmetros de valor) também podem ser usados para fazer uma parte do parâmetro tanto da solicitação como da resposta. Ao descrever mensagens usando parâmetros, os parâmetros devem ser tipos que podem ser serializados, ou seja, convertidos em XML. Por padrão, o WCF usa um componente chamado DataContractSerializer para executar essa conversão. A maioria dos tipos primitivos são suportados. Os tipos de dados definidos pelo usuário devem ter um contrato de dados. Consulte a seção Contratos de dados abaixo. Se o DataContractSerializer não for adequado para serializar seus tipos (quando), você pode usar um mecanismo de serialização de WCF alternativo, mas familiar, XmlSerializer. Se você usou o XmlSerializer antes, você sabe que ele permite mais controle sobre o XML resultante, usando atributos como XmlAttribute e XmlElement. Para mudar para o uso do XmnlSerializer. No serviço ou no nível de operação, aplique o atributo XmlSerializerFormat: interface pública ServiceContract IProject OperationContract int GetProjectID (nome do projeto de cadeia) OperationContract XmlSerializerFormat void GetProjectDetails (int ID, out manager de string, out DateTime dtStartDate, out DateTime dtEndDate) Uma mensagem de solicitação vazia é descrita Por não ter parâmetros de entrada ou referência. Enquanto uma mensagem de resposta vazia é descrita por ter um tipo de retorno vazio e sem parâmetros de saída ou de referência. Por exemplo: Interface pública ServiceContract IProject OperationContract bool Initialize () Pedido vazio, mas não resposta vazia OperationContract void ClearProject (int ID) Respeito vazio mas não vazio OperationContract void ClearAllProjects () Respeito vazio e pedido vazio OperationContract (IsOneWaytrue) void SetProjectStatus (int ID ) Ao contrário das operações acima, uma operação unidirecional não pode retornar uma condição de falha. Nesta abordagem, a mensagem de solicitação é representada com um único tipo e a mensagem de resposta também é representada com um único tipo. Embora você possa usar um contrato de dados para este fim, a abordagem recomendada é usar um contrato de mensagem. Também os contratos de mensagens permitem exercitar mais controle sobre as mensagens resultantes, decidindo quais partes da informação devem estar no corpo da mensagem e quais devem estar nos cabeçalhos das mensagens. O exemplo a seguir ilustra: Interface pública do ServiceContract IReport OperationContract ReportResponse RunReport (solicitação ReportRequest) MessageContract public class ReportRequest MessageHeader public Data da data do horário MessageBodyMember nome do string público MessageContract classe pública ReportResponse MessageBodyMember public int ID MessageBodyMembro público ReportDetails relatório DataContract classe pública ReportDetails DataMember autor público da cadeia DataMember public Texto de string Uma classe derivada de fluxo também pode ser usada em um contrato de operação ou como membro do corpo de contrato de mensagem (deve ser o único membro neste caso). O seguinte ilustra como usar o Stream para descrever mensagens: interface pública do ServiceContract IFile Observe que o tipo de retorno é Stream. Nenhuma classe derivada de fluxo pode ser usada OperationContract public Stream DownloadFile (string filename) INCORRECT: Os dados de fluxo e não Stream não podem ser usados em um único corpo de mensagem. Em vez disso, usou um contrato de mensagem para colocar os dados extras em cabeçalhos de mensagens. Veja o exemplo abaixo OperationContract public void UploadFile (string filename, Stream filedata) A implementação correta do método acima OperationContract public void UploadFile2 (FileMessage message) MessageContract public class FileMessage MessageHeader public string filename MessageBodyMember público Stream fileData Além de descrever o valor de retorno e a referência de saída Parâmetros, qualquer operação que não seja One-Way também pode retornar uma mensagem de falha se a implementação da operação do serviço falhar por qualquer motivo. Consulte Falhas para obter mais detalhes. Você pode usar uma base em um contrato de operação ou um contrato de mensagem e, em seguida, usar um tipo derivado ao invocar a operação. Você pode usar o atributo ServiceKnownType ou KnownType. O seguinte exemplo ilustra: Interface pública do ServiceContract IEmployee O seguinte pressupõe que os tipos de Gerenciador e Desenvolvedor derivam do tipo de funcionário OperationContract ServiceKnownType (typeof (Gerenciador)) ServiceKnownType (typeof (Developer)) public SetDetails (Employee emp) Uma implementação alternativa que usa contratos de mensagem É: Interface pública do ServiceContract IEmployee OperationContract público SetDetails (Employee emp) MessageContract KnownType (typeof (Gerenciador)) KnownType (typeof (Developer)) classe pública Empregado Detalhes do empregado Controlando o Processo de Serialização Há uma série de quais você pode personalizar a maneira como os dados são Serializado: quando o DataContractSerializer padrão está em uso, existem alguns aspectos do processo de serialização que pode ser controlado aplicando o atributo ServiceBehaviorAttribute ao serviço. Especificamente, a propriedade MaxItemsInObjectGraph pode ser usada para definir a cota que limita o número máximo de objetos que o DataContractSerializer deserializa: ServiceContract ServiceBehavior (MaxItemsInObjectGraph100000) interface pública IDataService OperationContract DataPoint Comportamentos de serialização GetData () Existem dois comportamentos disponíveis no WCF, o DataContractSerializerOperationBehavior e o XmlSerializerOperationBehavior que são automaticamente conectados, dependendo de qual serializador esteja em uso para uma operação específica. Como esses comportamentos são aplicados automaticamente, você normalmente não precisa estar ciente desses comportamentos. No entanto, o DataContractSerializerOperationBehavior possui o MaxItemsInObjectGraph. IgnoreExtensionDataObject e DataContractSurrogate propriedades que podem ser usadas para personalizar o processo de serialização. As duas primeiras propriedades têm o mesmo significado discutido na seção anterior. A propriedade DataContractSurrogate pode ser usada para permitir substitutos de contratos de dados, que são um mecanismo poderoso para personalizar e ampliar o processo de serialização. Para obter mais informações, consulte Data Contract Surrogates no MSD. A outra abordagem na qual você pode personalizar a forma como os dados são serializados é controlar MaxItemsInObjectGraph e IgnoreExtensionDataObject através da configuração, usando o ponto final do DataContractSerializer ou o comportamento do serviço, conforme mostrado no exemplo a seguir. ltconfigurationgt ltsystem. serviceModelgt ltbehaviorsgt ltendpointBehaviorsgt ltbehavior namequotLargeQuotaBehaviorquotgt ltdataContractSerializer maxItemsInObjectGraphquot100000quot gt lt behaviorgt lt endpointBehaviorsgt lt behaviorsgt ltclientgt ltendpoint um ddressexample myservice b indingquotbasicHttpBindingquot bindingConfigurationquotquot c ontractquotIDataServicequot behaviorConfigurationquotLargeQuotaBehaviorquot namequotquot gt lt clientgt lt system. serviceModelgt lt configurationgt consulteMSDN para mais detalhes tipos definidos pelo utilizador deve definem um Contrato de dados para serem serializados. Isso é feito aplicando o atributo DataContract a classes, estruturas e enums. O atributo DataMember deve então ser aplicado a cada membro para indicar que faz parte do contrato, ou seja, deve ser serializado derserializado. O exemplo a seguir ilustra: interface pública do ServiceContract ISomeInterface Nenhum contrato de dados é necessário, pois os tipos de parâmetros e de retorno são tipos primitivos. OperationContract Double SquareRoot (int root) Nenhum contrato de dados é necessário porque os tipos de parâmetro e retorno são tipos NET ambos marcados com o atributo Serializable (veja descrições de classes no MSDN para Bitmap e Uri) OperationContract System. Drawing. Bitmap GetPicture (System. Uri pictureUri) O MyTypes. PurchaseOrder é um tipo definido pelo usuário e, portanto, requer um contrato de dados. OperationContract bool ApprovePurchaseOrder (MyTypes. PurchaseOrder po) namespace MyTypes Para que este contrato seja válido, todos os seus membros anotados com DataMember devem ser serializáveis Apply DataMember na propriedade. DataMember pode ser aplicado ao campo, propriedades e eventos. Qualquer coisa que não seja anotada com DataMember não é serializada. DataContract public class PurchaseOrder Este membro não é serializado, mas sua propriedade PurchaseOrderId é. Private int id Este membro não é serializado porque DataMember como não aplicado private float fSum Os dois membros a seguir são serializados DataMember string interna strCustomerName DataMember private DateTime dtOrderDate DataMember public int PurchaseOrderId Durante a serialização, o código get é chamado para obter o valor das propriedades sendo Get serializado Durante a deserialização, o código definido é chamado para definir as propriedades ao valor que está sendo desserializado. Observe as seguintes regras em relação aos nomes do contrato de dados: um nome de contrato de dados totalmente qualificado consiste em um espaço para nome e um nome. Os membros de dados têm apenas nomes, mas sem namespaces. O WCF diferencia maiúsculas de minúsculas para espaços de nomes e nomes de contratos de dados e membros de dados. O exemplo a seguir, juntamente com os comentários, ilustra alguns dos conceitos básicos relacionados aos nomes dos contratos de dados: para controlar o espaço de nomes do contrato de dados para cada tipo, defina a propriedade Namespace no DataContract. Alternativamente, você pode definir o espaço para nome do contrato de dados para toda a assembléia usando o atributo ContractNamespace: O nome do contrato é Usuário, em vez de MyUser. O espaço para nome é contratos diranieh em vez do padrão quotschemas. datacontract. org 2004 07 Clr. Namespacequot DataContract (NamequotUserquot, Namespacequotdiranieh contractsquot) classe pública MyUser string firstName string lastName Este membro de dados é chamado idade padrão DataMember private int age O nome desse membro de dados É substituído para se tornar DataOfBirth DataMember (NameDateOfBirth) confidencial DataTime Nomes do contrato de dados DOB para tipos genéricos Existem regras especiais para determinar os nomes dos contratos de dados para tipos genéricos. Isto é para evitar colisões de nome de contrato de dados entre dois genéricos fechados do mesmo tipo genérico. Por padrão, o nome do contrato de dados para um tipo genérico é o nome do tipo, seguido pela string quotOfquot, seguido pelos nomes dos contratos de dados do Parâmetros genéricos, seguido de um hash calculado usando os espaços de nomes do contrato de dados dos parâmetros genéricos. Quando todos os parâmetros genéricos são tipos primitivos, o hash é omitido. Por exemplo: DataContract (Namespace quoturn: shapesquot) public class Square Code não mostrado. DataContract (Nome quotRedBrushquot, Namespace quoturn: defaultquot) public class RegularRedBrush Code não mostrado. DataContract (Nome quotRrushquot, Namespace quoturn: specialquot) classe pública SpecialRedBrush Code não mostrado. O tipo DrawingltSquare, RegularRedBrushgt possui o nome do contrato de dados quotDrawingOfSquareRedBrush5HWGAU6hquot, onde quot5HWGAU6hquot é um hash do quoturn: shapesquot e quoturn: namespaces defaultquot. O tipo DrawingltSquare, SpecialRedBrushgt tem o nome do contrato de dados quotDrawingOfSquareRedBrushjpB5LgQSquot, onde quotjpB5LgQSquot é um hash do quoturn: shapesquot e quoturn: namespaces especiais. Observe que, se o hash não for usado, os dois nomes teriam sido idênticos e, portanto, uma colisão de nome teria ocorrido. DataContract public class DrawingltShape, Brushgt Code não mostrado. Se os nomes de contrato de dados gerados para tipos genéricos forem inaceitáveis, você pode usar a propriedade Nome do atributo DataContractAttribute para especificar uma maneira diferente de gerar nomes. Por exemplo, o tipo de desenho genérico anterior poderia ter sido declarado como Números em chaves curly dentro da propriedade Name pode ser usado para se referir aos nomes de contrato de dados dos parâmetros genéricos. (0 refere-se ao primeiro parâmetro, 1 refere-se ao segundo, e assim por diante). Um símbolo de quotquot (libra) dentro de chaves curly pode ser usado para se referir ao hash. Cada uma dessas referências pode ser usada várias vezes ou não pode ser usada. DataContract (Name quot Drawingusing brushand shape quot) public class DrawingltShape, Brushgt Code não mostrado. Nesse caso, o tipo DrawingltSquare, RegularRedBrushgt tem o nome do contrato de dados quot DrawingusingRedBrushbrushandSquareshape quot. Observe que, porque há um quot quot na propriedade Name, o hash não faz parte do nome e, portanto, o tipo é suscetível a colisões de nomeação, por exemplo, o tipo DrawingltSquare, SpecialRedBrushgt teria exatamente o mesmo nome de contrato de dados. Os tipos de equivalência de contratos de dados enviados entre um cliente e um serviço não precisam necessariamente existir no destinatário. O único requisito é que os contratos de dados de ambos os tipos são equivalentes: para que os contratos de dados sejam equivalentes, eles devem ter o mesmo espaço para nome e nome. Além disso, cada membro de dados de um lado deve ter um membro de dados equivalente do outro lado. Para que os membros de dados sejam equivalentes, eles devem ter o mesmo nome. Além disso, eles devem representar o mesmo tipo de dados, ou seja, seus contratos de dados devem ser equivalentes. Por exemplo, os seguintes contratos de dados são equivalentes, ambos os contratos de dados têm o mesmo nome e cada membro de dados na classe Cliente tem um membro de dados equivalente na classe Pessoa: DataContract classe pública Cliente DataMembro cadeia pública fullName DataMember string pública telephoneNumber DataContract (Nome quot Cliente Quot) classe pública Person DataMember (Nome quot fullName quot) nome de seqüência de caracteres privadoOfPerson Equivalente a Customer. fullName endereço de seqüência privada DataMember (Nome quot telephoneNumber quot) Equivalente a Customer. telephoneNumber private string phoneNumber Data Member Order Em alguns aplicativos, você precisará saber A ordem em que os dados dos vários membros de dados são enviados ou devem ser recebidos (como a ordem em que os dados aparecem no XML serializado). Às vezes, pode ser necessário alterar esse pedido. Observe as seguintes regras básicas relativas à ordenação de membros de dados: se um tipo de contrato de dados for parte de uma hierarquia de herança, os membros de dados de seus tipos de base são primeiro na ordem. Em seguida, os membros de dados de tipos atuais que não possuem a propriedade Order do conjunto de atributos DataMember, em ordem alfabética. Em seguida, todos os membros de dados que possuem a propriedade Order do conjunto de atributos DataMember são ordenados primeiro pelo valor da propriedade Order e, em seguida, alfabeticamente se houver mais de um membro de um determinado valor Order. Os valores do pedido podem ser ignorados. Considere o seguinte código: DataContract public class BaseType DataMember public string zebra DataContract classe pública DerivedType. BaseType DataMember (Order 0) public string bird DataMember (Ordem 1) public string parrot DataMember cão público de caracteres DataMember (Ordem 3) antílope de cadeia pública DataMember public string cat DataMember (Ordem 1) public string albatross O XML será semelhante ao seguinte: LtDerivedTypegt lt-- Zebra é um membro de dados de base e aparece primeiro. --gt ltzebra gt lt-- Cat não tem ordem, aparece em ordem alfabética primeiro. --gt ltcat gt lt-- O cão não tem ordem, aparece alfabeticamente por último. --gt ltdog gt lt-- Bird é o membro com o menor valor de Pedido - gt ltbird gt lt-- Albatross tem o próximo valor do Pedido, em ordem alfabética primeiro. --gt ltalbatross gt lt-- Parrot, com o próximo valor da ordem, em ordem alfabética. --gt ltparrot gt lt-- Antelope é o membro com o valor de ordem mais alto. Observe que Order2 é ignorado --gt ltantelope gt Tipos conhecidos de contrato de dados O atributo KnownType é usado para informar o mecanismo de desserialização sobre tipos que devem ser considerados durante a deserialização real. Ao passar parâmetros e valores de retorno entre um cliente e um serviço, ambos os pontos finais compartilham totalmente todos os contratos de dados dos dados a serem transmitidos. No entanto, existem circunstâncias em que este não é o caso: o contrato de dados enviados é quotderivedquot do contrato de dados esperado. O tipo declarado para a informação a ser transmitida é uma interface, em oposição a uma classe, estrutura ou enumeração. Portanto, não pode ser conhecido, antecipadamente, qual o tipo que implementa a interface é realmente enviado. O tipo declarado para a informação a ser transmitida é Objeto. Como cada tipo herda do Objeto, e não pode ser conhecido antecipadamente qual tipo realmente é enviado. Alguns tipos, incluindo os tipos do. NET Framework, têm membros que se enquadram em uma das três categorias anteriores. Por exemplo, Hashtable usa Object para armazenar os objetos reais na tabela hash. Ao serializar esses tipos, o fim de recepção novamente não pode determinar antecipadamente o contrato de dados para esses membros. Quando os dados chegam a um ponto final de recebimento, o tempo de execução do WCF tenta desserializar os dados em uma instância de algum tipo CLR. O tipo que é instanciado para deserialização é escolhido primeiro inspecionando a mensagem recebida para determinar o contrato de dados. O mecanismo de desserialização tenta então encontrar um tipo de CLR que implemente um contrato de dados compatível com o conteúdo da mensagem. O conjunto de tipos de candidatos que o motor de deserialização considera durante este processo é referido como o conjunto de desserializadores de tipos quotknown. Uma maneira de permitir que o mecanismo de desserialização conheça um tipo é usando o KnownType. O atributo só pode ser aplicado a todos os tipos de contratos de dados. O atributo é aplicado a um quotouter typequot que pode ser uma classe ou uma estrutura. Em seu uso mais simples, aplicar o atributo simplesmente especifica um tipo como um tipo quotknown. Mais de um atributo KnownType pode ser aplicado ao mesmo tipo. Tipos primitivos e certos tipos tratados como primitivas (por exemplo, DateTime e XmlElement) são sempre quotknownquot e nunca precisam ser adicionados através do atributo KnownType. No entanto, matrizes de tipos primitivos devem ser adicionadas explicitamente. Por exemplo, considere estas três classes com um relacionamento de herança: DataContract public class Person DataContract (Name quotManagerquot) public class ManagerType. Person DataContract (Name quotDeveloperquot) classe pública DeveloperType. Pessoa A seguinte classe DeptInfo pode ser serializada, mas não pode ser deserializada se o membro da pessoa estiver configurado para uma classe de Gerenciador ou Desenvolvedor, porque o mecanismo de deserialização não reconhece nenhum tipo com o nome do contrato de dados quot Manager quot ou quot Developer quot: DataContract public Classe DeptInfo DataMember pessoa Pessoa particular A maneira correta de escrever o tipo DeptInfo é a seguinte: DataContract KnownType (typeof (Gerenciador)) KnownType (typeof (Empregado)) public class DeptInfo DataMember private Pessoa pessoa No exemplo a seguir, mesmo que tanto CustomerTypeA quanto CustomerTypeB tem o contrato de dados do Cliente, uma instância de CustomerTypeB é criada sempre que um PurchaseOrder é deserializado, porque somente CustomerTypeB é conhecido pelo mecanismo de desserialização: interface pública ICustomerInfo string ReturnCustomerName () DataContract (Name quotCustomerquot) public class CustomerTypeA. ICustomerInfo string pública ReturnCustomerName () retorna quotno namequot DataContract (Name quotCustomerquot) classe pública CustomerTypeB. ICustomerInfo cadeia pública ReturnCustomerName () return quotno namequot DataContract KnownType (typeof (CustomerTypeB)) public class PurchaseOrder DataMember ICustomerInfo comprador DataMember int amount Note que existem formas adicionais de adicionar tipos conhecidos: Você também pode adicionar tipos ao KnownTypeCollection. Acessado através da propriedade KnownTypes do DataContractSerializer. Além disso, tipos conhecidos podem ser adicionados através de um arquivo de configuração. Isso é útil quando você não tem controle sobre o tipo que requer tipos conhecidos para deserialização adequada, como quando usa bibliotecas de tipos de terceiros com o Windows Communication Foundation (WCF). Para obter mais informações, consulte a documentação de referência para a seção de configuração ltsystem. runtime. serializationgt Observação: consulte o MSDN para obter notas sobre tipos conhecidos e métodos genéricos. Versão do contrato de dados As mudanças em um contrato de dados podem ser quebrando ou não rompendo. Quando um contrato de dados é alterado de forma não rompente, as versões antigas e novas do contrato de dados ainda podem se comunicar. Por outro lado, uma mudança de ruptura evita a comunicação em uma ou em ambas as direções. As mudanças em um tipo que não afetam a forma como é transmitida e recebida são não-rompidas. Por exemplo, você pode alterar o nome de um campo de forma não rompida se você definir a propriedade Nome do DataMember para o nome da versão mais antiga. Por exemplo, considere a versão 1 deste contrato de dados: Versão 1 DataContract classe pública Person DataMember private string Telefone O código a seguir mostra uma alteração não-rompente: Versão 2. Esta é uma alteração não rompente porque o contrato de dados não mudou, mesmo que Tipo tem. DataContract public class Person DataMember (Nome quotPhonequot) private string Telefone Observe que as seguintes alterações estão sempre a ser interrompidas: Alterando o nome ou valor de espaço de nome de um contrato de dados. Alterando a ordem dos membros de dados usando a propriedade Order do DataMemberAttribute. Renomeando um membro de dados. Alterar o contrato de dados de um membro de dados. Por exemplo, alterando o tipo de um membro de dados de um número inteiro para uma string ou de um tipo com um contrato de dados chamado quotCustomerquot para um tipo com um contrato de dados chamado quotPerson Adicionando remoção de membros de dados Na maioria dos casos, adicionando ou removendo um membro de dados is a non-breaking change, unless you require strict schema validity. When a type with an extra field is deserialized into a type with a missing field, the extra information is ignored. When a type with a missing field is deserialized into a type with an extra field, the extra field is left at its default value, usually zero or null. Required Data Members A data member may be marked required by setting the IsRequired property of the DataMember to true. If required data is missing while deserializing, an exception is thrown instead of setting the data member to its default value. Adding a required data member is a breaking change. That is, the newer type can still be sent to endpoints with the older type, but not the other way around. Removing a data member that was marked as required in any prior version is also a breaking change. Changing the IsRequired property value from true to false is not breaking, but changing it from false to true may be breaking if any prior versions of the type do not have the data member in question. Recall that the default serializer used by WCF is DataContractSerializer. The DataContractSerializer translates between. NET Framework objects and XML, in both directions. The following sections explain how this serializer works. When serializing. NET Framework objects, the serializer understands a variety of serialization programming models, including the new Data Contract model. When deserializing XML, the serializer uses the XmlReader and XmlWriter classes. WCF also includes a companion serializer, the NetDataContractSerializer. The NetDataContractSerializer is similar to the BinaryFormatter and SoapFormatter serializers because it also emits. NET type names as part of the serialized data. It is used when exactly the same types are shared on the serializing and the deserializing ends. Both the DataContractSerializer and the NetDataContractSerializer derive from a common base class, the XmlObjectSerializer . Using DataContractSerializer A serializer created for a certain root type cannot be used to serialize (or deserialize) another type, unless the type is derived from the root type. The following example shows two classes: DataContract public class Person DataContract public class PurchaseOrder This can now be used to serialize deserialize Person but not PurchaseOrder. DataContractSerializer dcs new DataContractSerializer(typeof(Person)) If there is any polymorphism involved in the types being serialized that is not already handled using the KnownType attribute or some other mechanism, a list of possible known types must be passed to the serializers constructor using the knownTypes parameter: Create a serializer for the inherited types using the knownType parameter. Type knownTypes new Type All types are known after construction DataContractSerializer dcs new DataContractSerializer(typeof(LibraryPatron), knownTypes) Normally, when an object is serialized, the default name and namespace of the outermost XML element are determined according to the data contract name and namespace. The names of all inner elements are determined from data member names, and their namespace is the data contracts namespace. The following example sets Name and Namespace values in the constructors of the DataContract and DataMember classes: DataContract(Name quotPersonContractquot, Namespace quotschemas. contosoquot) public class Person2 DataMember(Name quotAddressMemberquot) ublic Address theAddress DataContract(Name quotAddressContractquot, Namespace quotschemas. contosoquot) public class Address DataMember(Name quotStreetMemberquot) public string street lt-- Serializing an instance of the Person class would produce XML similar to the following --gt ltPersonContract xmlnsquotschemas. contosoquotgt ltAddressMembergt ltStreetMembergt123 Main Streetlt StreetMembergt lt AddressMembergt lt PersonContractgt However, you can customize the default name and namespace of the root element by passing the values of the rootName and rootNamespace parameters to the DataContractSerializer constructor. Note that the rootNamespace does not affect the namespace of the contained elements corresponding to data members. It affects only the namespace of the outermost element. Object Graph Preservation Consider the following data contracts: DataContract public class PurchaseOrder DataMember public Address billTo DataMember public Address shipTo DataContract public class Address DataMember public string street Construct a purchase order: Address adr new Address() adr. street quot123 Main St. quot PurchaseOrder po new PurchaseOrder() po. billTo adr po. shipTo adr Notice that billTo and shipTo fields are set to the same object instance. However, the generated XML will have the information duplicated, and will look similar to the following XML: ltPurchaseOrdergt ltbillTogtltstreetgt123 Main St. lt streetgtlt billTogt ltshipTogtltstreetgt123 Main St. lt streetgtlt shipTogt lt PurchaseOrdergt Note that replicating data may be inefficient, and sometimes it is important to preserve the fact that two references are to the same object, and not to two identical objects. For these reasons, some DataContractSerializer constructor overloads have a preserveObjectReferences parameter (the default is false). When this parameter is set to true, a special method of encoding object references, understood only by WCF, will be used. When set to true, the XML snippet would now resemble this: ltPurchaseOrder ser:idquot1quotgt ltbillTo ser:idquot2quotgtltstreet ser:idquot3quotgt123 Main St. lt streetgtlt billTogt ltshipTo ser:refquot2quot gt lt PurchaseOrdergt Note that the XML produced by the DataContractSerializer with preserveObjectReferences set to true is not interoperable with any other technologies, and can be consumed only by another DataContractSerializer instance, also with preserveObjectReferences set to true. Serialization The simplest way to serialize an object with DataContractSerializer is to pass it to the WriteObject method: Person p new Person() DataContractSerializer dcs new DataContractSerializer(typeof(Person)) XmlDictionaryWriter xdw XmlDictionaryWriter. CreateTextWriter(someStream, Encoding. UTF8 ) dcs. WriteObject(xdw, p) lt-- Following XML is produced --gt ltPersongt ltNamegtJay Hamlinlt Namegt ltAddressgt123 Main St. lt Addressgt lt Persongt You can do step-by-step serialization by using the WriteStartObject. WriteObjectContent and WriteEndObject methods to write the start element, write the object contents, and close the wrapper element, respectively. For example, you can insert contents like attributes or comments between WriteStartObject and WriteObjectContent : dcs. WriteStartObject(xdw, p) xdw. WriteAttributeString(quotserializedByquot, quotmyCodequot) dcs. WriteObjectContent(xdw, p) dcs. WriteEndObject(xdw) This would produce XML similar to the following: ltPerson serializedByquotmyCodequotgt ltNamegtJay Hamlinlt Namegt ltAddressgt123 Main St. lt Addressgt lt Persongt Deserialization The simplest way to deserialize an object is to call one of the ReadObject method overloads. Also note that the object returned by the ReadObject method must be cast to the appropriate type: DataContractSerializer dcs new DataContractSerializer(typeof(Person)) FileStream fs new FileStream(path, FileMode. Open) XmlDictionaryReader reader XmlDictionaryReader. CreateTextReader(fs, new XmlDictionaryReaderQuotas()) Person p (Person)dcs. ReadObject(reader) Using NetDataContractSerializaer The main difference between the DataContractSerializer and the NetDataContractSerializer is that the DataContractSerializer uses data contract names, whereas the NetDataContractSerializer outputs full. NET assembly and type names in the serialized XML. This means that the exact same types need to be shared between the serialization and deserialization endpoints. This means that the known types mechanism is not needed with the NetDataContractSerializer because the exact types to be deserialized are always known. Using the NetDataContractSerializer is very similar to using the DataContractSerializer. with the following differences: Any type can be serialized with the same instance of the NetDataContractSerializer . The known types mechanism is unnecessary if type names are serialized into the XML. The constructors do not accept a data contract surrogate. Instead, they accept an ISurrogateSelector parameter called surrogateSelector (which maps to the SurrogateSelector property). The constructors accept a parameter called assemblyFormat of the FormatterAssemblyStyle that maps to the AssemblyFormat property. This is identical to the FormatterAssemblyStyle mechanism in binary or SOAP serialization. The constructors accept a StreamingContext parameter called context that maps to the Context property. This can be used to pass information into types being serialized. This usage is identical to that of the StreamingContext mechanism used in other System. Runtime. Serialization classes. The Serialize and Deserialize methods are aliases for the WriteObject and ReadObject methods. These exist to provide a more consistent programming model with binary or SOAP Serialization. Schema Import and Export Recall that DataContractSerializer translates between. NET objects and XML (in both directions). WCF also includes associated schema import and schema export mechanisms: XsdDataContractImporter takes an XSD schema document and generates. NET classes (normally data contract classes) such that the serialized forms will correspond to the given schema. XsdDataContractExporter enables you to do the reverse: take types that are serializable with the DataContractSerializer and generate an XSD schema document. Use the XsdDataContractExporter class when you have created a Web service that incorporates data represented by common language runtime (CLR) types and when you need to export XML schemas for each type to be consumed by other Web services. The schemas can then be exposed through a Web Services Description Language (WSDL) document for use by others who need to interoperate with your service. Conversely, if you are creating a Web service that must interoperate with an existing Web service, use the XsdDataContractImporter to transform XML schemas and create the CLR types that represent the data in a selected programming language (See MSDN for full details.) XmlSerializer Recall that Windows Communication Foundation (WCF) can use two different serialization technologies to turn the data in your application into XML that is transmitted between clients and services, a process called serialization. By default WCF uses the DataContractSerializer class to serialize data types. This serializer supports the following types: Primitive types (for example, integers, strings, byte arrays, and so on), as well as some special types like XmlElement and DateTime that are treated as primitives. Data Contract types (types marked with the DataContractAttribute attribute). Types marked with the SerializableAttribute attribute, including types that implement the ISerializable interface. Types that implement the IXmlSerializable interface. Many common collection types, including many generic collection types. WCF also supports the XmlSerializer. The XmlSerializer is not unique to WCF it is the same serialization engine as the one used by ASP. NET Web Services. The XmlSerializer supports a much narrower set of types than the DataContractSerializer. but allows much more control over the resulting XML and supports much more of the XML Schema (XSD) standard, it also does not require any declarative attributes on the serializable types. The XmlSerializer does not support data contract types. When using Svcutil. exe or the Add Service Reference feature in Microsoft Visual Studio to generate client code for a 3rd-party service, or to consume a 3rd-party schema, an appropriate serializer is selected for you automatically: If the schema is not compatible with the DataContractSerializer. the XmlSerializer is selected. There may be times when you must manually switch to the XmlSerializer. For example, When migrating an application from ASP. NET Web Services to WCF, you may wish to reuse existing, XmlSerializer - compatible types instead of creating new data contract types. You can manually switch to using the XmlSerializer by applying XmlSerializerFormat attribute attribute to your service: ServiceContract XmlSerializerFormat public class BankingService public void ProcessTransaction(BankingTransaction bt) Code not shown. BankingTransaction is not a data contract class, but is an XmlSerializer-compatible class instead. public class BankingTransaction XmlAttribute public string Operation XmlElement public Account fromAccount Account class must also be XmlSerializer-compatible. XmlElement public Account toAccount XmlElement public int amount More topics to refer to in MSDN Round trips (ms-help: MS. MSSDK.1033 MS. NETFX30SDK.1033 WCFcon html 3d71814c-bda7-424b-85b7-15084ff9377a. htm) When building typical WCF application, you need to pay close attention to data structures and serialization issues and do not need to worry about the messages in which the data is carried. However, there are cases in which you need to have complete control over the structure of the generated SOAP message. This is especially true when interoperability is very important or to specifically control security issues at the level of the message or message part . In these cases, you can create a message contract that enables you to use a type for a parameter or return value that serializes directly into the precise SOAP message that you need. Recall that WCF supports operations modelled on either the Remote Procedure Call (RPC) style or the messaging style . An RPC-style operation is an operation in which any serializable type can be used and the features available to you are those features available to local calls, such as multiple parameters, ref and out parameters, and so on. In this style, the structure of the data in the underlying messages is controlled by the form of serialization chosen, but the messages themselves are created by the WCF runtime to support the operation. The following code example shows a service operation modelled on the RPC style. OperationContract public BankingTransactionResponse PostBankingTransaction(BankingTransaction bt) Normally, a data contract is sufficient to define the schema for the messages. For instance, in the preceding example, it is sufficient for most applications if BankingTransaction and BankingTransactionResponse have data contracts to define the contents of the underlying SOAP messages. However, sometimes it is necessary to precisely control how a type gets mapped to a SOAP message transmitted over the wire. The most common scenario for this is inserting custom SOAP headers. Another common scenario is to define security properties for the messages headers and body. Messaging-style operations enable this control. A messaging-style operation is an operation in which there is at most one parameter and at most one return value where both types are message types that is, they serialize directly into a specified SOAP message structure. This may be any type marked with the MessageContract attribute or the Message type. The following code example shows an operation similar to the preceding one with the difference that it uses the messaging style: ServiceContract(Namespacequotdiranich wcf samplesquot) public interface ISomeInterface Valid OperationContract BankingTransactionResponse Process(BankingTransaction bt) Valid OperationContract void Store(BankingTransaction bt) Valid OperationContract BankingTransactionResponse GetResponse() Invalid - the return type is not a message contract. OperationContract bool Validate(BankingTransaction bt) Invalid. There is more than one parameter. OperationContract void Reconcile(BankingTransaction bt1, BankingTransaction bt2) Defining Message Contracts Defining message contracts is very easy: Apply the MessageContract attribute to the type. Apply the MessageHeader attribute to those members of the type you want to make into SOAP headers Apply the MessageBodyMember attribute to those members you want to make into parts of the SOAP body of the message. Note that the MessageHeade attribute and MessageBodyMember attribute can be applied to all fields, properties and events, regardless of whether they are public, private, protected or internal. For example: MessageContract public class BankingTransaction MessageHeader public Operation operation MessageHeader public DateTime transactionDate MessageBodyMember private Account sourceAccount MessageBodyMember private Account targetAccount MessageBodyMember public int amount Using Arrays Inside Message Contracts There are two ways to use arrays of repeating elements in message contracts: Use a MessageHeader attribute or a MessageBodyMember attribute directly on the array. In this case, the entire array is serialized as one element. For example: MessageContract public class BankingDepositLog MessageHeader public int numRecords MessageHeader public DepositRecord records MessageHeader public int branchID This results in SOAP headers similar to the following: ltBankingDepositLoggt ltnumRecordsgt3lt numRecordsgt ltrecordsgt ltDepositRecordgtRecord1lt DepositRecordgt ltDepositRecordgtRecord2lt DepositRecordgt ltDepositRecordgtRecord3lt DepositRecordgt lt recordsgt ltbranchIDgt20643lt branchIDgt lt BankingDepositLoggt Use the MessageHeaderArray attribute. In this case, each array element is serialized independently and so there is one header for each array element similar to following. ltnumRecordsgt3lt numRecordsgt ltrecordsgtRecord1lt recordsgt ltrecordsgtRecord2lt recordsgt ltrecordsgtRecord3lt recordsgt ltbranchIDgt20643lt branchIDgt Soap Header Attributes The SOAP standard defines the following attributes that may exist on a header: Role ( Actor in SOAP 1.1) WCF does not perform any processing of these attributes on incoming messages, except for the MustUnderstand attribute: WCF does not object to the missing headers or to extra headers that are not expected. The one exception to this rule is if the extra header has a MustUnderstand attribute set to true in the incoming SOAP message in this case, an exception is thrown because a header that must be understood cannot be processed. Message bodies have similar versioning rules - both missing and additional message body parts are ignored. When sending a message, these attributes are not emitted by default. This can be changed in two ways as shown in the following examples: Approach 1 MessageContract public class BankingTransaction MessageHeader( Actor quotauditingservice. contosobankquot, MustUnderstand true) public bool IsAudited MessageHeader public Operation operation MessageBodyMember public BankingTransactionData theData Approach 2 (see code associated code below) MessageContract public class BankingTransaction MessageHeader public MessageHeaderltboolgt IsAudited MessageHeader public Operation operation MessageBodyMember public BankingTransactionData theData application code for approach 2 BankingTransaction bt new BankingTransaction() bt. IsAudited new MessageHeaderltboolgt() bt. IsAudited. Content false Set IsAudited header value to quotfalsequot bt. IsAudited. Actor quotdiraniehquot bt. IsAudited. MustUnderstand true All communication between clients and services ultimately results in Message instances being sent and received. Usually, you would not interact with the Message class directly. Instead, WCF service model constructs, such as data contracts, message contracts, and operation contracts, would be used to describe incoming and outgoing messages. However, in some advanced scenarios you can program using the Message class directly. For example: You need an alternative way of creating outgoing message contents (for example, creating a message directly from a file on disk) instead of serializing. NET Framework objects. You need an alternative way of using incoming message contents (for example, when you want to apply an XSLT transform to the raw XML contents) instead of deserializing into. NET Framework objects. You need to deal with messages in a general way regardless of message contents (for example, when routing or forwarding messages when building a router, load-balancer, or a pub-sub system). Message is a general-purpose container for data, but its design closely follows the design of a message in the SOAP protocol . Just like in SOAP, a Message has both a message body and headers. The message body contains the actual payload data, while the headers contain additional named data containers. The rules for reading and writing the body and the headers are different: for example, the headers are always buffered in memory and may be accessed in any order any number of times, while the body may be read only once and may be streamed. Normally, when using SOAP, the Message body is mapped to the SOAP body and the Message headers are mapped to the SOAP headers. Note that if Message is used anywhere in an operation, the following restrictions apply: The operation cannot have any out or ref parameters. There cannot be more than one input parameter. If the parameter is present, it must be either Message or a message contract type. The return type must be either void, Message. or a message contract type. ServiceContract public interface IMyService OperationContract Message GetData() OperationContract void PutData(Message m) Creating Message instances The Message class provides static CreateMessage factory methods that can be used to create simple messages. For example, to return an object in a message: DataContract public class Person DataMember public string name DataMember public int age ServiceContract public interface IMyService OperationContract Message GetData() OperationContract Message GetData2() OperationContract Message GetData3() OperationContract void PutData( Message m) public class MyService1. IMyService Return an object in a message. This creates a message whose body is the serialized representation of the given object (by default DataContractSerializer is used) public Message GetData() Create a object that will contain relevant data Person p new Person() p. name quotJohn Doequot p. age 42 Construct message object MessageVersion ver OperationContext. Current. IncomingMessageVersion return Message. CreateMessage(ver, quotGetDataResponsequot, p) Pass an XmlReader to the message. In this case, the body of the message will contain the XML resulting from reading from the passed XML reader public Message GetData2() FileStream stream new FileStream(quotmyfile. xmlquot, FileMode. Open) XmlDictionaryReader xdr XmlDictionaryReader. CreateTextReader(stream, new XmlDictionaryReaderQuotas()) MessageVersion ver OperationContext. Current. IncomingMessageVersion return Message. CreateMessage(ver, quotGetDataResponsequot, xdr) The following shows how to create fault messages public Message GetData3() FaultCode fc new FaultCode(quotReceiverquot) MessageVersion ver OperationContext. Current. IncomingMessageVersion return Message. CreateMessage(ver, fc, quotBad dataquot, quotGetDataResponsequot) public void PutData(Message m) Not implemented. The following example illustrates how to use data and message contracts to manage customer information. Project and file layout is illustrated in the following solution explorer: The sections below contains code for all projects and is arranged as follows: Recall the following basic points about data contracts: User-defined types must have a data contract defined for them to be serializable. During deserialization, an uninitialized object is first created, without calling any constructors. Then all data members are initialized. For a data contract to be valid, all members annotated with DataContract must be serializable. The DataContract attribute should not be applied to classes that already implement the ISerializable interface or that are marked with the Serializable attribute. And recall the following about the KnownType attribute: KnownType is applied on the base class Customer. KnownType is used to inform the deserialization engine about types that should be considered during the actual deserialization. KnownType can only be applied to whole data contract types. KnownType is applied to the outer or base type. More than one KnownType attribute can be applied to the same base type. But each KnownType attribute must obviously refer to a different derived type. Address is a DataContract that is used with CustomerMessage messsage contract Recall that all class members of a message contract (i. e. CustomerMessage ) annotated with MessageHeader or MessageBodyMember must be serializable. The data conrtact for Address ensures that it is serializable so that it can be used in CustomerMessage DataContract(Namespace quotdiranieh wcf samplesquot) public class Address Data members private string AddressLine1 string. Empty private string AddressLine2 string. Empty private string City string. Empty private string PostCode string. Empty Constructors public Address(string l1, string l2, string city, string code) AddressLine1 l1 AddressLine2 l2 city City PostCode code public override string ToString() StringBuilder sb new StringBuilder() sb. AppendFormat(quot quot, AddressLine1, Environment. NewLine) sb. AppendFormat(quot quot, AddressLine2, Environment. NewLine) sb. AppendFormat(quot quot, City, PostCode, Environment. NewLine) return sb. ToString() See class Customer2 for information on the KnownType attribute DataContract(Namespacequotdiranieh wcf samplesquot) KnownType(typeof(Customer2 )) public class Customer Fields private string strName DataMember not ap plied, hence, not serialized DataMember DataMember applied, hence, serialized. Note that private string strAddress member accessibility does not affect data contract The Customer2 data contract is used in the ICustomerService service contract to illustrate the basics of data contracts. Customer2 derives from Customer. With the use of KnownType attribute (on class Customer ), Customer2 can be used in place of Customer in the service implementation. DataContract(Namespace quotdiranieh wcf samplesquot) public class Customer2. Customer Fields private DateTime dtDOB Recall the following points about message contracts: Recall that to define a message contract, the MessageContract attribute must be applied. MessageHeader and MessageBodyMember must then be applied to types that should make up the SOPA header and body, respectively. MessageHeader and MessageBodyMember can be applied to all fields, properties and events, regardless of whether they are public, private, protected or internal. Each class member annotated with MessageHeader and MessageBodyMember must be serializeable. This means that class members that are user-defined must have a data contract, or must be a primitive type. A messaging-style operation is an operation in which there is at most one parameter and at most one return value where both types are message types. CustomerMessage represents a custom user-defined messaged that will be passed to and from service operations. Instead of individual service operations to manager the customer, the custom message contains the operation that should be applied. MessageContract public class CustomerMessage private Guid id private Address address private string operation private string status Because Address is a user-defined type, it has a data contract so that it can be serialized MessageBodyMember public Address CustomerAddress get set There are three services: CustomerService. This service illustrates usage of data contracts. CustomerMessageService. This service illustrates usage of message contracts. ServiceContract(Namespacequotdiranieh wcf samplesquot) public interface ICustomerService No DataContract required since return type is a primitive type OperationContract int GetCustomerCount() DataContract is required since Customer is a user-defined type OperationContract int AddCustomer(Customer customer) DataContract is required since Customer is a user-defined type OperationContract Customer GetCustomer(int id) The following class implements the ICustomerService contract. It is assumed that the class manages customers by interacting with a database ServiceBehavior(InstanceContextModeInstanceContextMode. PerCall) public class CustomerService. ICustomerService Having a constructor allows you to monitor when objects are created. For example, with InstanceContextMode. PerCall, an instance will be created for each call. This is usually a good place to debug and monitor incoming calls. Becuase CustomerService is configured to be PerCall, the constructor will be invoked for each incoming call public CustomerService() OperationContext opContext OperationContext. Current Output some debugging info Trace. WriteLine(quotopContext. Channel. OperationTimeout: quot opContext. Channel. OperationTimeout) Trace. WriteLine(quotopContext. Channel. LocalAddress. Uri: quot opContext. Channel. LocalAddress. Uri) Trace. WriteLine(quotopContext. Channel. SessionId: quot opContext. Channel. SessionId) Trace. WriteLine(quotopContext. Host. Description: quot opContext. Host. Description) Trace. WriteLine(quotopContext. IncomingMessageHeaders: quot opContext. IncomingMessageHeaders) Display incoming message headers foreach (MessageHeaderInfo mhi in opContext. IncomingMessageHeaders) Trace. WriteLine(quotMessage Header: quot mhi. ToString() ) region ICustomerService Members public int GetCustomerCount() Trace. WriteLine(quotGetCustomerCountquot) Get customer count from database return GetCustomerCou ntFromDB() public int AddCustomer(Customer customer) Trace. WriteLine(quotAddCustomer: quot customer. Name) Add customer to database return AddCustomerToDB(customer) Note that this method GetCustomerFromDB return Customer2 but it returned as Customer. Customer2 class is listed as a known type for Customer class public Customer GetCustomer(int id) Trace. WriteLine(quotGetCustomer: quot id) Get customer from database return GetCustomerFromDB(id) endregion region Helpers - dummy implementations private int AddCustomerToDB(Customer customer) Random r new Random(10) return r. Next(0, 100) private Customer2 GetCustomerFromDB(int id) Customer2 cust new Customer2() cust. Name quotYazanquot cust. Address quotDotNetVillequot cust. DOB DateTime. Parse(quot01 01 1999quot) return cust private int GetCustomerCountFromDB() return 10 endregion Output when calling GetCustomerCount: opContext. Channel. OperationTimeout: 00:03:00 opContext. Channel. LocalAddress. Uri: net. tcp: localhost:9000 SampleServiceContracts opContext. Channel. SessionId: uuid:25d45439-aeac-4e7f-b2af-37bb8577758eid1 opContext. Host. Description: System. ServiceModel. Description. ServiceDescription opContext. IncomingMessageHeaders: System. ServiceModel. Channels. MessageHeaders Mess age Header: ltAction d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtdiranieh wcf samples ICustomerService GetCustomerCountlt Actiongt Message Header: ltMessageID xmlnsquotw3.org 2005 08 addressingquotgturn:uuid:6898282e-e37c-484a-9494-322db9015124lt MessageIDgt Message Header: ltReplyTo xmlnsquotw3.org 2005 08 addressingquotgt ltAddressgtw3.org 2005 08 addressing anonymouslt Addressgt lt ReplyTogt Message Header: ltTo d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtnet. tcp: localhost:9000 SampleServiceContractslt Togt Output when calling AddCustomer: opContext. Channel. OperationTimeout: 00:03:00 opContext. Channel. LocalAddress. Uri: net. tcp: localhost:9000 SampleServiceContracts opContext. Channel. SessionId: uuid:25d45439-aeac-4e7f-b2af-37bb8577758eid1 opContext. Host. Description: System. ServiceModel. Description. ServiceDescription opContext. IncomingMessa geHeaders: System. ServiceModel. Channels. MessageHeaders Message Header: ltAction d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtdiranieh wcf samples ICustomerService AddCustomerlt Actiongt Message Header: ltMessageID xmlnsquotw3.org 2005 08 addressingquotgturn:uuid:f28e9347-d79e-4d67-8e31-b64de0ee38bflt MessageIDgt Message Header: ltReplyTo xmlnsquotw3.org 2005 08 addressingquotgt ltAddressgtw3.org 2005 08 addressing anonymouslt Addressgt lt ReplyTogt Message Header: ltTo d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtnet. tcp: localhost:9000 SampleServiceContractslt Togt Note that both calls have the same session id. If client were to close the proxy between each call, there would be different sessions ids for each call. ServiceContract(Namespace quotdiranieh wcf samplesquot) public interface ICustomerMessageService Note: The following error is generated if methods signature was not valid (return type is not a message conrtract, more than on parameter): quot The operation ProcessCustomer could not be loaded because it has a parameter or return type of type System. ServiceModel. Channels. Message or a type that has MessageContractAttribute and other parameters of different types. When using System. ServiceModel. Channels. Message or types with MessageContractAttribute, the method must not use any other types of parameters quot OperationContract CustomerMessage ProcessCustomer(CustomerMessage customer) ServiceBehavior(InstanceContextMode InstanceContextMode. PerCall) public class CustomerMessageService. ICustomerMessageService region Constructors public CustomerMessageService() OperationContext opContext OperationContext. Current Output some debugging info Trace. WriteLine(quotopContext. Channel. OperationTimeout: quot opContext. Channel. OperationTimeout) Trace. WriteLine(quotopContext. Channel. LocalAddress. Uri: quot opContext. Channel. LocalAddress. Uri) Trace. WriteLine(quotopContext. Channel. SessionId: quot opContext. Channel. SessionId) Trace. WriteLine(quotopContext. Host. Description: quot opContext. Host. Description) Trace. WriteLine(quotopContext. IncomingMessageHeaders: quot opContext. IncomingMessageHeaders) Display incoming message headers foreach (MessageHeaderInfo mhi in opContext. IncomingMessageHeaders) Trace. WriteLine(quotMessage Header: quot mhi. ToString() ) endregion region ICustomerMessageService Members public CustomerMessage ProcessCustomer(CustomerMessage customer) Debugging Trace. WriteLine(quotCustomer ID: quot customer. CustomerID quotnAddress: quot customer. Custo merAddress. ToString()) Process the customer based on the supplied operation switch (customer. Operation) case quotDeletequot: Delete customer. customer. Status quotDeletedquot break case quotAddquot: Add customer. customer. Status quotAddedquot break default: break return customer endregion Note the following constructor output when this service is called: opContext. Channel. OperationTimeout: 00:03:00 opContext. Channel. LocalAddress. Uri: net. tcp: localhost:9001 SampleServiceContracts opContext. Channel. SessionId: uuid:9236a01c-414f-41d3-948f-ce5bf3b6a42fid1 opContext. Host. Description: System. ServiceModel. Description. ServiceDescription opContext. IncomingMessageHeaders: System. ServiceModel. Channels. MessageHeaders Message Header: ltAction d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtdiranieh wcf samples ICustomerMessageService ProcessCustomerlt Actiongt Message Header: System. ServiceModel. Channels. HeaderInfoCacheHeaderInfo Message Header: ltMessageID xmlnsquotw3.org 2005 08 addressingquotgturn:uuid:2f31ce1d-3844-4005-b831-10c86a3187fclt MessageIDgt Message Header: ltReplyTo xmlnsquotw3.org 2005 08 addressingquotgt ltAddressgt w3.org 2005 08 addressing anonymouslt Addressgt lt ReplyTogt Message Header: ltTo d1p1:mustUnderstandquot1quot xmlns:d1p1quotw3.org 2003 05 soap-envelopequot xmlnsquotw3.org 2005 08 addressingquotgtnet. tcp: localhost:9001 SampleServiceContractslt Togt ServiceContract(Namespace quotdiranieh wcf samplesquot) public interface ICustomerUntypedMessageService It is important to specify the Action and Reply action values to ensure that they are the same between the client and the service. If Action and ReplyAction properties below were not specified, the following error would be generated: quotOutgoing request message for operation ProcessCustomer specified Actiondiranieh wcf samples RequestAction, but contract for that operation specifies Action diranieh wcf samples ICustomerUntypedMessageService ProcessCustomer . The Action specified in the Message must match the Action in the contract, or the operation contract must specify Action quot. OperationContract(Action CustomerUntypedMessageService. Request, ReplyAction CustomerUntypedMessageService. Reply) Message ProcessCustomer(Message msg) region ICustomerUntypedMessageService Members public Message ProcessCustomer(Message msg) Get message data string data msg. GetBodyltstringgt() Process message based on message data string operation data0 string param1 data1 string param2 data2 object oResult null if (operation quotAddquot) oResult Convert. ToInt32(param1) Convert. ToInt32(param2) if (operation quotSubstractquot) oResult Convert. ToInt32(param1) - Convert. ToInt32(param2) if (operation quotMultiplyquot) oResult Convert. ToInt32(param1) Convert. ToInt32(param2) Return response Message reply Message. CreateMessage(msg. Version, Reply, oResult) return reply endregion ltxml versionquot1.0quot encodingquotutf-8quot gt ltconfigurationgt lt-- To create this file, either create it manually inside VS. NET making use of intellisense, or use the SvcConfigEditor. exe utility to create and edit WCF configuration files --gt ltsystem. serviceModelgt ltservicesgt lt-- SERVICE 1 --gt lt-- Recall that name corresponds to the fully-qualified name of the type implementing the contract--gt ltservice namequotServiceContracts. CustomerService quot behaviorConfigurationquot GeneralBehavior quotgt lt-- Note address syntax for the netTcpBinding binding. Note that netTcpBinding is case-sensitive. If binding was equal to NetTcpBinding, you would get the following error: Configuration binding extension system. serviceModel bindings NetTcpBinding could not be found. Verify that this binding extension is properly registered in system. serviceModel extensions bindingExtensions and that it is spelled correctly.--gt ltendpoint addressquotnet. tcp: localhost:9000 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquotServiceContracts. ICustomerServicequot bindingConfigurationquot TcpBinding quotgt lt endpointgt lt servicegt lt-- SERVICE 2--gt lt-- Note that the address must specify a different port number or end with a different name. Otheriwse, the following error is generated: quotA registration already exists for URI net. tcp: localhost:9000 SampleServiceContractsquot --gt ltservice namequotServiceContracts. CustomerMessageService quot behaviorConfigurationquot GeneralBehavior quotgt ltendpoint addressquotnet. tcp: localhost:9001 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquotServiceContracts. ICustomerMessageServicequot bindingConfigurationquot TcpBinding quotgt lt endpointgt lt servicegt lt-- SERVICE 3--gt ltservice namequotServiceContracts. CustomerUntypedMessageService quot behaviorConfigurationquot GeneralBehavior quotgt ltendpoint addressquotnet. tcp: localhost:9002 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquotServiceContracts. ICustomerUntypedMessageServicequot bindingConfigurationquot TcpBinding quotgt lt endpointgt lt servicegt lt servicesgt lt-- Behaviours for the service--gt ltbehaviorsgt ltserviceBehaviorsgt lt-- The name attribute is used to link the following behaviour to a service via the behaviorConfiguration attribute. See the service named ServiceContracts. CustomerService --gt ltbehavior namequot GeneralBehavior quotgt ltserviceDebug includeExceptionDetailInFaultsquotTruequot gt lt behaviorgt lt serviceBehaviorsgt lt behaviorsgt lt-- The following binding is used to configure the netTcpBinding used in the endpoint element above. The netTcpBinding is configured to increase timeout values (default was 1 minute) to allow server-side debugging without letting the client timeout. Otherwise, you get the following exception: quotThis request operation sent to net. tcp: localhost:9000 SampleServiceContracts did not receive a reply within the configured timeout (00:01:00). The time allotted to this operation may have been a portion of a longer timeout. This may be because the service is still processing the operation or because the service was unable to send a reply message. Please consider increasing the operation timeout (by casting the channel proxy to IContextChannel and setting the OperationTimeout property) and ensure that the service is able to connect to the client --gt ltbindingsgt ltnetTcpBindinggt ltbinding namequot TcpBinding quot closeTimeoutquot00:03:00quot openTimeoutquot00:03:00quot receiveTimeoutquot00:03:00quot sendTimeoutquot00:03:00quotgt lt bindinggt lt netTcpBindinggt lt bindingsgt lt system. serviceModelgt lt configurationgt static class ServiceCommon internal static ServiceHost StartService(Type typService) ServiceHost sh new ServiceHost(typService) Open myServiceHost sh. Open() Output some debugging information Diagnostics. DisplayInfo(sh) internal static void StopService(ServiceHost sh) Call StopService from your shutdown logic (i. e. dispose method) Trace. WriteLine(quot Service state: quot sh. State. ToString()) if (sh. State CommunicationState. Closed) sh. Close() Trace. WriteLine(quot Service closedquot) class Program stat ic void Main(string args) Start all services exposed by this host ServiceHost shDC ServiceCommon. StartService(typeof(CustomerService)) ServiceHost shMC ServiceCommon. StartService(typeof(CustomerMessageService)) ServiceHost shUMC ServiceCommon. StartService(typeof(CustomerUntypedMessageService)) The service can now be accessed until user presses ltreturngt to terminate the service Console. WriteLine(quotThe service is readyquot) Console. WriteLine(quotPress ltRETURNgt to terminate the servicequot) Console. ReadLine() Stop all services exposed by this host ServiceCommon. StopService(shDC) ServiceCommon. StopService(shMC) ServiceCommon. StopService(shUMC) The code below shows the client configuration file and the actual client code: ltxml versionquot1.0quot encodingquotutf-8quot gt ltconfigurationgt ltsystem. serviceModelgt ltclientgt lt-- Again, not the use of a different port number for each each point. See comments in the servicee config file --gt ltendpoint namequotBasicDataContractConfigquot addressquotnet. tcp: localhost: 9000 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquot ICustomerService quot gt lt endpointgt ltendpoint namequotBasicMessageContractConfigquot addressquotnet. tcp: localhost: 9001 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquot ICustomerMessageService quot gt lt endpointgt ltendpoint namequotBasicUntypedMessageContractConfigquot addressquotnet. tcp: localhost: 9002 SampleServiceContractsquot bindingquotnetTcpBindingquot contractquot ICustomerUntypedMessageService quot gt lt endpointgt lt clientgt lt system. serviceModelgt lt configurationgt Code for actual client that is used to invoke WCF service public partial class Window1. System. Windows. Window . region Event handlers private void DataContractClickHandler(object sender, RoutedEventArgs args) CustomerServiceClient proxy new CustomerServiceClient(quotBasicDataContractConfigquot) int nCount proxy. GetCustomerCount() Add a new customer. Note: Initially, I forgot to apply the DataMember attribute to the Address property on Customer. Address property was therefore not available on customer instance. After adding DataMember to the Customer class, the Address property was available to be invoked on the customer object Customer c1 new Customer() c1.Name quotMyNamequot c1.Address quotMyAddressquot int nNewCustomer proxy. AddCustomer(c1) Retrieve a customer Customer c2 proxy. GetCustomer( 1234) if (c2 is Customer2) Trace. WriteLine(quotDOB: quot ((Customer2)c2).DOB) private void MessageContractClickHandler(object sender, RoutedEventArgs args) Craeat proxy to service object CustomerMessageServiceClient proxy new CustomerMessageServiceClient(quotBasicMessageContractConfigquot) Construct parameter for the AddCustomer method Note: Could not initialize Address via its constructor. Why is constructor not available Address address new Address() address. AddressLine1 quotLine1quot address. AddressLine2 quotLine2quot address. City quotMyCityquot address. PostCode quotMyPostcodequot CustomerMessage cm new CustomerMessage() cm. CustomerAddress address cm. Operation quotAddquot Call the service object. Note how the proxy is casted to ICustomerMessageService Otherwise, the signature for AddCustomer on the proxy object will be : public void AddCustomer(ref Guid CustomerID, ref Address CustomerAddress) Casting makes the syntax cleaner CustomerMessage cmUpdated ((ICustomerMessageService)proxy).ProcessCustomer( cm ) Trace. WriteLine(quotCustomer Status:quot cmUpdated. Status) private void UntypedMessageContractClickHandler(object sender, RoutedEventArgs args) Create proxy CustomerUntypedMessageServiceClient proxy new CustomerUntypedMessageServiceClient(quotBasicUntypedMessageContractConfigquot) Prepare request message OperationContextScope scope new OperationContextScope(proxy. InnerChannel) string astrMsgData new string String Request quotdiranieh wcf samples RequestAction quot Message request Message. CreateMessage(OperationContext. Current. OutgoingMessageHeaders. MessageVersion, Request, astrMsgData) Send message to service Message response proxy. ProcessCustomer(re quest) Process response int nValue response. GetBodyltintgt() Trace. WriteLine(quotValue quot nValue. ToString()) Basic Considerations WCF is an XML-based communication infrastructure. A major concern for system architects is the footprint of messages sent across the wire. The following sections address this concern. Text Vs. Binary While XML-text encoded messages are very transparent and quothuman readablequot, binary messages are often fairly obscure in comparison and difficult to decode without tools. This simple difference in legibility easily leads one to neglect that binary messages also often carry inline metadata alongside the payload, which adds overhead just as with XML text messages. This is specifically true for binary formats that aim to provide loose-coupling and dynamic invocation capabilities. In general, the size of a single serialized payload object will be quite similar when comparing text to binary representations. Still, for certain data types such as numbers, there is a disadvantage to using fixed-size, binary numerical representations such as a 128-bit decimal type instead of plain text as the plain text representation might indeed be several bytes smaller. Text data also might have size benefits from the typically more flexible XML text encoding choices, while some binary formats might choose to default to 16-bit or even 32-bit Unicode (which does not apply to the. NET Binary XML Format). As a result, the text vs. binary choice is not quite as simple as to assume that binary messages are always smaller than XML-text messages . Binary Content One area where binary encodings are clearly superior to text based encodings in terms of the resulting message size are large binary data items such as pictures, videos, sound-clips, or any other form of opaque, binary data that needs to be exchanged between services and their consumers. To fit these types of data into XML text, the common approach is to encode them using the Base64 encoding. Large Content By default, WCF processes messages in quotbuffered modequot. This means that the entire content of a message will be present in memory before it is being sent or after it has been received. While that is a good strategy for most scenarios, very large messages might easily end up exhausting a systems resources. The strategy to deal with very large payloads is streaming. When data is transferred in a streaming mode instead of a buffered mode, the message body contents will be made available by the sender and to the recipient in form of a stream and the message infrastructure continuously forwards the data from sender to receiver as it being made available. The most common scenario in which such large data content transfers occur are transfers of binary data objects that : Cannot be broken up into a message sequence easily. Need to be delivered in a very timely manner Are not available in their entirety when the transfer is initiated. For data that does not have any of these constraints, it is typically better to send sequences of messages within the scope of a session than one large message. Streaming is available and easily enabled on all standard bindings except the MSMQ-based NetMsmqBinding and the MsmqIntegrationBinding. The MSMQ transport only supports buffered data transfers with a constrained message size, while all other transports do not have any practical message size limit for the vast majority of scenarios. Streaming can be enabled in three different ways: Send accept requests in streaming mode and accept return responses in buffered mode ( StreamedRequest ). Send accept requests in buffered mode and accept return responses in streamed mode ( StreamedResponse ) Send and receive requests and responses in streamed mode in both directions. (Streamed) Streaming is disabled by setting the transfer mode to Buffered, which is the default setting on all bindings. You can set the transfer mode in configuration as shown in the snippets shown below: ltsystem. serviceModelgt ltbindingsgt ltwsHttpBindinggt ltbinding namequotExampleBindingquot transferModequotStreamingquot gt lt wsHttpBindinggt lt bindingsgt ltsystem. serviceModelgt Programming Model for Streamed Transfers For receiving streamed data, you need to specify an operation contract that has a single Stream typed input parameter. For returning streamed data you return a Stream reference: ServiceContract(NamespacequotMicrosoft. ServiceModel. Samplesquot) public interface IStreamedService OperationContract Stream Echo( Stream data) OperationContract Stream RequestInfo(string query) OperationContract(OneWaytrue) void ProvideInfo( Stream data) Note that adding a second parameter to the Echo() or ProvideInfo() operations below would cause the service model to revert back to a buffered strategy and use the runtime serialization representation of the stream. Only operations with a single input stream parameter are compatible with end-to-end request streaming .
Comments
Post a Comment