WCF Webinvoke POST 给出(400)特定服务器的错误请求
Posted
技术标签:
【中文标题】WCF Webinvoke POST 给出(400)特定服务器的错误请求【英文标题】:WCF Webinvoke POST giving (400) Bad Request for specific server 【发布时间】:2020-07-04 17:13:27 【问题描述】:早安/晚安,
我是 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 不适用于特定服务器。有人可以帮我解决这个问题吗?提前致谢。
【问题讨论】:
【参考方案1】:这部分有效负载在我看来不正确。我更改了 1 行,见下文。
唯一的补充是在recipient.id
值周围添加引号
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>\"," // this line I think was wrong. added quotes around the value
+"\"type\": \"user\""
+","
+"\"role\": \"VIEWER\""
+"";
【讨论】:
我已经添加了报价并运行了程序,但到目前为止还没有运气。 :(【参考方案2】:为什么要使用代理(通道工厂)调用 WCF Restful 服务?如果确实如此,我们应该使用服务基地址而不是POST URL
。此外,服务合同应与服务器相同。
uri = new Uri(protocol + "://" + servername + ":" + @"/rest") // where is the service port number? also, is the format right?
此代码 sn-p 应使用服务基地址通过代理发送请求。
实际上,我们通常在调用Webhttpbinding
创建的WCF服务的同时通过POSTMan/fiddler发送请求。此外,我们应该使用由 URITemplate 属性修饰的 Uri。
如果问题仍然存在,请随时告诉我。
【讨论】:
uri 的格式似乎是正确的,因为在调试应用程序时,我得到了正确的绝对 uri。我认为需要对 json 请求进行反序列化。我将尝试同样的方法并发布我的发现。谢谢。 是的,400 bad request 通常与参数的格式有关,而大多数情况下,反序列化过程由 WCF 框架完成。我没有看到你在函数的签名中添加了强类型参数。 我已经反序列化了我的请求,但仍然无法找到突破口。 :(以上是关于WCF Webinvoke POST 给出(400)特定服务器的错误请求的主要内容,如果未能解决你的问题,请参考以下文章
预检的 Wcf webHttpBinding 响应具有无效的 HTTP 状态代码 400