WebInvoke参数为NULL [英] WebInvoke Parameter is NULL

查看:160
本文介绍了WebInvoke参数为NULL的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一项服务,其运营合同如下所示.我有一个WebInvoke属性,并且该方法设置为POST.我确实有一个UriTemplate.实际的服务方法名称是SaveUser.我试图传递一个User对象(一个数据合同,其属性被标注为数据成员属性).

I have a service where the operation contract looks like the following. I have a WebInvoke attribute and the method is set to POST. I do have a UriTemplate. The actual service method name is SaveUser. I am trying to pass in a User object (a data contract with properties annotated as data member attributes).

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

客户端如下所示.为了简单起见,我不包括令牌和授权等.

The client looks like the following. For simplicity I have excluded the token and authorization etc.:

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

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

Problem: The service method (actual service) is receiving the param (User) as NULL. What am I doing wrong? I tried adding the known type in the service contract but no luck.

推荐答案

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

Your problem is that you define your operation to have a wrapped request. That means that the parameter, instead of being sent as a "plain" JSON object, must be wrapped in a JSON object, and the member name must correspond to the parameter name (in your case, user). The code below does the wrapping; you can see that with that the parameter now is properly received by the server. Another option would be to change the BodyStyle property to Bare instead of WrappedRequest as you have (in which case you'd need to send the plain object to the service operation).

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

这篇关于WebInvoke参数为NULL的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆