おはよう/こんばんは
私は 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のみが機能していません。誰でもこれに関して私を助けることができますか? 前もって感謝します。