5

我不完全确定如何问这个,所以我做了一个SSCCE

我有这个简单的 WCF 服务

[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
public class EmailService
{
    [WebInvoke(UriTemplate = "/SendEmail", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Xml)]
    public bool SendEmail(EmailData data)
    {
        try
        {
            byte[] fileBinaryContents = Convert.FromBase64String(data.Enc64FileContents);
            File.WriteAllBytes(data.FileName, fileBinaryContents);
            return true;
        }
        catch (Exception)
        {
            return false;
        }
    }
}

[DataContract(Namespace = "http://somenamespace/")]
public class EmailData
{
    [DataMember]
    public string FileName { get; set; }

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

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

我正在尝试让 Winforms 客户端调用 webservice 方法;这就是我所拥有的

string URI = " http://localhost:59961/EmailService/SendEmail";
string fileContents = Convert.ToBase64String(File.ReadAllBytes("test.txt"));

EmailData emailData = new EmailData
                          {
                              EmailAddress = "foo@bar.com",
                              Enc64FileContents = fileContents,
                              FileName = "test.txt"
                          };

XNamespace ns = "http://somenamespace/";
XElement emailDataElement = new XElement(ns + "EmailData");
emailDataElement.Add(new XElement(ns + "FileName", emailData.FileName));

emailDataElement.Add(new XElement(ns + "Enc64FileContents", emailData.Enc64FileContents));
emailDataElement.Add(new XElement(ns + "EmailAddress", emailData.EmailAddress));

var xml = emailDataElement.ToString(SaveOptions.DisableFormatting);

using (WebClient wc = new WebClient())
{
    wc.Headers[HttpRequestHeader.ContentType] = "application/xml; charset=utf-8";
    string response = wc.UploadString(URI, "POST", xml);
}

现在在服务端,一些属性为空,如下面的屏幕截图所示。 在此处输入图像描述

为什么它FileName具有正确的价值而其他人没有?

4

1 回答 1

3

反序列化时,XML 元素的顺序很重要。默认情况下,顺序是按字母顺序排列的,因此您应该先发送EmailAddress,然后Enc64FileContents,然后FileName。或者另一种方法是在Order属性中设置[DataMember]属性,如下面的这个真正的SSCCE 代码:)

public class StackOverflow_14281800
{
    [ServiceContract]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class EmailService
    {
        [WebInvoke(UriTemplate = "/SendEmail", Method = "POST", ResponseFormat = WebMessageFormat.Json, RequestFormat = WebMessageFormat.Xml)]
        public bool SendEmail(EmailData data)
        {
            try
            {
                Console.WriteLine("data.FileName = " + data.FileName);
                Console.WriteLine("data.EmailAddress = " + data.EmailAddress);
                Console.WriteLine("data.FileContents = " + new string(Convert.FromBase64String(data.Enc64FileContents).Select(b => (char)b).ToArray()));
                //byte[] fileBinaryContents = Convert.FromBase64String(data.Enc64FileContents);
                //File.WriteAllBytes(data.FileName, fileBinaryContents);
                return true;
            }
            catch (Exception)
            {
                return false;
            }
        }
    }

    [DataContract(Name = "EmailData", Namespace = "http://somenamespace/")]
    public class EmailData
    {
        [DataMember(Order = 1)]
        public string FileName { get; set; }

        [DataMember(Order = 2)]
        public string EmailAddress { get; set; }

        [DataMember(Order = 3)]
        public string Enc64FileContents { get; set; }
    }

    public static void Test()
    {
        string baseURI = "http://localhost:59961/EmailService";

        var host = new WebServiceHost(typeof(EmailService), new Uri(baseURI));
        host.Open();
        Console.WriteLine("Host opened");

        string URI = baseURI + "/SendEmail";

        //string fileContents = Convert.ToBase64String(File.ReadAllBytes("test.txt"));
        string fileContents = Convert.ToBase64String("hello world".Select(c => (byte)c).ToArray());

        EmailData emailData = new EmailData
        {
            EmailAddress = "foo@bar.com",
            Enc64FileContents = fileContents,
            FileName = "test.txt"
        };

        XNamespace ns = "http://somenamespace/";
        XElement emailDataElement = new XElement(ns + "EmailData");

        emailDataElement.Add(new XElement(ns + "FileName", emailData.FileName));
        emailDataElement.Add(new XElement(ns + "EmailAddress", emailData.EmailAddress));
        emailDataElement.Add(new XElement(ns + "Enc64FileContents", emailData.Enc64FileContents));

        var xml = emailDataElement.ToString(SaveOptions.DisableFormatting);

        using (WebClient wc = new WebClient())
        {
            wc.Headers[HttpRequestHeader.ContentType] = "application/xml; charset=utf-8";
            string response = wc.UploadString(URI, "POST", xml);
            Console.WriteLine(response);
        }
    }
}
于 2013-01-11T18:24:25.513 回答