C# 从WCF到WCF。远程服务器返回意外响应:(400)请求错误

C# 从WCF到WCF。远程服务器返回意外响应:(400)请求错误,c#,wcf,C#,Wcf,我们有两个WCF服务,第一个是api web方法。在这样创建的界面中: [OperationContract] [WebInvoke( Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.WrappedRequest )] RequestParams

我们有两个WCF服务,第一个是api web方法。在这样创建的界面中:

[OperationContract]
[WebInvoke(
   Method = "POST",
   RequestFormat = WebMessageFormat.Json,
   ResponseFormat = WebMessageFormat.Json,
   BodyStyle = WebMessageBodyStyle.WrappedRequest
)]
RequestParams GetAccount(RequestParams requestParams);
我想从第二个WCF服务调用此方法。像这样:

try
{
   var myBinding = new WebHttpBinding();
   var myEndpoint = new EndpointAddress(endpointAddress);

   using (var factory = new ChannelFactory<IAccount>(myBinding, myEndpoint))
   {
       IAccount apiService = null;

       try
       {
           factory.Endpoint.Behaviors.Add(new WebHttpBehavior());
           apiService = factory.CreateChannel();

           result = apiService.GetAccount(requestParams);

           ((ICommunicationObject)apiService).Close();
           factory.Close();
        }
        catch (Exception ex)
        {
           Fatal(ex);
           (apiService as ICommunicationObject)?.Abort();
        }
    }
}
试试看
{
var myBinding=新的WebHttpBinding();
var myEndpoint=新的端点地址(EndpointAddress);
使用(var factory=newchannelfactory(myBinding,myEndpoint))
{
IAccount apiService=null;
尝试
{
添加(新的WebHttpBehavior());
apiService=factory.CreateChannel();
结果=apiService.GetAccount(requestParams);
((ICommunicationObject)apiService.Close();
工厂关闭();
}
捕获(例外情况除外)
{
致命(ex);
(apiService作为ICommunicationObject)?.Abort();
}
}
}
当我用use Postman检查GetAccount方法时,它工作并返回期望值。但当我尝试从第二个服务调用时,并没有调用该方法(在调试模式下检查),并且在异常中捕获-(400)错误请求。
我认为这个错误与返回值的json格式有关。当我尝试在接口中更改为xml时,将调用该方法(使用调试模式进行检查)。如何配置WebHttpBehavior以使用json?谢谢

这实际上是由WebMessageBodyStyle.WrappedResponse引起的。如果将WebMessageBodyStyle更改为Wrapped,WCF将再次封装该对象。下面是一个演示:

 [OperationContract]
        [WebInvoke(
        Method = "POST",
        ResponseFormat = WebMessageFormat.Json, RequestFormat =
        WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.WrappedResponse
 )]
        string GetAccount(UserData requestParams);
[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(
        Method = "POST",
        ResponseFormat = WebMessageFormat.Json, RequestFormat =
        WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare
 )]
        string GetAccount(UserData requestParams);
    }
    [DataContract(Name = "user")]
    public class UserData
    {
        [DataMember(Name = "Name")]
        public string Name { get; set; }
        [DataMember(Name = "Password")]
        public string Password { get; set; }
        [DataMember(Name = "Email")]
        public string Email { get; set; }
    }
    public class Service1 : IService1
    {
        public string GetAccount(UserData requestParams)
        {
            return "OK";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost selfHost = new ServiceHost(typeof(Service1));
            selfHost.Open();
            Console.WriteLine("Service Open");
            Console.ReadKey();
            selfHost.Close();
        }
    }
WrappedResponse将封装响应

因为您的WebMessageBodyStyle是WrappedRequest,所以必须封装您在客户端发送的对象,否则将出现400个错误请求

我认为最好的解决方案是将WebMessageBodyStyle设置为Bare,下面是一个演示:

 [OperationContract]
        [WebInvoke(
        Method = "POST",
        ResponseFormat = WebMessageFormat.Json, RequestFormat =
        WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.WrappedResponse
 )]
        string GetAccount(UserData requestParams);
[ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebInvoke(
        Method = "POST",
        ResponseFormat = WebMessageFormat.Json, RequestFormat =
        WebMessageFormat.Json,
        BodyStyle = WebMessageBodyStyle.Bare
 )]
        string GetAccount(UserData requestParams);
    }
    [DataContract(Name = "user")]
    public class UserData
    {
        [DataMember(Name = "Name")]
        public string Name { get; set; }
        [DataMember(Name = "Password")]
        public string Password { get; set; }
        [DataMember(Name = "Email")]
        public string Email { get; set; }
    }
    public class Service1 : IService1
    {
        public string GetAccount(UserData requestParams)
        {
            return "OK";
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            ServiceHost selfHost = new ServiceHost(typeof(Service1));
            selfHost.Open();
            Console.WriteLine("Service Open");
            Console.ReadKey();
            selfHost.Close();
        }
    }
这是Program.cs

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup>
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.7.2" />
    </startup>

    <system.serviceModel>
        <services>

            <service name="ConsoleApp113.Service1" behaviorConfiguration="ServiceBehavior">
                <host>
                    <baseAddresses>
                        <add baseAddress="http://localhost:8012/ServiceModelSamples/service"/>
                    </baseAddresses>
                </host>

                <endpoint address=""
                          binding="webHttpBinding"
                          contract="ConsoleApp113.IService1"
                          behaviorConfiguration="ESEndPointBehavior" />
            </service>
        </services>


        <behaviors>
            <endpointBehaviors>
                <behavior name="ESEndPointBehavior">
                    <webHttp helpEnabled="true"/>
                </behavior>
            </endpointBehaviors>

            <serviceBehaviors>
                <behavior name="ServiceBehavior">
                    <serviceMetadata/>
                </behavior>
            </serviceBehaviors>

        </behaviors>

    </system.serviceModel>
</configuration>
您可以将RequestParams封装到GetAccount中,然后将GetAccount直接发送到服务器。因此,为了成功调用WCF服务,您必须修改服务接口:

[OperationContract]
[WebInvoke(
   Method = "POST",
   RequestFormat = WebMessageFormat.Json,
   ResponseFormat = WebMessageFormat.Json,
   BodyStyle = WebMessageBodyStyle.WrappedRequest
)]
RequestParams GetAccount(GetAccount requestParams);

谢谢您的回答。不幸的是,我无法更改BodyStyle,另一个前端应用程序正在使用此端点,也许我可以设置webHttpBinding以使用json和wrappedRequest?我更新我的回复。嗨,问题解决了吗?如果你认为我的回答对你有帮助,你可以把它标记为回答。这很有帮助。谢谢!:)