<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>LUTI @ Microsoft : WSDL</title><link>http://blogs.msdn.com/luti/archive/tags/WSDL/default.aspx</link><description>Tags: WSDL</description><dc:language>en</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>[WCF] Controlando minOccur e nillable no WSDL (-&gt; XSD)</title><link>http://blogs.msdn.com/luti/archive/2008/11/13/wcf-controlando-minoccur-e-nillable-no-wsdl-xsd.aspx</link><pubDate>Thu, 13 Nov 2008 20:27:37 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:9066762</guid><dc:creator>Luciano Caixeta Moreira</dc:creator><slash:comments>5</slash:comments><comments>http://blogs.msdn.com/luti/comments/9066762.aspx</comments><wfw:commentRss>http://blogs.msdn.com/luti/commentrss.aspx?PostID=9066762</wfw:commentRss><description>&lt;p&gt;Recebi um questionamento de um cliente e minha resposta acabou tendo um desdobramento curioso que compartilho com voc&amp;#234;s.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;     &lt;br /&gt;Problema e solu&amp;#231;&amp;#227;o&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;A pergunta era mais ou menos assim: &amp;quot;Eu tenho um servi&amp;#231;o que exp&amp;#245;e um tipo complexo e quero alterar o minOccurs de um elemento para ser minOccurs=1. Por&amp;#233;m o WSDL n&amp;#227;o est&amp;#225; gerando o que eu estou pedindo, mesmo utilizando o atributo XMLElement na defini&amp;#231;&amp;#227;o da propriedade&amp;quot;.    &lt;br /&gt;Para ajud&amp;#225;-lo eu montei um projeto simples que exp&amp;#245;e um servi&amp;#231;o e defini um m&amp;#233;todo que recebe como par&amp;#226;metro o tipo complexo InfoPapel, que possui algumas propriedades, entre elas a seguinte (mesmos atributos informados pelo cliente, a classe eu inventei):&lt;/p&gt;  &lt;p&gt;[XmlElement(IsNullable = false)]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [DataMember]     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public string NomePapel     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return nomePapel; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set { nomePapel = value; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;Essa defini&amp;#231;&amp;#227;o ir&amp;#225; gerar a seguinte defini&amp;#231;&amp;#227;o de esquema:&lt;/p&gt;  &lt;p&gt;&amp;#160; &amp;lt;xs:complexType name=&amp;quot;InfoPapel&amp;quot;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:sequence&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; name=&amp;quot;NomePapel&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:element name=&amp;quot;Empresa&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/xs:sequence&amp;gt;     &lt;br /&gt;&amp;#160; &amp;lt;/xs:complexType&amp;gt;&lt;/p&gt;  &lt;p&gt;O problema aqui est&amp;#225; na utiliza&amp;#231;&amp;#227;o do XmlElement ao inv&amp;#233;s de utilizar a propriedade &lt;strong&gt;IsRequired&lt;/strong&gt; do atributo DataMember. Para entendimento, o WCF possui tr&amp;#234;s serializadores: XMLSerializer, DataContractSerializer, e NetDataContractSerializer (&lt;a title="http://msdn.microsoft.com/en-us/magazine/cc163569.aspx" href="http://msdn.microsoft.com/en-us/magazine/cc163569.aspx"&gt;http://msdn.microsoft.com/en-us/magazine/cc163569.aspx&lt;/a&gt;), sendo que por padr&amp;#227;o &amp;#233; utilizado o DataContractSerializer. Utilizando o padr&amp;#227;o, o serializador vai ignorar o atributo XmlElement, n&amp;#227;o gerando um WSDL diferente, como esperado.&lt;/p&gt;  &lt;p&gt;Se alterarmos nosso c&amp;#243;digo para utilizar as propriedade do DataMember, poderemos controlar efetivamente o esquema gerado, conforme vemos abaixo:&lt;/p&gt;  &lt;p&gt;[DataMember(IsRequired = true, Order = 1)]    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; public string NomePapel     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; get { return nomePapel; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; set { nomePapel = value; }     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }&lt;/p&gt;  &lt;p&gt;&amp;#160; &amp;lt;xs:complexType name=&amp;quot;InfoPapel&amp;quot;&amp;gt;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:sequence&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:element name=&amp;quot;NomePapel&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;lt;xs:element name=&amp;quot;Empresa&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;lt;/xs:sequence&amp;gt;     &lt;br /&gt;&amp;#160; &amp;lt;/xs:complexType&amp;gt;&lt;/p&gt;  &lt;p&gt;Veja que n&amp;#227;o temos mais o minOccurs=&amp;quot;0&amp;quot; na defini&amp;#231;&amp;#227;o do esquema e, sabendo que por padr&amp;#227;o o minOccurs &amp;#233; igual a 1 (especifica&amp;#231;&amp;#227;o do XSD), conseguimos o resultado esperado, que era um minOccurs=&amp;quot;1&amp;quot;.&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;     &lt;br /&gt;XmlSerializerFormat&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Se voc&amp;#234; quer utilizar o serializador XML (utilizado pelo ASP.NET web services), precisa colocar junto ao atributo ServiceContract , definido na interface, outro atributo:&amp;#160; XmlSerializerFormat. Utilizando esse atributo, quando o WCF for gerar o WSDL e XSDs relacionados, ele ir&amp;#225; levar em conta o atributo XmlElement e ignorar o DataMember.&lt;/p&gt;  &lt;p&gt;O que me chamou a aten&amp;#231;&amp;#227;o foi a aus&amp;#234;ncia da propriedade IsNullable no atributo DataMember e a aus&amp;#234;ncia da propriedade IsRequired no atributo XmlElement.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;&lt;strong&gt;minOccurs vs. nillable&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Se dermos uma olhada na especifica&amp;#231;&amp;#227;o do XML Schema Definition (XSD) em &lt;a title="http://www.w3.org/TR/xmlschema-0/" href="http://www.w3.org/TR/xmlschema-0/"&gt;http://www.w3.org/TR/xmlschema-0/&lt;/a&gt;, temos uma explica&amp;#231;&amp;#227;o clara das diferen&amp;#231;as: em uma defini&amp;#231;&amp;#227;o de esquema, um elemento pode aparecer de X a Y vezes, sendo controlado pelo minOccurs e maxOccurs, enquanto o nillable define um elemento que aparece no XML mas n&amp;#227;o possui nenhum valor, utilizando o atributo xsi:nil=&amp;quot;true&amp;quot; no elemento. Note que dependendo do objetivo do XML que voc&amp;#234; est&amp;#225; manipulando, pode existir diferen&amp;#231;as sem&amp;#226;nticas na aus&amp;#234;ncia de um elemento (minOccurs = 0) e no aparecimento de um elemento marcado como nulo. E a&amp;#237;?&lt;/p&gt;  &lt;p&gt;Quando utilizamos o XmlElement e XmlSerializerFormat, conseguimos dois formatos de sa&amp;#237;da:&lt;/p&gt;  &lt;p&gt;Quando &amp;#8220;IsNullable = false&amp;#8221; o atributo nillable desaparece e minOccurs = 0.    &lt;br /&gt;&amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;NomePapel&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;Quando &amp;#8220;IsNullable = true&amp;#8221; o atributo nillable aparece e minOccurs = 1!    &lt;br /&gt;&amp;lt;xs:element minOccurs=&amp;quot;1&amp;quot; maxOccurs=&amp;quot;1&amp;quot; name=&amp;quot;NomePapel&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt;&lt;/p&gt;  &lt;p&gt;No primeiro caso ou o elemento n&amp;#227;o aparece ou ele aparece com um valor definido. Note por&amp;#233;m que no segundo caso, como o nulo dever&amp;#225; ser informado no XML como um atributo do elemento, o XSD est&amp;#225; definindo o elemento com minOccurs=1, isto &amp;#233;, se existe a possibilidade dele ser nulo, o elemento t&amp;#234;m que estar presente.&lt;/p&gt;  &lt;p&gt;   &lt;br /&gt;J&amp;#225; na utilia&amp;#231;&amp;#227;o do DataContractSerializer com o DataMember, conseguimos obter duas defini&amp;#231;&amp;#245;es diferentes utilizando ou n&amp;#227;o o IsRequired:&lt;/p&gt;  &lt;p&gt;&amp;lt;xs:element minOccurs=&amp;quot;0&amp;quot; name=&amp;quot;NomePapel&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt; (IsRequired = false)    &lt;br /&gt;&amp;lt;xs:element name=&amp;quot;NomePapel&amp;quot; nillable=&amp;quot;true&amp;quot; type=&amp;quot;xs:string&amp;quot; /&amp;gt; (IsRequired = true)&lt;/p&gt;  &lt;p&gt;Note que aqui n&amp;#227;o temos a defini&amp;#231;&amp;#227;o do elemento tipo string para n&amp;#227;o aceitar nulos, por se tratar de um tipo por refer&amp;#234;ncia. Por outro lado, conseguimos ter um minOccurs=&amp;quot;0&amp;quot; com nillable=&amp;quot;true&amp;quot;, o que n&amp;#227;o consegui atrav&amp;#233;s do XmlElement.&lt;/p&gt;  &lt;p&gt;N&amp;#227;o vi uma maneira f&amp;#225;cil (nem sei &amp;#233; poss&amp;#237;vel e se faz sentido) do DataMember definir um elemento string como nillable=&amp;quot;false&amp;quot;. Algu&amp;#233;m sabe?&lt;/p&gt;  &lt;p&gt;&lt;strong&gt;     &lt;br /&gt;Finalizando...&lt;/strong&gt;&lt;/p&gt;  &lt;p&gt;Al&amp;#233;m do lado geek do post e da explica&amp;#231;&amp;#227;o dos serializers e atributos, fica uma pergunta: porque eu mencionei essa hist&amp;#243;ria do minOccurs e nillable? Esse post surgiu num contexto de interoperabilidade e o preciosismo pode at&amp;#233; parecer in&amp;#250;til, mas eu acredito que quanto mais conhecermos os detalhes do que est&amp;#225; acontecendo com nossos servi&amp;#231;os, mais f&amp;#225;cil ser&amp;#225; de resolvermos um eventual problema de interop. Vai que a gente cruza com um gerador de proxies mais enjoadinho...&lt;/p&gt;  &lt;p&gt;&amp;#160;&lt;/p&gt;  &lt;p&gt;[]s    &lt;br /&gt;Luciano Caixeta Moreira     &lt;br /&gt;&lt;a href="mailto:luciano.moreira@microsoft.com"&gt;luciano.moreira@microsoft.com&lt;/a&gt;     &lt;br /&gt;===============================================     &lt;br /&gt;This post is provided &amp;quot;AS IS&amp;quot; and confers no right     &lt;br /&gt;===============================================&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=9066762" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/luti/archive/tags/WCF/default.aspx">WCF</category><category domain="http://blogs.msdn.com/luti/archive/tags/XSD/default.aspx">XSD</category><category domain="http://blogs.msdn.com/luti/archive/tags/WSDL/default.aspx">WSDL</category></item></channel></rss>