Как использовать WcfCoreMtomEncoder в проекте .Net Core?

Я хочу использовать эту библиотеку WcfCoreMtomEncoder здесь в моем проекте .Net Core, но я не знаю, как ее использовать это синтаксически.

У меня есть этот код ниже, но я не могу использовать MessageEncoding, потому что я нахожусь в проекте .Net Core (без поддержки mtom):

var binding = new BasicHttpBinding(BasicHttpSecurityMode.Transport)
{ 
    // MessageEncoding = WSMessageEncoding.Mtom, not supported in .Net Core
    TransferMode = TransferMode.Streamed
};

EndpointAddress endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(binding, endpoint);
var webService = channelFactory.CreateChannel();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var documentAddResult = webService.DocumentAdd(document);
channelFactory.Close();

Из того, что я прочитал, я могу заменить его этим кодом library ниже, и я вижу из документации для кодировщика lib что использование выглядит следующим образом:

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);

var client = new MtomEnabledServiceClient(customBinding);

но я не уверен, что здесь что? Как он будет использоваться для загрузки документа, которого я пытаюсь достичь? И делает ли это библиотека, или я неправильно понимаю, что она делает?

Если кто-нибудь может предоставить мне пример того, как использовать эту библиотеку для загрузки документов, я был бы признателен.


person user1186050    schedule 06.01.2020    source источник
comment
Со своей стороны пробовал, не получилось, всегда вылетала одна и та же ошибка.   -  person Abraham Qian    schedule 07.01.2020
comment
Привет. Что именно ты пробовал? Может быть, вы можете показать фрагмент вашего кода и ошибку?   -  person user1186050    schedule 07.01.2020
comment
Я создал службу WCF с базовой привязкой http с помощью кодировщика Mtom. Затем я вызываю службу, настроив пользовательскую привязку с помощью кодировщика Mtom. Я также попытался создать службу WCF с данной привязкой и использовать ее. Кроме того, Channel Factory с такой привязкой тоже не работал. Я не знаю, для чего используется библиотека классов. проблемы GitHub также еще не решены.   -  person Abraham Qian    schedule 08.01.2020
comment
(Тип контента multipart/related; type=application/xop+xml; start=‹tempuri.org/0. ›; border=uuid:b84ef9c6-0def-4900-a3cb-27d13b846c62+id=5; start-info=text/xml ответного сообщения не соответствует типу содержимого привязки (text/xml; charset=utf-8 ). Если вы используете пользовательский кодировщик, убедитесь, что метод IsContentTypeSupported реализован правильно. Первые 435 байтов ответа были следующими:   -  person Abraham Qian    schedule 08.01.2020


Ответы (4)


После некоторых усилий мне удалось создать службу WCF, которую могла использовать библиотека классов. Но он поддерживает только Custombinding. См. приведенный ниже пример.
На стороне сервера (консольное приложение на основе Dotnet Framework 4.7.2).

class Program
    {
        static void Main(string[] args)
        {
            Uri uri = new Uri("http://localhost:21011");
            MtomMessageEncodingBindingElement encoding = new MtomMessageEncodingBindingElement();
            var transport = new HttpTransportBindingElement();
            transport.TransferMode = TransferMode.Streamed;
            var binding = new CustomBinding(encoding, transport);
            using (ServiceHost sh = new ServiceHost(typeof(MyService), uri))
            {
                sh.AddServiceEndpoint(typeof(IService), binding, "");
                ServiceMetadataBehavior smb;
                smb = sh.Description.Behaviors.Find<ServiceMetadataBehavior>();
                if (smb == null)
                {
                    smb = new ServiceMetadataBehavior()
                    {
                        HttpGetEnabled = true
                    };
                    sh.Description.Behaviors.Add(smb);
                }
                Binding mexbinding = MetadataExchangeBindings.CreateMexHttpBinding();
                sh.AddServiceEndpoint(typeof(IMetadataExchange), mexbinding, "mex");


                sh.Opened += delegate
                {
                    Console.WriteLine("Service is ready");
                };
                sh.Closed += delegate
                {
                    Console.WriteLine("Service is clsoed");
                };
                sh.Open();
                Console.ReadLine();
                //pause
                sh.Close();
                Console.ReadLine();
            }
        }
    }
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string Test();

    }
    public class MyService : IService
    {
        public string Test()
        {
            return DateTime.Now.ToLongTimeString();
        }
}

На стороне клиента (базовое консольное приложение с пакетом WcfCoreMtomEncoder nuget, вызывающее службу с помощью ChannelFactory).

    class Program
    {
        static void Main(string[] args)
        {
            var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
            var transport = new HttpTransportBindingElement();
            transport.TransferMode = TransferMode.Streamed;
            var binding = new CustomBinding(encoding, transport);
            EndpointAddress endpoint = new EndpointAddress("http://vabqia969vm:21011");
            ChannelFactory<IService> channelFactory = new ChannelFactory<IService>(binding, endpoint);
            var webService = channelFactory.CreateChannel();
            Console.WriteLine(webService.Test());
        }
    }
    [ServiceContract]
    public interface IService
    {
        [OperationContract]
        string Test();

}

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

Netsh http добавить sslcert ipport=0.0.0.0 certhash=0102030405060708090A0B0C0D0E0F1011121314 appid={00112233-4455-6677-8899-AABBCCDDEEFF}

В приведенном выше примере я привязываю сертификат с именованным субъектом vabqia969vm (DNS) к машине (имя хоста — vabqia969vm). Вот несколько официальных ссылок.
https://docs.microsoft.com/en-us/windows/win32/http/add-sslcert
https://docs.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
На стороне клиента перед вызовом службы мы должны установить доверительные отношения, чтобы связь доступен между клиентской и серверной частью. Поэтому я устанавливаю сертификат сервера на клиентской части LocalCA (доверенные корневые центры сертификации в хранилище сертификатов). В качестве альтернативы мы могли бы вручную добавить процесс проверки сертификата.

ChannelFactory<IService> channelFactory = new ChannelFactory<IService>(binding, endpoint);
            channelFactory.Credentials.ServiceCertificate.SslCertificateAuthentication = new System.ServiceModel.Security.X509ServiceCertificateAuthentication()
            {
                CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
                RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
            };

Не стесняйтесь, дайте мне знать, если я могу чем-то помочь.
Обновлено.
Я обновил приведенный выше пример, который правильно работает по протоколу HTTP.

person Abraham Qian    schedule 24.01.2020
comment
Ваш код использует .Net Framework 4.7.2? Мой пост был конкретно связан с .Net Core - person user1186050; 25.01.2020
comment
На стороне сервера используется .Net Framework 4.7.2, на стороне клиента используется .Net core Sdk. Вот где применяется библиотека, позволяющая базовому приложению использовать кодировщик Mtom. Серверная часть на основе .Net Core не может создавать сервисные приложения Wcf, поскольку это распределенная структура, основанная на .Net framework, еще не реализованная в Core. gRPC — лучший подход для создания распределенных приложений в Core. - person Abraham Qian; 25.01.2020
comment
@ user1186050 , В приведенных выше фрагментах кода мы также можем создать службу без режима безопасности транспортного уровня. и его можно правильно вызывать и в приложении Dotnet Core. Если мы поступим таким образом, нам не нужно указывать базовый адрес `https', нет необходимости привязывать сертификат, это будет легко завершено. Я обновил ответ, пожалуйста, проверьте. - person Abraham Qian; 27.01.2020

Действуйте следующим образом:

  1. Создайте клиент службы с помощью WCF, это приведет к пространству имен и разделяемому классу, скажем, DocumentWebServiceClient,
  2. в том же проекте и пространстве имен создайте файл для расширения частичного класса и реализации метода ConfigureEndpoint, который предназначен для задач настройки конечной точки:
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using WcfCoreMtomEncoder;

public partial class DocumentWebServiceClient // DocumentWebServiceClient is generated by the WCF
{
    static partial void ConfigureEndpoint(ServiceEndpoint serviceEndpoint, ClientCredentials clientCredentials)
    {
        var messageEncodingBindingElementType = typeof(MessageEncodingBindingElement);
        var elements = serviceEndpoint.Binding.CreateBindingElements();

        IEnumerable<BindingElement> elementsWithoutEncodingElement = elements.Where(item => !messageEncodingBindingElementType.IsAssignableFrom(item.GetType()));
        var existingEncodingElement = (MessageEncodingBindingElement)elements.Where(item => messageEncodingBindingElementType.IsAssignableFrom(item.GetType())).First();

        var newEncodingElement = new MtomMessageEncoderBindingElement(existingEncodingElement);

        // Encoding is before transport, so we prepend the MTOM message encoding binding element
        // https://docs.microsoft.com/en-us/dotnet/framework/wcf/extending/custom-bindings
        var cb = new CustomBinding(elementsWithoutEncodingElement.Prepend(newEncodingElement));
        serviceEndpoint.Binding = cb;
    }
}
person aleksander_si    schedule 31.08.2020

ваш основной клиентский код .net должен быть примерно таким

var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement());
var transport = new HttpTransportBindingElement();
var customBinding = new CustomBinding(encoding, transport);


EndpointAddress endpoint = new EndpointAddress(url);
var channelFactory = new ChannelFactory<T>(customBinding, endpoint);
var webService = channelFactory.CreateChannel();
user.UserName = await webService.EncryptValueAsync(userName);
user.Password = await webService.EncryptValueAsync(password);
var documentAddResult = webService.DocumentAdd(document);
channelFactory.Close();
person divyang4481    schedule 14.01.2020
comment
Вы знаете, поддерживает ли это https? Используя его, я получаю исключение, в котором говорится: Предоставленная схема URI «https» недействительна; ожидаемый 'http' - person user1186050; 22.01.2020
comment
в этом случае используйте HttpsTransportBindingElement вместо HttpTransportBindingElement - person divyang4481; 22.01.2020
comment
но он ожидает http, а не https согласно сообщению. Ты не предлагаешь мне сделать наоборот? - person user1186050; 23.01.2020
comment
Если URL-адрес вашего сервера http, используйте httptransportbinding - person divyang4481; 23.01.2020

Расширение ответа @divyang4481. Для тех, кто все еще борется с этим, в зависимости от службы, с которой вы взаимодействуете, вам, возможно, придется изменить кодировку на что-то вроде следующего:

        var encoding = new MtomMessageEncoderBindingElement(new TextMessageEncodingBindingElement
        {
            MessageVersion = MessageVersion.CreateVersion(EnvelopeVersion.Soap12, AddressingVersion.None)
        });

        var transport = new HttpsTransportBindingElement();
        var customBinding = new CustomBinding(encoding, transport);

Веб-служба, которую я вызывал, выдала ошибку, то есть заголовки mustUnderstand с TextMessageEncodingBindingElement по умолчанию, поэтому мне пришлось установить для AddressVersion значение none, чтобы решить проблему. проблема.

person hamza_ml    schedule 25.04.2021