早上好/晚上好,
我是 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
示例服务.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不适用于特定服务器。有人可以帮我解决这个问题吗?提前致谢。