2009-07-13 8 views
10

Je reçois ce qui suit lors de la mise en série pour sérialiser un message en utilisant le foratter los.Comment sérialiser un message électronique?

Erreur: Sys.WebForms.PageRequestManagerServerErrorException: Erreur de sérialisation de la valeur 'System.Net.Mail.MailMessage' de type 'System.Net.Mail.MailMessage'.

Existe-t-il un moyen FACILE de sérialiser cet objet ou dois-je effectuer une sérialisation de chacune des propriétés individuellement?

+0

Où essayez-vous de le sérialiser? –

+0

J'essaie de le mettre dans un tableau d'octets. – Middletone

Répondre

0

Malheureusement, la classe System.Net.Mail.MailMessage n'est pas marquée comme sérialisable. Donc, oui, vous devrez le faire vous-même. Il y a une technique décrite dans l'article de blog suivant qui peut vous donner une idée de la façon dont vous pouvez procéder: How to Serialize a MailMessage ... fondamentalement, vous devrez retirer chacune des propriétés individuellement. Quote:

To serialize the properties of a MailMessage object you can create a new class and create a property of MailMessage type for it that embeds your MailMessage in the class. In this new class you can implement IXmlSerializable interface to manually serialize its MailMessage. Here I create this class and call it SerializableMailMessage [...]

[code implementation of WriteXml() and ReadXml() methods follow; see source link]

+0

Lien redirige vers la page d'accueil du blog. –

+0

Le lien est rompu. –

+0

@GunnarSteinn Merci - fixe. –

2

Je sais que c'est un ancien poste, mais j'avais aussi la question où je devais sérialiser la classe MailAddress donc je créé une version sérialisable. Si vous êtes en mesure d'utiliser une classe MailAddress personnalisée au lieu de la classe System.Net.Mail.MailAddress, cela peut fonctionner pour vous.

/// <summary> 
/// Serializable implementation of <see cref="System.Net.Mail.MailAddress"/>. 
/// </summary> 
[Serializable] 
public class MailAddress : System.Net.Mail.MailAddress, ISerializable 
{ 
    // Keep reference to the display name encoding so we can serialize/deserialize the value 
    private readonly Encoding _displayNameEncoding; 

    public MailAddress(string address) 
     : this(address, null, null) 
    { 
    } 

    public MailAddress(string address, string displayName) 
     : this(address, displayName, null) 
    { 
    } 

    public MailAddress(string address, string displayName, Encoding displayNameEncoding) 
     : base(address, displayName, displayNameEncoding) 
    { 
     // Keep reference to the supplied displayNameEncoding so we can serialize/deserialize this value 
     _displayNameEncoding = displayNameEncoding ?? Encoding.GetEncoding("utf-8"); 
    } 

    public void GetObjectData(SerializationInfo info, StreamingContext context) 
    { 
     info.AddValue("Address", base.Address); 
     info.AddValue("DisplayName", base.DisplayName); 
     info.AddValue("DisplayNameEncoding", _displayNameEncoding); 
    } 

    protected MailAddress(SerializationInfo info, StreamingContext context) 
     : this(info.GetString("Address"), info.GetString("DisplayName"), (Encoding)info.GetValue("DisplayNameEncoding", typeof (Encoding))) 
    { 
    } 
} 
2

Pour ceux qui recherchent le code source complet sur comment sérialiser MailMessage en XML écrit par Keyvan Nayyeri, voici le lien vers son github:

https://github.com/keyvan/Gopi/blob/master/Gopi/Gopi/SerializableMailMessage.cs

Et est ici la archives de son blog qui est maintenant défunte:

http://web.archive.org/web/20131124074822/http://keyvan.io/how-to-serialize-a-mailmessage

Juste au cas où le lien ci-dessus pourrait devenir mort aussi, ici, je repostez son blog ici:

Comment sérialiser un MailMessage

Il existe deux classes de MailMessage dans .NET. Le premier est dans l'espace de noms System.Web.Mail et est obsolète dans .NET 2.0 et versions ultérieures et le second est disponible dans System.Net.Mail. Je ne me soucie pas de la classe obsolète, donc je montre juste comment vous pouvez sérialiser les instances de la classe System.Net.Mail.MailMessage.

Pour sérialiser les propriétés d'un objet MailMessage, vous pouvez créer une nouvelle classe et créer une propriété de type MailMessage pour celle-ci qui incorpore votre MailMessage dans la classe. Dans cette nouvelle classe, vous pouvez implémenter l'interface IXmlSerializable pour sérialiser manuellement son MailMessage.

sérialisation

côté sérialisation du travail est aussi simple que la mise en œuvre de la méthode WriteXML. Le code ci-dessous est ce que j'ai écrit pour le faire.

public void WriteXml(XmlWriter writer) 
{ 
    if (this != null) 
    { 
     writer.WriteStartElement("MailMessage"); 
     writer.WriteAttributeString("Priority", Convert.ToInt16(this.Priority).ToString()); 
     writer.WriteAttributeString("IsBodyHtml", this.IsBodyHtml.ToString()); 

     // From 
     writer.WriteStartElement("From"); 
     if (!string.IsNullOrEmpty(this.From.DisplayName)) 
      writer.WriteAttributeString("DisplayName", this.From.DisplayName); 
     writer.WriteRaw(this.From.Address); 
     writer.WriteEndElement(); 

     // To 
     writer.WriteStartElement("To"); 
     writer.WriteStartElement("Addresses"); 
     foreach (MailAddress address in this.To) 
     { 
      writer.WriteStartElement("Address"); 
      if (!string.IsNullOrEmpty(address.DisplayName)) 
       writer.WriteAttributeString("DisplayName", address.DisplayName); 
      writer.WriteRaw(address.Address); 
      writer.WriteEndElement(); 
     } 
     writer.WriteEndElement(); 
     writer.WriteEndElement(); 

     // CC 
     if (this.CC.Count > 0) 
     { 
      writer.WriteStartElement("CC"); 
      writer.WriteStartElement("Addresses"); 
      foreach (MailAddress address in this.CC) 
      { 
       writer.WriteStartElement("Address"); 
       if (!string.IsNullOrEmpty(address.DisplayName)) 
        writer.WriteAttributeString("DisplayName", address.DisplayName); 
       writer.WriteRaw(address.Address); 
       writer.WriteEndElement(); 
      } 
      writer.WriteEndElement(); 
      writer.WriteEndElement(); 
     } 

     // Bcc 
     if (this.Bcc.Count > 0) 
     { 
      writer.WriteStartElement("Bcc"); 
      writer.WriteStartElement("Addresses"); 
      foreach (MailAddress address in this.Bcc) 
      { 
       writer.WriteStartElement("Address"); 
       if (!string.IsNullOrEmpty(address.DisplayName)) 
        writer.WriteAttributeString("DisplayName", address.DisplayName); 
       writer.WriteRaw(address.Address); 
       writer.WriteEndElement(); 
      } 
      writer.WriteEndElement(); 
      writer.WriteEndElement(); 
     } 

     // Subject 
     writer.WriteStartElement("Subject"); 
     writer.WriteRaw(this.Subject); 
     writer.WriteEndElement(); 

     // Body 
     writer.WriteStartElement("Body"); 
     writer.WriteCData(Body); 
     writer.WriteEndElement(); 

     writer.WriteEndElement(); 
    } 
} 

En suivant la même approche, vous pouvez sérialiser d'autres propriétés telles que les pièces jointes. La semaine prochaine, je vais publier la nouvelle version de Gopi qui contient le code mis à jour qui sérialise tout afin que vous puissiez attendre rapidement pour mettre la main sur le code.

Désérialisation

public void ReadXml(XmlReader reader) 
{ 
    XmlDocument xml = new XmlDocument(); 
    xml.Load(reader); 

    // Properties 
    XmlNode rootNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage"); 
    this.IsBodyHtml = Convert.ToBoolean(rootNode.Attributes["IsBodyHtml"].Value); 
    this.Priority = (MailPriority)Convert.ToInt16(rootNode.Attributes["Priority"].Value); 

    // From 
    XmlNode fromNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/From"); 
    string fromDisplayName = string.Empty; 
    if (fromNode.Attributes["DisplayName"] != null) 
     fromDisplayName = fromNode.Attributes["DisplayName"].Value; 
    MailAddress fromAddress = new MailAddress(fromNode.InnerText, fromDisplayName); 
    this.From = fromAddress; 

    // To 
    XmlNode toNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/To/Addresses"); 
    foreach (XmlNode node in toNode.ChildNodes) 
    { 
     string toDisplayName = string.Empty; 
     if (node.Attributes["DisplayName"] != null) 
      toDisplayName = node.Attributes["DisplayName"].Value; 
     MailAddress toAddress = new MailAddress(node.InnerText, toDisplayName); 
     this.To.Add(toAddress); 
    } 

    // CC 
    XmlNode ccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/CC/Addresses"); 
    foreach (XmlNode node in ccNode.ChildNodes) 
    { 
     string ccDisplayName = string.Empty; 
     if (node.Attributes["DisplayName"] != null) 
      ccDisplayName = node.Attributes["DisplayName"].Value; 
     MailAddress ccAddress = new MailAddress(node.InnerText, ccDisplayName); 
     this.CC.Add(ccAddress); 
    } 

    // Bcc 
    XmlNode bccNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Bcc/Addresses"); 
    foreach (XmlNode node in bccNode.ChildNodes) 
    { 
     string bccDisplayName = string.Empty; 
     if (node.Attributes["DisplayName"] != null) 
      bccDisplayName = node.Attributes["DisplayName"].Value; 
     MailAddress bccAddress = new MailAddress(node.InnerText, bccDisplayName); 
     this.Bcc.Add(bccAddress); 
    } 

    // Subject 
    XmlNode subjectNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Subject"); 
    this.Subject = subjectNode.InnerText; 

    // Body 
    XmlNode bodyNode = GetConfigSection(xml, "SerializableMailMessage/MailMessage/Body"); 
    this.Body = bodyNode.InnerText; 
} 

code ci-dessus utilise une méthode d'aide pour obtenir un XmlNode pour différentes sections.

public XmlNode GetConfigSection(XmlDocument xml, string nodePath) 
{ 
    return xml.SelectSingleNode(nodePath); 
} 

Ce code est explicite et n'a pas besoin de commentaire mais notez que vous devez mettre à jour les expressions XPath pour vos noms de classe. Bien sûr, je pourrais utiliser la réflexion pour rendre ce code plus général mais parfois je suis un méchant !!

Questions connexes