Веб-служба WCF Ошибка в десериализации тела сообщения запроса для работы - PullRequest
0 голосов
/ 19 апреля 2019

Этот вопрос возник из этого другого вопроса . Код в основном такой же, за исключением методов FirstMethod и LastMethod, которые я удалил, потому что они вызывали проблемы (я комментирую это в том же вопросе).

Несмотря на это, я скопирую здесь интерфейс службы только для ссылок. Если некоторые из вас сочтут необходимым скопировать полный код и здесь, у меня нет проблем, я скопирую его сюда.

Интерфейс контракта на обслуживание

[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);
}

Полагаю, Action параметр OperationContractAttribute определяет, какой метод будет вызываться в службе (опять же, исправьте меня, если я ошибаюсь, пожалуйста), поэтому я изменил его, просто чтобы проверить, с таким результатом:

            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  ;

Итак, нет, я ошибался: (

И да, это все, что я могу сказать, я понятия не имею, почему это происходит. Честно говоря, я думал, что «поставщик ссылок» будет генерировать вызов к методу сервиса, как это происходит в интерфейсе сервиса, но, полагаю, я этого не понял ...

Во всяком случае, я не знаю, что теперь делать. Любая помощь будет принята с благодарностью ... еще раз.


Edit:

Ладно, я не могу получить рабочие решения для проблемы 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 и добавил символ @, чтобы избежать "проблем с символами экранирования". Но без изменений.

После прочтения комментария @tgolisch я изменил файл web.config и увидел, что привязка была https. Я пересмотрел клиента и установил привязку как http при создании класса клиента службы, поэтому я изменил это:

private IMJRFFrasCdadesService _Service;

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

Я также изменил этот метод с автоматически сгенерированного класса клиента службы, потому что он создавал привязку http, когда параметр ссылался на https (во втором 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 автоматически генерировал код, полный ошибок.

Несмотря на все это, я не отказываюсь от проблемы с ксамарином, которую я указал на комментарии.

1 Ответ

0 голосов
/ 22 апреля 2019

Я отказался от этого.Я только что сделал ASP.Net ядро ​​веб-API.

С веб-сервисом WCF я потратил больше недели между чтением, обучением и борьбой с ним: никогда не работай, как задумано.

С веб-интерфейсом я потратил полдня на чтение и обучение (и большей частью это было это видео на канале визуальной студии youtube . Я всегда ненавидел статьи MSDN как способ объяснения вещей, но это видео было настоящей живой заставкой), и один день и утро заставляли его работатьвключая Xamarin.Forms клиента, все с очень небольшими знаниями о HTTP или ASP.Net.

Теперь все работает отлично.Спасибо за попытку помочь :)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...