0

操作契約が次のようなサービスがあります。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());
        }
    }
}

問題:サービス メソッド (実際のサービス) がパラメーター (ユーザー) を NULL として受け取ります。私は何を間違っていますか?サービス契約に既知のタイプを追加しようとしましたが、うまくいきませんでした。

4

1 に答える 1

2

あなたの問題は、ラップされたリクエストを持つように操作を定義することです。つまり、パラメーターは「プレーンな」JSON オブジェクトとして送信されるのではなく、JSON オブジェクトでラップする必要があり、メンバー名はパラメーター名 (この場合はuser) に対応している必要があります。以下のコードはラッピングを行います。これで、パラメーターがサーバーによって適切に受信されるようになったことがわかります。別のオプションは、BodyStyleプロパティを変更するBareことWrappedRequestです (その場合、プレーンオブジェクトをサービス操作に送信する必要があります)。

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());
            }
        }
    }
}
于 2012-09-24T20:58:10.070 に答える