WebInvoke参数为NULL

时间:2012-09-17 02:23:04

标签: json wcf rest webinvoke

我有一项服务,其中操作合同如下所示。我有一个WebInvoke属性,该方法设置为POST。我有一个UriTemplate。实际的服务方法名称是SaveUser。我试图传入一个User对象(一个带有注释为数据成员属性的属性的数据协定)。

[OperationContract]
[WebInvoke(Method = "POST", UriTemplate = "SaveUser", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
User SaveUser(User user);

客户端如下所示。为简单起见,我已经排除了令牌和授权等。:

using (WebClient webClient = new WebClient())
{
    try
    {
        Random r = new Random();
        var partitionKey = Guid.NewGuid().ToString();
        var rowKey = r.Next(999900, 999999).ToString();

        User u = new User()
        {
            UserId = partitionKey,
            FirstName = "First-" + DateTime.Now.Ticks.ToString(),
            LastName = "Last-" + DateTime.Now.Ticks.ToString(),
            LoginName = rowKey,
            Password = "password1",
            PayPalEmailAddress = "First" + DateTime.Now.Ticks.ToString() + "@verascend.com",
            PhoneNumber = "+1206" + r.Next(1234567, 9999999).ToString()
        };

        string url = serviceBaseUrl + "/SaveUser";

        webClient.Headers["Content-type"] = "application/json; charset=utf-8";
        // webClient.Headers[HttpRequestHeader.Authorization] = authToken;

        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(User));

        using (var memStream = new MemoryStream())
        {
            ser.WriteObject(memStream, u);

            Debug.WriteLine("-------------> "+ByteArrayToString(memStream.ToArray()));

            webClient.UploadData(url, "POST", memStream.ToArray());

        }
    }
    catch (WebException ex)
    {
        if (ex.Status == WebExceptionStatus.ProtocolError)
        {
            string responseText = string.Empty;

            using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream())
            {
                using (StreamReader streamReader = new StreamReader(responseStream))
                {
                    responseText = streamReader.ReadToEnd();
                }
            }

            throw new Exception(responseText);
        }
        else
        {
            throw new Exception(ex.Message.ToString());
        }
    }
}

问题:服务方法(实际服务)正在接收param(User)为NULL。我究竟做错了什么?我尝试在服务合同中添加已知类型,但没有运气。

1 个答案:

答案 0 :(得分:2)

您的问题是您将操作定义为包装请求。这意味着该参数不是作为“普通”JSON对象发送,而是必须包装在JSON对象中,并且成员名称必须对应于参数名称(在您的情况下为user)。下面的代码包装;你可以看到,现在服务器正确接收了参数。另一种选择是将BodyStyle属性更改为Bare而不是WrappedRequest(在这种情况下,您需要将 plain 对象发送到服务运营)。

public class StackOverflow_12452466
{
    [ServiceContract]
    public interface ITest
    {
        [OperationContract]
        [WebInvoke(Method = "POST", UriTemplate = "SaveUser", BodyStyle = WebMessageBodyStyle.WrappedRequest, RequestFormat = WebMessageFormat.Json)]
        User SaveUser(User user);
    }

    public class Service : ITest
    {
        public User SaveUser(User user)
        {
            Console.WriteLine("User: {0}", user);
            return user;
        }
    }

    public class User
    {
        public string UserId { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string LoginName { get; set; }
        public string Password { get; set; }
        public string PayPalEmailAddress { get; set; }
        public string PhoneNumber { get; set; }

        public override string ToString()
        {
            return string.Format("Id={0},First={1},Last={2},Login={3},Pwd={4},PayPal={5},Phone={6}",
                UserId, FirstName, LastName, LoginName, Password, PayPalEmailAddress, PhoneNumber);
        }
    }

    public static void Test()
    {
        string serviceBaseUrl = "http://" + Environment.MachineName + ":8000/Service";
        ServiceHost host = new ServiceHost(typeof(Service), new Uri(serviceBaseUrl));
        host.AddServiceEndpoint(typeof(ITest), new WebHttpBinding(), "").Behaviors.Add(new WebHttpBehavior());
        host.Open();

        Random r = new Random();
        User u = new User()
        {
            UserId = "partitionKey",
            FirstName = "First-" + DateTime.Now.Ticks.ToString(),
            LastName = "Last-" + DateTime.Now.Ticks.ToString(),
            LoginName = "rowKey",
            Password = "password1",
            PayPalEmailAddress = "First" + DateTime.Now.Ticks.ToString() + "@verascend.com",
            PhoneNumber = "+1206" + r.Next(1234567, 9999999).ToString()
        };

        string url = serviceBaseUrl + "/SaveUser";

        WebClient webClient = new WebClient();
        webClient.Headers["Content-type"] = "application/json; charset=utf-8";

        Func<byte[], string> ByteArrayToString = (b) => Encoding.UTF8.GetString(b);
        DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(User));

        try
        {
            using (var memStream = new MemoryStream())
            {
                byte[] wrappingStart = Encoding.UTF8.GetBytes("{\"user\":");
                memStream.Write(wrappingStart, 0, wrappingStart.Length);
                ser.WriteObject(memStream, u);
                byte[] wrappingEnd = Encoding.UTF8.GetBytes("}");
                memStream.Write(wrappingEnd, 0, wrappingEnd.Length);

                Debug.WriteLine("-------------> " + ByteArrayToString(memStream.ToArray()));

                webClient.UploadData(url, "POST", memStream.ToArray());
            }
        }
        catch (WebException ex)
        {
            if (ex.Status == WebExceptionStatus.ProtocolError)
            {
                string responseText = string.Empty;

                using (Stream responseStream = ((HttpWebResponse)ex.Response).GetResponseStream())
                {
                    using (StreamReader streamReader = new StreamReader(responseStream))
                    {
                        responseText = streamReader.ReadToEnd();
                    }
                }

                throw new Exception(responseText);
            }
            else
            {
                throw new Exception(ex.Message.ToString());
            }
        }
    }
}