roroinpho21
roroinpho21

Reputation: 742

How to include empty xml elements in SOAP request using WCF?

I have to consume a Java web service. The signature of service method is

public bool UpsertEmployee(Employee employe);

The problem is when the SOAP is generated, for the properties with null value the coresponding XML elements are not included in request. The result is:

...
<Employee>
  <id>1</id>
  <firstName>Jhonny</firstName>
</Employee>

And I want to be:

...
<Employee>
  <id>1</id>
  <firstName>Jhonny</firstName>
  <lastName/>
</Employee>

Is there a way to accomplish this?

Can I set a property before mehod invocation?

var client= new EmployeeServiceClient();;
// Can I do something here to accoplish my goal?    
client.UpsertEmployee(new Employee{
    id = "1",
    firstname = "Jhonny"
});

The generated Employee class code is

[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Xml", "4.0.30319.36366")]
[System.SerializableAttribute()]
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.ComponentModel.DesignerCategoryAttribute("code")]
[System.Xml.Serialization.XmlTypeAttribute(Namespace = "urn:mve.go.all.mdg.vendor")]
public partial class Employee : object, System.ComponentModel.INotifyPropertyChanged
{

    private string idField;

    private string firstNameField;

    private string lastNameField;

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
    public string id
    {
        get
        {
            return this.idField;
        }
        set
        {
            this.idField = value;
            this.RaisePropertyChanged("id");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
    public string firstName
    {
        get
        {
            return this.firstNameField;
        }
        set
        {
            this.firstNameField = value;
            this.RaisePropertyChanged("firstName");
        }
    }

    /// <remarks/>
    [System.Xml.Serialization.XmlElementAttribute(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 3)]
    public string lastName
    {
        get
        {
            return this.lastNameField;
        }
        set
        {
            this.lastNameField = value;
            this.RaisePropertyChanged("lastName");
        }
    }

    public event System.ComponentModel.PropertyChangedEventHandler PropertyChanged;

    protected void RaisePropertyChanged(string propertyName)
    {
        System.ComponentModel.PropertyChangedEventHandler propertyChanged = this.PropertyChanged;
        if ((propertyChanged != null))
        {
            propertyChanged(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
        }
    }
}

I cannot modify the file code because in the future it is posible to need an update on the service reference.

Upvotes: 2

Views: 4258

Answers (1)

dbc
dbc

Reputation: 116514

Your class is marked with XmlSerializer attributes so it appears you are using that serializer.

Your problem is that the lastName property is null. As explained in Xsi:nil Attribute Binding Support:

When serializing objects into an XML document: If the XmlSerializer class encounters a null reference for an object corresponding to an XML element, it either generates an element that specifies xsi:nil="true" or leaves the element out entirely, depending on whether a nillable="true" setting applies.

Thus, by default, when lastName is null no element is emitted. And if you were to set [XmlElementAttribute(IsNullable = true)] you would instead get

<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>1</id>
  <firstName>Jhonny</firstName>
  <lastName xsi:nil="true" />
</Employee>

Which is not what you want (and in any event you cannot change the auto-generated code).

Instead you need to initialize lastName to the empty string:

var employee = new Employee
{
    id = "1",
    firstName = "Jhonny",
    lastName = "",
};

And then the following XML will be generated:

<Employee xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <id>1</id>
  <firstName>Jhonny</firstName>
  <lastName />
</Employee>

Or, since the auto-generated code does not have a default constructor, you could add one yourself in a separate partial class code file. Since it is independent from the auto-generated code file it will not gen overwritten when you regenerate the generated code:

public partial class Employee
{
    public Employee()
    {
        this.firstName = this.lastName = this.id = "";
    }
}

Upvotes: 3

Related Questions