Web API - Self close tag instead of i:nil
Asked Answered
B

2

9

I am using Web API with DataContract serialization. The output looks like this:

<Data>
<Status>
  <Date>2014-08-13T00:30:00</Date>
  <ID>312</ID>
  <Option>No Limitation</Option>
  <Value i:nil="true" />
</Status>
<Status>
  <Date>2014-08-13T01:00:00</Date>
  <ID>312</ID>
  <Option>No Limitation</Option>
  <Value i:nil="true" />
</Status>
<Status>
  <Date>2014-08-13T01:30:00</Date>
  <ID>312</ID>
  <Option>No Limitation</Option>
  <Value i:nil="true" />
</Status>
<Status>
  <Date>2014-08-13T02:00:00</Date>
  <ID>312</ID>
  <Option>No Limitation</Option>
  <Value i:nil="true" />
</Status>

I was able to remove all the extra namespaces by doing:

[DataContract(Namespace="")]
public class Status

But the only attribute left is the i:nil attribute. What should i do in order to remove the i:nil attribute?

Braw answered 17/8, 2014 at 6:43 Comment(2)
Would this solve your problem: #12465785, DataMember(EmitDefaultValue = false)]Bowman
@Prescott, that will remove the empty element at all. What I want is to show the element without the i:nil attribute.Braw
E
4

What you want is to make the code "think" that instead of having a null value, it actually has an empty string. You can do that by being a little smart with the property getter (see below). Just remember to add a comment explaining why you're doing that so other people who will maintain the code know what's going on.

[DataContract(Namespace = "")]
public class Status
{
    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string Option { get; set; }

    private string value;

    [DataMember]
    public string Value
    {
        get { return this.value ?? ""; }
        set { this.value = value; }
    }
}
Exocarp answered 20/8, 2014 at 22:22 Comment(2)
Simple and nice. That was exactly what I needed, Thanks.Braw
Great, works for me. After this change I had to change the code that uses this value from Value != null to string.IsNullOrEmpty(Value)Lumpfish
L
6

You need to set the EmitDefaultValue property in the DataMember attribute

[DataMember(EmitDefaultValue = false)]

Be sure not to set this attribute on members that have the IsRequired = true set to them.

Edit

You may also iterate the XML manually and remove the nil attributes using LINQ 2 XML:

XNamespace i = "http://www.w3.org/2001/XMLSchema-instance";
        XDocument xdoc = XDocument.Load(@"XmlHere"); // This may be replaced with XElement.Parse if the XML is in-memory

        xdoc.Descendants()
                 .Where(node => (string)node.Attribute(i + "nil") == "true")
                 .Remove();
Loosejointed answered 17/8, 2014 at 7:40 Comment(7)
That will remove the empty element at all, isn't it? I want to show the element but without the i:nil attribute.Braw
It will remove any null element, yes. I edited my answer with a way to manually remove the specified attributes.Loosejointed
What you are proposing is right, but in the case of Web API, you can't manipulate the XML like this, it is an internal serialization.Braw
You can by implementing IXmlSerializable yourself.Loosejointed
Take a look at thisLoosejointed
That will force me to use XmlSerializer but I need to use DataContract. Is there a way to remove i:nil attribute using DataContract?Braw
I haven't ever done that with DataContractSerializer. Sorry.Loosejointed
E
4

What you want is to make the code "think" that instead of having a null value, it actually has an empty string. You can do that by being a little smart with the property getter (see below). Just remember to add a comment explaining why you're doing that so other people who will maintain the code know what's going on.

[DataContract(Namespace = "")]
public class Status
{
    [DataMember]
    public DateTime Date { get; set; }

    [DataMember]
    public int ID { get; set; }

    [DataMember]
    public string Option { get; set; }

    private string value;

    [DataMember]
    public string Value
    {
        get { return this.value ?? ""; }
        set { this.value = value; }
    }
}
Exocarp answered 20/8, 2014 at 22:22 Comment(2)
Simple and nice. That was exactly what I needed, Thanks.Braw
Great, works for me. After this change I had to change the code that uses this value from Value != null to string.IsNullOrEmpty(Value)Lumpfish

© 2022 - 2024 — McMap. All rights reserved.