Share via


IsRequired Attribute on DataMember

Question

Thursday, September 13, 2007 3:32 PM

 

Hi,

 

I have a DataContract that has various data members which some have the is required attribute set to true. However when I reference the service the client ignores these fields and pass the Data Contract object to the service. How do I get so that if a field is not present to produce an error before it being sent to the service?

All replies (13)

Thursday, September 13, 2007 6:10 PM âś…Answered | 2 votes

The IsRequired attribute on the data member refers to the validation that happens on the data that is arriving on the wire. Imagine, for example, that you have this data contract:

Code Snippet

[DataContract]

public class MyDC {

[DataMember]

public string str = "Hello";

[DataMember(IsRequired = true)]

public int i;

}

 

[ServiceContract]

public interface ITest {

[OperationContract]

string Process(MyDC dc);

}

 

 

When the client sends a request to a server for an operation that takes a MyDC as a parameter, the message on the wire will contain something like

<dc ...>

<str>Hello</str>

<i>123</i>

</dc>

 

In this case, the operation should succeed. If the client had sent the value for MyDC below:

<dc ...>

<i>123</i>

</dc>

 

It would still succeed, and the operation would receive a MyDC object with the field "str" with the default value for string (null). However, if this request was sent:

<dc ...>

<str>Hello</str>

</dc>

 

Then the request would fail - because the data contract MyDC requires that the member "i" is present on the wire.

 

Does it make sense?

 

If you want validation done at the client side, however, you'll going to need to add code to the client code for that. Another thing you'll have to keep in mind is the definition of "not present". Given that you have an object of type MyDC (as defined above), what does it mean for it not to have the field "i" present? On the definition above I didn't set any value, but the CLR will set it to zero (default for integer) automatically.


Friday, June 6, 2008 5:18 PM

I have a follow-up question about DataContract and IsRequired.  In the example below, I am developing a WCF service.

Let's say I have the following class.  It has 10 public attributes of type int, named mInt_1 ... mInt_10.  I keep the definition of the class simple for my questions.

    public sealed class Foo
    {
        [DataMember]
        public int mInt_1;
        ...
    }

Suppose that I have defined a service that exposes some APIs.  One API only wants to deal with from mInt_1 to mInt5.  Another API deals only with mInt_6 to mInt_10.

void From01To05( Foo aObject );
void From06To10( Foo aObject );

Based on the definition of Foo, each call to one of the APIs will send the entire XML data for the Foo object.

Question: Is there a way to "turn off" the XML serialization for mInt_6 to mInt_10 when I call From01To05() so that only the data for mInt_01 to mInt_05 gets serialized and sent over the wire?

I would appreciate any help and guidance that anyone can provide.  Thank you.


Friday, June 6, 2008 6:26 PM | 1 vote

Hi Alan,

 

Have you try adding IsRequired="false" to each data member?

 

HTH,

An

 


Friday, June 6, 2008 6:37 PM

You can set IsRequired=True and EmitDefaultValue=False.

 

This does is requires the Wcf runtime to serialize data member but do not serialize default values, i.e. do not serialize null values for reference types, 0 for integers, etc.

 

In effect, a runtime exception will be thrown if the data member has not been assign a value during serialization.

 


Thursday, June 12, 2008 5:51 PM

Hi An Phu,

I will try that out and let you know.  By the way, are you Vietnamese?

Alan


Thursday, June 12, 2008 8:36 PM

Hi An Phu,

That works!  Using the combination of IsRequired=false and EmitDefaultValue=false.

Thank you again.  Terrific!  :-)

Alan


Friday, June 17, 2011 12:39 PM

Hi All,

Tried with the option suggested, but getting the following error..

[DataMember (EmitDefaultValue=false, IsRequired =false)]
public bool BoolValue
{
get { return boolValue; }
set { boolValue = value; }
}

Error : 

 

http://schemas.xmlsoap.org/soap/envelope/%22%3E%3Cfaultcode xmlns:a="http://schemas.microsoft.com/net/2005/12/windowscommunicationfoundation/dispatcher">

a:DeserializationFailed</faultcode><faultstring xml:lang="en-GB">The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:composite. The InnerException message was 'There was an error deserializing the object of type WcfService.CompositeType. The value '' cannot be parsed as the type 'Boolean'.'.  Please see InnerException for more details.</faultstring>

Any Help would really appriciated

Thanks,

Mruthunjaya J


Friday, June 17, 2011 1:16 PM

Well from the error I would guess that the data came across as something that couldn't be interpreted as a boolean value. Can you turn  on message logging and see what was actually sent for this value?Richard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
Twitter: richardblewett


Friday, June 17, 2011 2:06 PM

Hi Blewett,

can you find if something is wrong in this ? but actually this is how we get the request from client.

scenerio 1

Request :

      <tem:GetBoolean>
         <!--Optional:-->
         <tem:composite1>
            <!--Optional:-->
            <wcf:EntityYesNo>true</wcf:EntityYesNo>
            <!--Optional:-->
            <wcf:StringValue>Hello</wcf:StringValue>
         </tem:composite1>
      </tem:GetBoolean>

Response:

I get response without any issues.

scenerio 2

Request :

      <tem:GetBoolean>
         <!--Optional:-->
         <tem:composite1>
            <!--Optional:--> 
            **<wcf:EntityYesNo/> **
            <!--Optional:-->
            <wcf:StringValue>Hello</wcf:StringValue>
         </tem:composite1>
      </tem:GetBoolean>

Response:

I get response with the following error

The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://tempuri.org/:composite. The InnerException message was 'There was an error deserializing the object of type WcfService.CompositeType. The value '' cannot be parsed as the type 'Boolean'.'

can you please point me what causing this error ?

 

Thanks,

Mruthunjaya J


Friday, June 17, 2011 2:26 PM

For EmitDefaultValue = false you should not have the wcf:EntityYesNo in the message at allRichard Blewett, thinktecture - http://www.dotnetconsult.co.uk/weblog2
Twitter: richardblewett


Monday, June 20, 2011 4:19 AM

Hi Blewett,

Client is using some middlware to form this request and hence we get the request only in the form mentioned below. client doesn't have an option to remove the **<wcf:EntityYesNo/> **tag.. but you are right removing that will work, but can you suggest any other alternative where we can solve this problem even when the  **<wcf:EntityYesNo/> **tag exists ?

Request :

      <tem:GetBoolean>
         <!--Optional:-->
         <tem:composite1>
            <!--Optional:--> 
            **<wcf:EntityYesNo/> **
            <!--Optional:-->
            <wcf:StringValue>Hello</wcf:StringValue>
         </tem:composite1>
      </tem:GetBoolean>

Thanks,

Mruthunjaya J


Thursday, March 15, 2012 10:49 AM

I am using wcf 4.0, here when i use is required=true, then wcf does not give me error, if i do not initialize it to any value, in service function default value is assigned to it. please help me


Wednesday, November 28, 2012 3:09 AM

Hello,

1.

Declare the **EntityYesNo **property as a string.

2. 

Override the de-serialization by implementing IXmlSerialization.

HTH,

An