After some struggles, I managed to create a WCF service that could be consumed by the class library. But it only supports the Custombinding. Please refer to the below example.
Server-side (a console application based on 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();
}
}
Client-side (Core-based Console application with WcfCoreMtomEncoder
nuget package, calling the service by using 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();
}
One more thing we pay attention to is that we should manually bind a certificate to the particular port on the server-side if the server using Transport security mode to secure the communication.
Netsh http add sslcert ipport=0.0.0.0
certhash=0102030405060708090A0B0C0D0E0F1011121314
appid={00112233-4455-6677-8899-AABBCCDDEEFF}
In the above example, I bind a certificate that has a named vabqia969vm
subject(DNS) to the machine(hostname is vabqia969vm
). Here are some official links.
https://learn.microsoft.com/en-us/windows/win32/http/add-sslcert
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-configure-a-port-with-an-ssl-certificate
On the client-side, before making a call to the service, we should establish a trust relationship so that communication is available between the client-side and the server-side. Therefore, I install the server certificate on the client-side LocalCA(Trusted Root Certification Authorities in the certification store). Alternatively, we could manually add a certificate validation process.
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
};
Feel free to let me know if there is anything I can help with.
Updated.
I have updated the above example which works properly over HTTP
protocol.