Dynamically invoking WCF service - wcf

I've created ASP.NET application and added simple WCF service to it. The ASP.NET application is host for WCF service. The service is running.
The service looks as follows:
[ServiceContract]
public interface IService1
{
[OperationContract]
string DoWork(string text);
}
public class Service1 : IService1
{
public string DoWork(string text)
{
return text.ToUpper();
}
}
On the client side is console application that should invoke WCF service dynamically. I use following code:
WSHttpBinding binding = new WSHttpBinding(SecurityMode.None);
IChannelFactory<IRequestChannel> factory = binding.BuildChannelFactory<IRequestChannel>(
new BindingParameterCollection());
factory.Open();
EndpointAddress address = new EndpointAddress("http://localhost:3929/Service1.svc");
IRequestChannel irc = factory.CreateChannel(address);
using (irc as IDisposable)
{
irc.Open();
XmlReader reader = XmlReader.Create(new StringReader(
#"<DoWork xmlns='http://tempuri.org/'>
<composite xmlns:a='http://www.w3.org/2005/08/addressing'
xmlns:i='http://www.w3.org/2001/XMLSchema-instance'>
<a:StringValue>aaaa</a:StringValue>
</composite>
</DoWork>"));
Message m = Message.CreateMessage(MessageVersion.Soap12,
"http://tempuri.org/IService1/DoWork", reader);
Message ret = irc.Request(m);
reader.Close();
Console.WriteLine(ret);
}
//close the factory
factory.Close();
But, it crashes at this line:
Message ret = irc.Request(m);
with following error:
The message version of the outgoing message (Soap12 (http://www.w3.org/2003/05/soap-envelope) AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)) does not match that of the encoder (Soap12 (http://www.w3.org/2003/05/soap-envelope) Addressing10 (http://www.w3.org/2005/08/addressing)). Make sure the binding is configured with the same version as the message.
Does anybody know what I'm doing wrong?
Thank you in advance.

Message.CreateMessage(MessageVersion.Soap12,
Instead of the MessageVersion enum value Soap12, you need to specify Soap12Addressing10 to match your binding.

Related

There was no endpoint listening at ... that could accept the message

I'm building an ASP.NET Core web API project.
Service runs sometimes, sometimes fails.
I get 90% successful results.
There was no endpoint listening at (url) that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
The binding is as follows
The service should work improperly. By default, the invocation sent by a proxy preferentially uses the service URI generated in the reference.cs file.
We should change it to the practical service URL.
https://vabqia96vm:21011/
Furthermore, the service communicates with the client is protected by the transport layer security. We should trust the server’s certificate before sending an invocation or add a procedure of SSL authentication to ignore validating the server's certificate.
ServiceReference1.ServiceClient client = new ServiceClient();
//ignore the SSL authentication.
client.ClientCredentials.ServiceCertificate.SslCertificateAuthentication=new System.ServiceModel.Security.X509ServiceCertificateAuthentication()
{
CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};
var result = client.TestAsync();
Console.WriteLine(result.Result);
Also, we could call the service by using ChannelFactory.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("https://vabqia969vm:21011");
BasicHttpsBinding binding = new BasicHttpsBinding();
binding.Security.Mode = BasicHttpsSecurityMode.Transport;
binding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri));
factory.Credentials.ServiceCertificate.SslCertificateAuthentication=new System.ServiceModel.Security.X509ServiceCertificateAuthentication()
{
CertificateValidationMode = System.ServiceModel.Security.X509CertificateValidationMode.None,
RevocationMode = System.Security.Cryptography.X509Certificates.X509RevocationMode.NoCheck
};
var client = factory.CreateChannel();
var result = client.Test();
Console.WriteLine(result);
}
}
//the service contract is shared between the server-side and the client-side.
[ServiceContract]
public interface IService
{
[OperationContract]
string Test();
}
Feel free to let me know if there is anything I can help with.

Consume external WCF service using channel factory and not by using proxy or adding service reference

I would like to know if there is a possibility to consume an external wcf service (by external wcf service i mean a service that is not part of my solution) using channel factory. I'm aware that we can consume by generating a proxy or adding service reference but i want to know if we can use channel factory. Since its an external service we will not be having the interface class with use so need to know how will the channel factory instance look like?
You would need to mimic the interface the service has by looking at the WSDL file(metadata file on the service)
Then you can use a few helper methods to initialise your service,
public static TChannel GetBasicHttpService<TChannel>(string serviceEndpoint) where TChannel : class
{
EndpointAddress myEndpoint = new EndpointAddress(serviceEndpoint);
ChannelFactory<TChannel> myChannelFactory = new ChannelFactory<TChannel>(DefaultHttpBinding(), myEndpoint);
// Create a channel.
return myChannelFactory.CreateChannel();
}
public static BasicHttpBinding DefaultHttpBinding()
{
BasicHttpBinding defaultBinding = new BasicHttpBinding();
defaultBinding.MaxReceivedMessageSize = 2147483647;
defaultBinding.MaxBufferPoolSize = 2147483647;
defaultBinding.MaxBufferSize = 2147483647;
defaultBinding.ReaderQuotas.MaxArrayLength = 2147483647;
defaultBinding.ReaderQuotas.MaxStringContentLength = 2147483647;
return defaultBinding;
}
where TChannel is the Mimicked interfaced
You should know the format of the service contract interface and endpoint, or we could not create the channel factory. The reason why the channel factory is used to invoke the service is that in order to protect the WCF service, server-side disable publishing service metadata. I have made a simple demo, wish it is useful to you.
Server-side.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1900");
BasicHttpBinding binding = new BasicHttpBinding();
using (ServiceHost sh=new ServiceHost(typeof(MyService),uri))
{
sh.AddServiceEndpoint(typeof(IService), binding, "");
sh.Open();
Console.WriteLine("Service is ready...");
Console.ReadLine();
sh.Close();
}
}
}
[ServiceContract(Namespace ="mydomain")]
public interface IService
{
[OperationContract(Name ="AddInt")]
int Add1(int x, int y);
}
public class MyService : IService
{
public int Add(int x, int y)
{
return x + y;
}
}
Client-side.
class Program
{
static void Main(string[] args)
{
Uri uri = new Uri("http://localhost:1900");
BasicHttpBinding binding = new BasicHttpBinding();
using (ChannelFactory<IService> factory = new ChannelFactory<IService>(binding, new EndpointAddress(uri)))
{
IService sv = factory.CreateChannel();
var result = sv.Add(34, 3);
try
{
Console.WriteLine(result);
}
catch (Exception ex)
{
throw;
}
}
}
}
[ServiceContract(Namespace = "mydomain")]
public interface IService
{
[OperationContract(Name = "AddInt")]
int Add2(int x, int y);
}
There is no need to make sure that the client and the server has a same service interface, but they at least need to ensure that the namespace and name property of the interface is consistent between the client and server.
Feel free to let me know if there is anything I can help with.

Hosting WCF Service as Windows Service

I have created WCF service project.
It has following content in SVC file.
<%# ServiceHost Service="Deepak.BusinessServices.Implementation.ApiImplementation"
Factory="Deepak.BusinessServices.Implementation.CustomServiceHostFactory"%>
SVC reference
http://localhost/DeepakGateway/Service.svc
Service is UP and WSDL generated. Now I want to host this service as Windows Service.
How can I do it?
I have created "Windows Service" Project ans have following code.
protected override void OnStart(string[] args)
{
if (m_Host != null)
{
m_Host.Close();
}
Uri httpUrl = new Uri("http://localhost/DeepakGateway/Service.svc");
m_Host = new ServiceHost
(typeof(?????? WHAT TO FILL HERE?), httpUrl);
//Add a service endpoint
m_Host.AddServiceEndpoint
(typeof(?????? WHAT TO FILL HERE?), ), new WSHttpBinding(), "");
//Enable metadata exchange
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
m_Host.Description.Behaviors.Add(smb);
//Start the Service
m_Host.Open();
}
You need to add the type of the class that implements your service contract in the ServiceHost constructor, and type of the service contract in your AddServiceEndpoint
Assuming your service implementation class looks something like this:
namespace Deepak.BusinessServices.Implementation
{
public class ApiImplementation : IApiImplementation
{
....
}
}
then you need:
m_Host = new ServiceHost(typeof(ApiImplementation), httpUrl);
m_Host.AddServiceEndpoint(typeof(IApiImplementation), new WSHttpBinding(), "");
the service host needs to know what (concrete) type of service class to host
the endpoint needs to know what service contract (interface) it exposes

Error while trying to access the method in the WCF service where the project type is "WCF Service application"

I have a WCF Service application project , a class library project(acts as a proxy betwen the service and the client) and a Asp.net web project.
Now in the WCF Service application project, I have the method GetData(int) [the default one]
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
I complied the WCF service project and found it working and henceforth added that as service reference to the Class library project. And written a method as under to fetch the value from the service
public string GetResult(int number)
{
string result = "";
try
{
Service1Client sc = new Service1Client();
result = sc.GetData(number);
}
catch (Exception ex)
{
var message = ex.Message;
}
return result;
}
Now this method is being invoked from the Web application. At runtime I am getting an exception
Could not find default endpoint element that references contract 'ServiceReference1.IService1' in the ServiceModel client configuration section. This might be because no configuration file was found for your application, or because no endpoint element matching this contract could be found in the client element.
The error is happening at Service1Client sc = new Service1Client();
All the config files are in place....Should I have to create the proxy using SVC util?
What am I missing?
Are you sure you have apropriate configuration for wcf placed in web.config? It seems you don't.

How to call a service operation at a REST style WCF endpoint uri?

is it possible to call a service operation at a wcf endpoint uri with a self hosted service?
I want to call some default service operation when the client enters the endpoint uri of the service.
In the following sample these uris correctly call the declared operations (SayHello, SayHi):
- http://localhost:4711/clerk/hello
- http://localhost:4711/clerk/hi
But the uri
- http://localhost:4711/clerk
does not call the declared SayWelcome operation. Instead it leads to the well known 'Metadata publishing disabled' page. Enabling mex does not help, in this case the mex page is shown at the endpoint uri.
private void StartSampleServiceHost()
{
ServiceHost serviceHost = new ServiceHost(typeof(Clerk), new Uri( "http://localhost:4711/clerk/"));
ServiceEndpoint endpoint = serviceHost.AddServiceEndpoint(typeof(IClerk), new WebHttpBinding(), "");
endpoint.Behaviors.Add(new WebHttpBehavior());
serviceHost.Open();
}
[ServiceContract]
public interface IClerk
{
[OperationContract, WebGet(UriTemplate = "")]
Stream SayWelcome();
[OperationContract, WebGet(UriTemplate = "/hello/")]
Stream SayHello();
[OperationContract, WebGet(UriTemplate = "/hi/")]
Stream SayHi();
}
public class Clerk : IClerk
{
public Stream SayWelcome() { return Say("welcome"); }
public Stream SayHello() { return Say("hello"); }
public Stream SayHi() { return Say("hi"); }
private Stream Say(string what)
{
string page = #"<html><body>" + what + "</body></html>";
return new MemoryStream(Encoding.UTF8.GetBytes(page));
}
}
Is there any way to disable the mex handling and to enable a declared operation instead?
Thanks in advance, Dieter
Did you try?
[OperationContract, WebGet(UriTemplate = "/")]
Stream SayWelcome();
UPDATE:
Not sure why it is not working for you, I have a self hosted WCF service with the following service contract:
[ServiceContract]
public interface IDiscoveryService {
[OperationContract]
[WebGet(BodyStyle=WebMessageBodyStyle.Bare, UriTemplate="")]
Stream GetDatasets();
The only difference I can see is that I use WebServiceHost instead of ServiceHost.