WCF Web 服务在反序列化操作请求消息正文时出错

WCF web service Error in deserializing body of request message for operation

本题来自。除了我删除的 FirstMethodLastMethod 方法外,代码基本相同,因为它们出现问题(我在同一个问题中对其进行评论)。

即便如此,我还是将服务接口复制到这里,仅供参考。如果大家觉得有必要把完整的代码也复制过来,我没问题,我就复制过来。

服务契约接口

[ServiceContract]
public interface IMJRFFrasCdadesService
{
    [OperationContract]
    string Ping();

    [OperationContract]
    Task<string> GoogleLoginAsync(string email);

    [OperationContract]
    Task<string> UploadFileAsync(byte[] fileBytes, string fileName, string email);
}

好的,现在当我连接到服务时它会抛出这个:

            Error: 
Error in deserializing body of request message for operation 'GoogleLogin'. OperationFormatter encountered an invalid Message body. Expected to find node type 'Element' with name 'GoogleLogin' and namespace 'http://tempuri.org/'. Found node type 'Element' with name 'GoogleLoginAsync' and namespace 'http://tempuri.org/' ;

            Trace: 
at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_remoting_wrapper(intptr,intptr)
at (wrapper remoting-invoke) ServiceReference2.IMJRFFrasCdadesService.GoogleLoginAsync(string)
at ServiceReference2.MJRFFrasCdadesServiceClient.GoogleLoginAsync (System.String email) [0x00006] in <e1f3df4dfbf340f09d2768d7fbc33427>:0 
at MJRFFacturasComunidades.Model.WebService.WebServiceClass+<LogEmail>d__6.MoveNext () [0x00023] in <e1f3df4dfbf340f09d2768d7fbc33427>:0  ;

如果我错了,请纠正我,但我知道客户端正在尝试调用一个名为 GoogleLogin 的方法,但该方法被称为 GoogleLoginAsync(正如您在代码),也就是说,它找不到方法。很明显。

但是,VStudio 自动生成带有 WCF Web Service Reference Provider 的客户端代码...我该怎么办?没看懂。

无论如何,我已经尝试查看客户端生成的代码(现在我要重复一遍,我是 WCF 的新手)并看到了这个:

[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName="ServiceReference1.IMJRFFrasCdadesService")]
public interface IMJRFFrasCdadesService
{

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMJRFFrasCdadesService/Ping", ReplyAction="http://tempuri.org/IMJRFFrasCdadesService/PingResponse")]
    System.Threading.Tasks.Task<string> PingAsync();

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMJRFFrasCdadesService/GoogleLogin", ReplyAction="http://tempuri.org/IMJRFFrasCdadesService/GoogleLoginResponse")]
    System.Threading.Tasks.Task<string> GoogleLoginAsync(string email);

    [System.ServiceModel.OperationContractAttribute(Action="http://tempuri.org/IMJRFFrasCdadesService/UploadFile", ReplyAction="http://tempuri.org/IMJRFFrasCdadesService/UploadFileResponse")]
    System.Threading.Tasks.Task<string> UploadFileAsync(byte[] fileBytes, string fileName, string email);
}

我想 OperationContractAttributeAction 参数定义了将在服务中调用什么方法(再次,如果我错了,请纠正我),所以我改变了那个,只是为了测试它,结果是:

            Error: 
The message with Action 'http://tempuri.org/IMJRFFrasCdadesService/GoogleLoginAsync' cannot be processed at the receiver, due to a ContractFilter mismatch at the EndpointDispatcher. This may be because of either a contract mismatch (mismatched Actions between sender and receiver) or a binding/security mismatch between the sender and the receiver.  Check that sender and receiver have the same contract and the same binding (including security requirements, e.g. Message, Transport, None). ;

            Trace: 
at (wrapper managed-to-native) System.Object.__icall_wrapper_mono_remoting_wrapper(intptr,intptr)
at (wrapper remoting-invoke) ServiceReference1.IMJRFFrasCdadesService.GoogleLoginAsync(string)
at ServiceReference1.MJRFFrasCdadesServiceClient.GoogleLoginAsync (System.String email) [0x00006] in <7e18c3beb694450a8a87883f2950def0>:0 
at MJRFFacturasComunidades.Model.WebService.WebServiceClass+<LogEmail>d__6.MoveNext () [0x00023] in <7e18c3beb694450a8a87883f2950def0>:0  ;

所以,不,我错了:(

是的,我只能说这么多,我不知道为什么会这样。老实说,我认为 "reference provider" 会生成对服务方法的调用,因为它在服务接口中,但是,我想我不明白...

反正我现在不知道怎么办。 任何帮助将不胜感激...再次。


编辑:

好的,我无法为我在评论中写的 Xamarin.Forms 问题工作,所以正如@mahlatse 所建议的,这是现在网络服务中的服务合同:

[ServiceContract]
public interface IMJRFFrasCdadesService
{
    [OperationContract]
    string Ping();

    [OperationContract]
    Task<string> GoogleLoginAsync(string email);

    [OperationContract]
    Task<string> UploadFileAsync(byte[] fileBytes, string fileName, string email);
}

并且在 Xamarin.Forms 客户端自动生成的界面,由我修改:

[System.CodeDom.Compiler.GeneratedCodeAttribute("dotnet-svcutil", "1.0.0.1")]
[System.ServiceModel.ServiceContractAttribute(ConfigurationName= "ServiceReference1.IMJRFFrasCdadesService")]
public interface IMJRFFrasCdadesService
{
    [System.ServiceModel.OperationContractAttribute(Action=@"http://tempuri.org/IMJRFFrasCdadesService/Ping", ReplyAction=@"http://tempuri.org/IMJRFFrasCdadesService/PingResponse")]
    System.Threading.Tasks.Task<string> PingAsync();

    [System.ServiceModel.OperationContractAttribute(Action=@"http://tempuri.org/IMJRFFrasCdadesService/GoogleLoginAsync", ReplyAction= @"http://tempuri.org/IMJRFFrasCdadesService/GoogleLoginAsyncResponse")]
    System.Threading.Tasks.Task<string> GoogleLoginAsync(string email);

    [System.ServiceModel.OperationContractAttribute(Action=@"http://tempuri.org/IMJRFFrasCdadesService/UploadFileAsync", ReplyAction= @"http://tempuri.org/IMJRFFrasCdadesService/UploadFileAsyncResponse")]
    System.Threading.Tasks.Task<string> UploadFileAsync(byte[] fileBytes, string fileName, string email);
}

如您所见,我也修改了 ReplyAction 参数,并且添加了 @ 只是为了避免 "escaped characters problems"。但是完全没有变化。

阅读@tgolisch 评论后我修改了 web.config 文件并看到绑定是 https。我修改了客户端,并在创建服务客户端 class 时将绑定设置为 http,因此我更改了:

private IMJRFFrasCdadesService _Service;

public WebServiceClass(string url)
{
    _ServiceUrl = url;
    _Service = new MJRFFrasCdadesServiceClient(
        new BasicHttpsBinding(),
        new EndpointAddress(_ServiceUrl));
}

我还从自动生成的服务客户端 class 更改了此方法,因为它在参数引用 https 时创建了 http 绑定(在第二个 if 它使用的是 System.ServiceModel.BasicHttpBinding 而不是 https 版本):

    private static System.ServiceModel.Channels.Binding GetBindingForEndpoint(EndpointConfiguration endpointConfiguration)
    {
        if ((endpointConfiguration == EndpointConfiguration.BasicHttpBinding_IMJRFFrasCdadesService))
        {
            System.ServiceModel.BasicHttpBinding result = new System.ServiceModel.BasicHttpBinding();
            result.MaxBufferSize = int.MaxValue;
            result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            result.MaxReceivedMessageSize = int.MaxValue;
            result.AllowCookies = true;
            return result;
        }
        if ((endpointConfiguration == EndpointConfiguration.BasicHttpsBinding_IMJRFFrasCdadesService))
        {
/*HERE -->*/ System.ServiceModel.BasicHttpsBinding result = new System.ServiceModel.BasicHttpsBinding();
            result.MaxBufferSize = int.MaxValue;
            result.ReaderQuotas = System.Xml.XmlDictionaryReaderQuotas.Max;
            result.MaxReceivedMessageSize = int.MaxValue;
            result.AllowCookies = true;
            result.Security.Mode = System.ServiceModel.BasicHttpsSecurityMode.Transport;
            return result;
        }
        throw new System.InvalidOperationException(string.Format("No se pudo encontrar un punto de conexión con el nombre \"{0}\".", endpointConfiguration));
    }

毕竟我仍然得到相同的结果。

老实说,我开始问自己让 VStudio 自动生成充满错误的代码有什么意义。

尽管如此,我仍未放弃我在评论中指出的 xamarin 问题。

我放弃了这个。我刚刚制作了一个 ASP.Net 核心网站 api。

对于 WCF Web 服务,我花了一个多星期的时间阅读、学习和使用它:从来没有按预期工作。

通过网络 api 我花了半天的时间阅读和学习(其中大部分是 this video at youtube's visual studio channel。我一直讨厌 MSDN 文章解释事物的方式,但这个视频是real live saver),一天零一个早上让它工作,包括 Xamarin.Forms 客户端,所有这些以前对 HTTP 或 ASP.Net.

知之甚少

现在一切正常。感谢您的帮助:)