I want to create WCF client directly from code:
var binding = new BasicHttpBinding();
var myEndpoint = new EndpointAddress("http://localhost/acquisition/production.svc");
var myChannelFactory = new ChannelFactory<IProduction>(binding, myEndpoint);
proxy = myChannelFactory.CreateChannel();
The problem is that following code throws exception:
There was no endpoint listening at.
But when add reference do WCF test client, service is discovered properly and can be invoked withouy any errors:
Why manual endpoint doesn't work?
Related
I have a WCF service which has a method named ArchiveFile(string fileName) which basically archives files. I have created a proxy project using svcutil and added its reference created in my client application and is consuming the service as follows:
var binding = new WSHttpBinding { Security = new WSHttpSecurity() { Mode = SecurityMode.None } };
var address = new EndpointAddress(this.TargetUrl);
var fileService = new FileServiceClient(binding, address);'
I want to know how do I determine the Http Status Code (200 - OK or any other) for the WCF Service call.
We can get the http status code through WebOperationContext Class:
WebOperationContext statuscode = WebOperationContext.Current;
Console.WriteLine(statuscode.OutgoingResponse.StatusCode);
For more information about WebOperationContext,please refer to the following link:
https://learn.microsoft.com/en-us/dotnet/api/system.servicemodel.web.weboperationcontext?view=netframework-4.8
I've got a strange problem: I have a wcf service which needs to be hosted by tcp protocol on a standalone console application.
I have created a new console app project and added a lib reference for my wcf project. The problem occurs when I want to configure and broadcast the host.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
MyServiceHost = new ServiceHost(typeof(ImyService), Uri);
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "");
var mexBinding = MetadataExchangeBindings.CreateMexTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange),mexBinding, "");
ServiceMetadataBehavior serviceBehavior = new ServiceMetadataBehavior();
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
When it comes to open the host, I get this message:
The contract name 'IMetadataExchange' could
not be found in the list of contracts implemented by the service WcfService.Ser
vices.MyService. Add a ServiceMetadataBehavior to the configuration
file or to the ServiceHost directly to enable support for this contract.
Now that I have better time to check this.
First you need to get the service behavior from the host or create a new one and add it if not found.
Setting the HttpGetEnabled requires you to also ad a metadata uri to the baseaddresses.
Also it does not seem to matter if the metadata endpoint is named "mex", as long as all endpoints added have unique names. So you can't use empty string for both endpoints.
var Uri = new Uri("net.tcp://myaddress:4322/MyService");
var MetadataUri = new Uri("http://myaddress:8000/MyService");
var MyServiceHost = new ServiceHost(typeof(MyService), Uri, MetadataUri);
var serviceBehavior = MyServiceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
if (serviceBehavior == null)
{
serviceBehavior = new ServiceMetadataBehavior();
MyServiceHost.Description.Behaviors.Add(serviceBehavior);
}
serviceBehavior.HttpGetEnabled = true;
serviceBehavior.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
MyServiceHost.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexTcpBinding(), "mex");
var binding = new NetTcpBinding();
MyServiceHost.AddServiceEndpoint(typeof(IImageExchangeService), binding, "image");
I'm trying to get my generated WCF ServiceClient to send its requests to the WCF service through a HTTP (not HTTPS) proxy with username/password authentication, however I just can't get it work. My WCF service uses basicHttpBinding so I tried to configure my ServiceClient instance like so:
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.ProxyAddress = new Uri(proxyAddress);
b.UseDefaultWebProxy = false;
b.Security.Mode = BasicHttpSecurityMode.Transport;
b.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
b.Security.Transport.ProxyCredentialType = HttpProxyCredentialType.Basic;
svc.ClientCredentials.UserName.UserName = proxyUsername;
svc.ClientCredentials.UserName.Password = proxyPassword;
This however results in a System.ArgumentException saying:
The provided URI scheme http is invalid. expected https
When I set the b.Security.Mode to BasicHttpSecurityMode.None though, it seems the HTTP proxy settings are ignored by WCF altogether!
The second solution I tried was to set the DefaultWebProxy property of WebRequest and set the UseDefaultWebProxy property to true such as so:
var webProxy = new WebProxy(proxyAddress, true);
webProxy.Credentials = new NetworkCredential(proxyUsername, proxyPassword);
WebRequest.DefaultWebProxy = webProxy;
var svc = new ServiceClient();
var b = svc.Endpoint.Binding as BasicHttpBinding;
b.UseDefaultWebProxy = true;
However this also doesn't work and ServiceClient doesn't send it's requests through the HTTP proxy.
I'm out of ideas here so please let me know what I am doing wrong, thank you!
Set the security mode to BasicHttpSecurityMode.TransportCredentialOnly. This allows for passing plain-text authentication details over HTTP.
I am working on a C# WCF application. I am trying to start a soap service that is self hosted within a console application.
I want to do everything programatically as its going to be in a library which will have different values, such as URL etc for various other applications it is going to be used on.
I have added the code but when I try to start the service I am getting an error:
The contract name 'IMetadataExchange' could not be found i n the list
of contracts implemented by the service Engine.SoapServer. Add a Ser
viceMetadataBehavior to the configuration file or to the ServiceHost
directly to enable support for this contract.
Below is how I am starting the soap service
if (Environment.GetEnvironmentVariable("MONO_STRICT_MS_COMPLIANT") != "yes")
{
Environment.SetEnvironmentVariable("MONO_STRICT_MS_COMPLIANT", "yes");
}
if (String.IsNullOrEmpty(soapServerUrl))
{
string message = "Not starting Soap Server: URL or Port number is not set in config file";
library.logging(methodInfo, message);
library.setAlarm(message, CommonTasks.AlarmStatus.Medium, methodInfo);
return;
}
baseAddress = new Uri(soapServerUrl);
host = new ServiceHost(soapHandlerType, baseAddress);
BasicHttpBinding basicHttpBinding = new BasicHttpBinding();
//basicHttpBinding.Namespace = "http://tempuri.org/";
host.AddServiceEndpoint(soapManagerInterface, basicHttpBinding, soapServerUrl);
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
var meta = new ServiceMetadataBehavior()
{
//ExternalMetadataLocation = new Uri(soapServerUrl + "/CritiMon?wsdl"),
HttpGetEnabled = true,
HttpGetUrl = new Uri("", UriKind.Relative),
HttpGetBinding = basicHttpBinding,
};
//meta.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(meta);
var debugBehaviour = new ServiceDebugBehavior()
{
HttpHelpPageEnabled = true,
HttpHelpPageUrl = new Uri("", UriKind.Relative),
IncludeExceptionDetailInFaults = true,
HttpHelpPageBinding = basicHttpBinding,
};
host.Description.Behaviors.Remove(typeof(ServiceDebugBehavior));
host.Description.Behaviors.Add(debugBehaviour);
host.Opened += new EventHandler(host_Opened);
host.Faulted += new EventHandler(host_Faulted);
host.Closed += new EventHandler(host_Closed);
host.UnknownMessageReceived += new EventHandler<UnknownMessageReceivedEventArgs>(host_UnknownMessageReceived);
host.Open();
At the moment I am seeing this issue on Windows but I also need it work on Linux under Mono
UPDATE
As per Vibhu, suggestion, I have tried doing what was suggested and I am now getting a different error, so hopefully getting somewhere, the error is as follows:
MessageVersion 'Soap11 (http://schemas.xmlsoap.org/soap/envelope/)
AddressingNone
(http://schemas.microsoft.com/ws/2005/05/addressing/none)' is not
supported in this scenario. Only MessageVersion 'EnvelopeNone
(11http://s chemas.microsoft.com/ws/2005/05/envelope/none11)
AddressingNone (http://schemas.microsoft.com/ws/2005/05/addressing/none)' is supported.
UPDATE 2
I have done again what vibhu suggeste and the soap service is successfully starting now but I am getting an error about a mismatched content type when I try and access it from the WCF Test client bundled with VS2010.
Below is the error
> Error: Cannot obtain Metadata from http://localhost:8000/CritiMon If
> this is a Windows (R) Communication Foundation service to which you
> have access, please check that you have enabled metadata publishing at
> the specified address. For help enabling metadata publishing, please
> refer to the MSDN documentation at
> http://go.microsoft.com/fwlink/?LinkId=65455.WS-Metadata Exchange
> Error URI: http://localhost:8000/CritiMon Metadata contains a
> reference that cannot be resolved: 'http://localhost:8000/CritiMon'.
> Content Type application/soap+xml; charset=utf-8 was not supported by
> service http://localhost:8000/CritiMon. The client and service
> bindings may be mismatched. The remote server returned an error:
> (415) Cannot process the message because the content type
> 'application/soap+xml; charset=utf-8' was not the expected type
> 'text/xml; charset=utf-8'..HTTP GET Error URI:
> http://localhost:8000/CritiMon There was an error downloading
> 'http://localhost:8000/CritiMon'. The request failed with HTTP
> status 400: Bad Request
Place your metadata behavior before adding Mex endpoint -
var meta = new ServiceMetadataBehavior()
{
//ExternalMetadataLocation = new Uri(soapServerUrl + "/CritiMon?wsdl"),
HttpGetEnabled = true,
HttpGetUrl = new Uri("", UriKind.Relative),
HttpGetBinding = basicHttpBinding,
};
host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
I've written a WCF duplex service and client. Everything works well until I try to call .Demand() in the client implementation. It appears that the the service invokes the callback method Anonymously. I think I am missing how to correctly configure the service.
Code used to create ServiceHost;
ServiceHost duplex = new ServiceHost(new ServerWCallbackImpl());
NetTcpBinding secureBinding = new NetTcpBinding(SecurityMode.Message);
secureBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
duplex.AddServiceEndpoint(typeof(IServerWithCallback),
secureBinding,
"net.tcp://localhost:9080/DataService");
Console.WriteLine(Thread.CurrentPrincipal.Identity.Name); //<-- this correctly shows the current principal
duplex.Open();
if (duplex.State == CommunicationState.Opened)
((ServerWCallbackImpl)duplex.SingletonInstance).Send("Hello World!");
Code used to create client;
CallbackImpl callbackInstance = new CallbackImpl();
NetTcpBinding secureBinding = new NetTcpBinding(SecurityMode.Message);
secureBinding.Security.Message.ClientCredentialType = MessageCredentialType.Windows;
DuplexChannelFactory<IServerWithCallback> cf = new DuplexChannelFactory<IServerWithCallback>(
callbackInstance,
secureBinding,
new EndpointAddress(requestingEndpointAddress));
cf.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
cf.Credentials.Windows.ClientCredential = (NetworkCredential)CredentialCache.DefaultCredentials;
IServerWithCallback srv = cf.CreateChannel(new InstanceContext(callbackInstance));
srv.InitiateConversation();
Client implementation:
public void MethodOnClient(string message)
{
Console.WriteLine(Thread.CurrentPrincipal.Identity.Name); // <-- anonymous
PrincipalPermission p = new PrincipalPermission(#"DOMAIN\User", null);
p.Demand(); // <-- fails
}
How can I configure so that the ServiceHost correctly invokes the Callback with Windows credentials?
Does setting TokenImpersonationLevel to Delegation instead of Impersonation? Like this:
cf.Credentials.Windows.AllowedImpersonationLevel = TokenImpersonationLevel.Impersonation;
See this MSDN article.