tags:

views:

170

answers:

4

To my knowledge Uri implements ISerializable, but throws error when used like this:

XmlSerializer xs = new XmlSerializer(typeof(Server));
xs.Serialize(Console.Out, new Server { Name = "test", URI = new Uri("http://localhost/") });

public class Server
{
    public string Name { get; set; }
    public Uri URI { get; set; }
}

Works just fine if Uri type is changed to string.

Anyone knows what is the culprit?


Solution proposed by Anton Gogolev:

public class Server
{
    public string Name { get; set; }

    [XmlIgnore()]
    public Uri Uri; 

    [XmlElement("URI")]
    public string _URI // Unfortunately this has to be public to be xml serialized.
    { 
        get { return Uri.ToString(); }
        set { Uri = new Uri(value); }
    }
}

(Thanks for SLaks also pointing out the backwardness of my method...)

This produces XML output:

<Server>
    <URI>http://localhost/&lt;/URI&gt;
    <Name>test</Name>
</Server>

I rewrote it here so the code is visible.

+1  A: 

In order to be serialized to XML, Uri class should have a parameterless constructor, which it doesn't: Uri is designed to be immutable. Honestly, I can't see why it cannot be serialized without having a parameterless constructor.

To circumvent this, either change URI property type to string, or add one more property called _URI, mark URI with XmlIgnoreAttribute and rewrite it's get method as get { return new Uri(_URI); }.

Anton Gogolev
I added yoursolution to the question, just to make the code visible...
Ciantic
A: 

Inner exceptions says:

System.Uri cannot be serialized because it does not have a parameterless constructor.

Simple answer is that you can't serialize that to xml.

Beku
+1  A: 

You're confusing binary serialization with XML serialization.

XML serialization is a very simple process that saves field values and restores into a new object.

Binary serialization is much more powerful, and allows the object to control serialization behavior. The ISerializable interface, which Uri does implement, is only used for binary serialization.

SLaks
That indeed was the case. I thought the ISerializable means it's serializable by any serializer (including XML). But I didn't consider this as a answer to *my problem* because my actual problem was to get this XML Serialized.
Ciantic
Maybe I should change the topic, since this specifically is about xml serialization...
Ciantic
+1  A: 

Actually, the best solution would be the reverse - storing the value in a Uri property and accessing it with a string.

For example:

public class Server
{
    public string Name { get; set; }

    [XmlIgnore]
    public Uri Uri { get; set; }

    [XmlElement("URI")]
    public string UriString { 
        get { return Uri.ToString(); }
        set { Uri = new Uri(value); } 
    }
}

This way, it's impossible to set it to an invalid Uri (which would in your code throw an exception in the property getter). Also, to follow standard .Net casing guidelines, the property should be called Uri, not URI.

SLaks
Yes, thats correct, thanks for that! You don't mind if I added it to the code I wrote to question.
Ciantic
No, I don't mind.
SLaks