Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Simple WCF service, not all parameters from client making through to the service

Tags:

c#

wcf

I wasn't exactly sure how to ask this so I made an SSCCE

I have this simple WCF service

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

and I'm trying to get a Winforms client to call the webservice method; this is what I have

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

EmailData emailData = new EmailData
                          {
                              EmailAddress = "[email protected]",
                              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);
}

now on the service side, some of the properties are null as shown by the following screenshot. enter image description here

Why is it that the FileName has the right value but the others don't ?

like image 613
Professor Chaos Avatar asked Oct 22 '22 20:10

Professor Chaos


1 Answers

The order of the XML elements is important when deserialization. By default, the order is alphabetical, so you should send first the EmailAddress, then Enc64FileContents, then FileName. Or an alternative is to set the Order property in the [DataMember] attribute, as in this really SSCCE code below :)

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 = "[email protected]",
            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);
        }
    }
}
like image 177
carlosfigueira Avatar answered Oct 24 '22 11:10

carlosfigueira