1

おはよう/こんばんは

私は WCF を初めて使用し、サンプル アプリケーションを作成しました。問題は、json 文字列をリクエストとして渡しているのに、400:Bad request エラーが発生することです。私のサンプルの詳細は以下のとおりです。

ISampleService.cs:

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;

namespace SampleWCF
{
    [ServiceContract]
    public interface ISampleService
    {
        [OperationContract]
        [WebInvoke(UriTemplate = "/folder_entries/{mFileID_param}/shares?notify=true", Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        string AddShareToFileNotify(string mFileID_param, string rqst_param);
    }
}


#region TestSample
[DataContract]
public class TestSample
{
    public TestSample() { }

    [DataMember(Name = "recipient")]
    public Recipient Recipient { get; set; }

    [DataMember(Name = "role")]
    public String Role { get; set; }

    [DataMember(Name = "access")]
    public TestAccess access{ get; set; }

    [DataMember(Name = "can_share")]
    public bool CanShare { get; set; }

    [DataMember(Name = "days_to_expire")]
    public int DaysToExpire { get; set; }

}

    #region TestAccess 
    [DataContract]
    public class TestAccess 
    {
        #region Attributes

        [DataMember(Name = "role")]
        public String Role { get; set; }

        [DataMember(Name = "rights")]
        public AccessRights AccessRights { get; set; }

        #endregion

        #region Constructor
        public TestAccess () { }
        #endregion
    }
    #endregion

    #region rights
    [DataContract]
    public class AccessRights
    {
        public AccessRights() { }

        [DataMember(Name = "testinternal")]
        public Boolean Internal { get; set; }

        [DataMember(Name = "testexternal")]
        public Boolean External { get; set; }

        [DataMember(Name = "public")]
        public Boolean Public { get; set; }

        [DataMember(Name = "max_role")]
        public String Max_Role { get; set; }

        [DataMember(Name = "grant")]
        public Boolean Grant { get; set; }

    }
    #endregion

    #region Recipient
    [DataContract]
    public class Recipient
    {
        public Recipient() { }

        [DataMember(Name = "id")]
        public string ID { get; set; }

        [DataMember(Name = "type")]
        public string Type { get; set; }

    }
    #endregion
#endregion

SampleService.svc.cs

    using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.Text;
using System.ServiceModel.Web;
using System.ServiceModel.Security;
using System.Net;
using System.IO;
using System.Threading;
using System.Security.Cryptography.X509Certificates;
using System.Net.Security;

namespace SampleWCF
{
    public class SampleService : ISampleService
    {
        private ISampleService client = null;
        private WebChannelFactory<ISampleService> cf = null;
        private Uri uri = null;
        private WebHttpSecurityMode mode = WebHttpSecurityMode.Transport;
        public const string CERTIFICATE_TRUST_STORE_NAME = "Trust";

        //Method to Validate if the server certificate is valid or not
        private static bool ValidateServerCertificate(object sender,
                                                      X509Certificate certificate,
                                                      X509Chain chain,
                                                      SslPolicyErrors sslPolicyErrors)
        {
            bool result = false;
            X509Store store = null;

            try
            {
                // If the certificate is valid signed certificate, return true.
                if (SslPolicyErrors.None == sslPolicyErrors)
                {
                    return true;
                }

                // If there are errors in the certificate chain, look in the certificate store to check
                // if the user has already trusted the certificate or not.
                if ((0 != (sslPolicyErrors & SslPolicyErrors.RemoteCertificateChainErrors)) ||
                    (0 != (sslPolicyErrors & SslPolicyErrors.RemoteCertificateNameMismatch)))
                {
                    store = new X509Store(CERTIFICATE_TRUST_STORE_NAME, StoreLocation.CurrentUser);
                    store.Open(OpenFlags.ReadOnly);
                    result = store.Certificates.Contains(certificate);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Could not validate certificate!");
                result = false;
            }
            finally
            {
                if (store != null)
                    store.Close();
            }

            return result;
        }


        public ISampleService initClient(string servername,
                                         string protocol,
                                         string username,
                                         string password)
        {
            uri = new Uri(protocol + "://" + servername + ":" + @"/rest");
            WebHttpBinding binding = new WebHttpBinding();
            binding.ReaderQuotas.MaxStringContentLength = int.MaxValue;
            binding.MaxReceivedMessageSize = int.MaxValue;
            binding.ReceiveTimeout = TimeSpan.FromMinutes(10.0);
            binding.SendTimeout = TimeSpan.FromMinutes(10.0);
            System.Net.ServicePointManager.DefaultConnectionLimit = 200;

            binding.Security.Mode = mode;
            binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.Basic;

            cf = new WebChannelFactory<ISampleService>(binding, uri);
            cf.Credentials.UserName.UserName = username;
            cf.Credentials.UserName.Password = password;

            client = cf.CreateChannel();

            System.Net.ServicePointManager.ServerCertificateValidationCallback = ValidateServerCertificate;
            System.Net.ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;

            Thread.Sleep(500);
            return client;
        }

        public string AddShareToFileNotify(string mFileID_param, string rqst_param)
        {
            using (new OperationContextScope((IContextChannel)client))
            {
                string rsp = null;
                try
                {
                    rsp = client.AddShareToFileNotify(mFileID_param, rqst_param);
                }
                catch (Exception ce)
                {
                    Console.WriteLine("Exception found!{0}",ce);
                    return rsp;
                }
                return rsp;
            }
        }
    }
}

主な呼び出し機能:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace TriggerMain
{
    class Program
    {
        static void Main(string[] args)
        {

            string mFileID = "xxxxxx";
            string rqst = "{"
    +"\"access\":{"
        +"\"role\":\"VIEWER\","
        +"\"sharing\":{"
            +"\"external\":false,"
            +"\"grant\":false,"
            +"\"internal\":false,"
            +"\"max_role\":null,"
            +"\"public\":false"

        +"}"
    +"},"
    +"\"can_share\": false,"
    +"\"days_to_expire\": 30,"
    +"\"recipient\": {"
        +"\"id\": <yyyyyy>,"
        +"\"type\": \"user\""
            +"},"
    +"\"role\": \"VIEWER\""
+"}";
            string rsp = null;

            SampleWCF.SampleService sample = new SampleWCF.SampleService();
            sample.initClient("<URL1.xxx.com>", "https", "<Username>", "<Password>");
            rsp = sample.AddShareToFileNotify(mFileID, rqst);
            Console.ReadLine();
        }
    }
}

アプリケーションの実行中に、次のエラーが発生します。

Exception found!System.ServiceModel.ProtocolException: The remote server returned an unexpected response: (400) Bad Request. ---> System.Net.WebException: The remote server returned an error: (400) Bad Request.
   at System.Net.HttpWebRequest.GetResponse()
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   --- End of inner exception stack trace ---

Server stack trace:
   at System.ServiceModel.Channels.HttpChannelUtilities.ValidateRequestReplyResponse(HttpWebRequest request, HttpWebResponse response, HttpChannelFactory`1 factory, WebException responseException, ChannelBinding channelBinding)
   at System.ServiceModel.Channels.HttpChannelFactory`1.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
   at System.ServiceModel.Channels.RequestChannel.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Dispatcher.RequestChannelBinder.Request(Message message, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannel.Call(String action, Boolean oneway, ProxyOperationRuntime operation, Object[] ins, Object[] outs, TimeSpan timeout)
   at System.ServiceModel.Channels.ServiceChannelProxy.InvokeService(IMethodCallMessage methodCall, ProxyOperationRuntime operation)
   at System.ServiceModel.Channels.ServiceChannelProxy.Invoke(IMessage message)

Exception rethrown at [0]:
   at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
   at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
   at SampleWCF.ISampleService.AddShareToFileNotify(String mFileID_param, String rqst_param)
   at SampleWCF.SampleService.AddShareToFileNotify(String mFileID_param, String rqst_param) in c:\Users\SBasu\Documents\Visual Studio 2013\Projects\SampleWCF\SampleWCF\SampleService.svc.cs:line 103

私が試したこと:送信と受信のタイムアウトを変更しました。コンテンツタイプはapplication / jsonです。リクエストは、このサーバーに対してのみエラーをスローしています。私が試した別のサーバーがあり、POST がサーバーを通過しています。両方のサーバーの構成は同じです。エラーのあるサーバーに対して Fiddler を実行すると、POST 呼び出しが成功します。POSTMAN からエラーのあるサーバーにまったく同じ要求を送信すると、成功 (200 OK) ステータスが返され、これらの両方のケースで適切な応答が得られます。

注: WEBGET、WEBInvoke DELETE は、サーバーに対して正常に機能しています。特定のサーバーでWEBInvoke POSTのみが機能していません。誰でもこれに関して私を助けることができますか? 前もって感謝します。

4

2 に答える 2