Как мне сериализовать почтовое сообщение? - PullRequest
11 голосов
/ 14 июля 2009

Я получаю следующее при попытке сериализации сообщения mial с помощью los foratter.

Ошибка: Sys.WebForms.PageRequestManagerServerErrorException: Ошибка сериализации значения 'System.Net.Mail.MailMessage' типа 'System.Net.Mail.MailMessage.'

Есть ли ЛЕГКИЙ способ сериализации этого объекта, или мне придется искать каждый из свойств по отдельности?

Ответы [ 3 ]

4 голосов
/ 01 марта 2015

Для тех, кто ищет полный исходный код на , как сериализовать MailMessage в XML, написанный Кейваном Найери, вот ссылка на его github:

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

А вот архив его блога, который сейчас не существует:

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

На случай, если приведенная выше ссылка тоже может стать мертвой, здесь я повторно отправлю его блог здесь:

Как сериализовать почтовое сообщение

В .NET есть два класса MailMessage. Первый находится в пространстве имен System.Web.Mail и устарел в .NET 2.0 и более поздних, а второй доступен в System.Net.Mail. Меня не волнует устаревший, поэтому я просто покажу, как можно сериализовать экземпляры класса System.Net.Mail.MailMessage.

Чтобы сериализовать свойства объекта MailMessage, вы можете создать новый класс и создать для него свойство типа MailMessage, которое встраивает ваше MailMessage в класс. В этом новом классе вы можете реализовать интерфейс IXmlSerializable, чтобы вручную сериализовать его MailMessage.

Сериализация

Сериализация стороны работы так же проста, как реализация метода WriteXml. Ниже приведен код, который я написал для этого.

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();
    }
}

Следуя тому же подходу, вы можете сериализовать другие свойства, такие как вложения. На следующей неделе я выпущу новую версию Gopi, которая содержит обновленный код, который сериализует все, так что вы можете подождать, чтобы получить код.

Десериализация

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;
}

Приведенный выше код использует вспомогательный метод для получения XmlNode для разных разделов.

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

Этот код не требует пояснений и не требует комментариев, но имейте в виду, что вам нужно обновить выражения XPath для имен ваших классов. Конечно, я мог бы использовать рефлексию, чтобы сделать этот код более общим, но иногда я плохой парень !!

3 голосов
/ 21 августа 2014

Я знаю, что это старый пост, но у меня также была проблема, когда мне нужно было сериализовать класс MailAddress, поэтому я создал сериализуемую версию. Если вы можете использовать собственный класс MailAddress вместо класса System.Net.Mail.MailAddress, это может сработать для вас.

/// <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)))
    {
    }
}
1 голос
/ 14 июля 2009

К сожалению, класс System.Net.Mail.MailMessage не помечен как сериализуемый. Так что да, вам нужно сделать это самостоятельно. В следующем посте блога описана методика, которая может дать вам представление о том, как вы могли бы действовать: Как сериализовать MailMessage ... в основном вам нужно будет извлекать каждое из свойств по отдельности. Цитата:

Для сериализации свойств объекта MailMessage вы можете создать новый класс и создайте для него свойство типа MailMessage, которое встраивает Ваше MailMessage в классе. В этом новом классе вы можете реализовать Интерфейс IXmlSerializable для ручной сериализации своего MailMessage. Вот Я создаю этот класс и называю его SerializableMailMessage [...]

[реализация кода методов WriteXml () и ReadXml () приведена ниже; см. ссылку на источник]

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...