I've searched thoroughly, and found several answers to this problem, but none of them apply.
I have a .NET 4.0 WCF service hosted by windows services using a named pipe endpoint. This is set to start automatically on boot. I have a client that consumes the service.
When the server is rebooted, the service will start normally, but the client will get the following error:
1: There was no endpoint listening at net.pipe://localhost/WCFSQLService/ that could accept the message. This is often caused by an incorrect address or SOAP action. See InnerException, if present, for more details.
2: The pipe endpoint 'net.pipe://localhost/WCFSQLService/' could not be found on your local machine.
If the client and service are both restarted, the problem resolves itself.
As others have pointed out, both the Net.Pipe Listener Adapter is running and the WCF Non-HTTP Activation is checked:
We've even tried setting the service to delayed start, but no joy. One would assume it was something wrong with the endpoint or config or normal WCF stuff, but when the service and client are both restarted everything works. Additionally, this only happens on 1 machine. If necessary I can provide endpoint information and code.
Client:
NetNamedPipeBinding binding = new NetNamedPipeBinding();
EndpointAddress endpoint = new EndpointAddress(endpointAddress);
ChannelFactory<IWCFSQLService> channel = new ChannelFactory<IWCFSQLService>(binding, endpoint);
IWCFSQLService client = channel.CreateChannel();
// do client calls
channel.Close();
Host
class Program
{
static void Main(string[] args)
{
ServiceBase[] servicesToRun = new ServiceBase[]
{
new WinServiceHost(),
};
ServiceBase.Run(servicesToRun);
}
}
public class WinServiceHost : ServiceBase
{
private readonly ServiceManager serviceManager = new ServiceManager();
protected override void OnStart(string[] args)
{
base.OnStart(args);
serviceManager.OpenHost<MyService>();
}
protected override void OnStop()
{
base.OnStop();
serviceManager.CloseAll();
}
}
public class ServiceManager
{
private readonly List<ServiceHost> serviceHosts = new List<ServiceHost>();
public void CloseAll()
{
foreach (ServiceHost serviceHost in serviceHosts)
{
serviceHost.Close();
}
}
public void OpenHost<T>()
{
Type type = typeof(T);
ServiceHost serviceHost = new ServiceHost(type);
serviceHost.Open();
serviceHosts.Add(serviceHost);
}
}
config
<system.serviceModel>
<services>
<service behaviorConfiguration="behaviorConfig" name="MyService">
<endpoint address="" binding="netNamedPipeBinding" bindingConfiguration="clientNamedPipeBinding"
contract="IMyService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/MyService" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netNamedPipeBinding>
<binding name="clientNamedPipeBinding">
<readerQuotas maxArrayLength="65536" maxBytesPerRead="65536" />
</binding>
</netNamedPipeBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="behaviorConfig">
<serviceMetadata httpGetEnabled="false" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
<serviceSecurityAudit auditLogLocation="Application" suppressAuditFailure="true" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="SuccessOrFailure" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
Maybe the server is killing the named pipe? Try to re-open the channel on the client periodically until it recovers maybe.
Related
I am developing an UWP application which consumes wcf duplex service made by myself. The problem occurs when I try to call a method from service, literally method does not firing up and no breakpoint in service code is hitted.
This is my configuration in host application
<system.serviceModel>
<services>
<service name="WcfService.Services.ImageExchangeService" behaviorConfiguration="behaviorConfig">
<endpoint address="net.tcp://localhost:4322/WcfService/Services/ImageExchangeService/tcp" binding="netTcpBinding" contract="WcfService.Services.IImageExchangeService" bindingConfiguration="tcpBinding"></endpoint>
<endpoint address="net.tcp://localhost:4323/WcfService/Services/ImageExchangeService/mex" binding="mexTcpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:4321/WcfService/Services/ImageExchangeService" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="behaviorConfig">
<!-- To avoid disclosing metadata information,
set the values below to false before deployment -->
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<!-- To receive exception details in faults for debugging purposes,
set the value below to true. Set to false before deployment
to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="False" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<netTcpBinding>
<binding name="tcpBinding">
<security mode="None"></security>
<reliableSession enabled="true"/>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
This is my service interface
[ServiceContract(CallbackContract = typeof(IImageExchangeClient), SessionMode =SessionMode.Required)]
public interface IImageExchangeService
{
[OperationContract(IsOneWay = true)]
void Connect(string deviceIdentifier);
}
This is my implementation of above interface
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Single, IncludeExceptionDetailInFaults =true)]
public class ImageExchangeService : IImageExchangeService
{
private Dictionary<string, IImageExchangeClient> _connectedDevices = new Dictionary<string, IImageExchangeClient>();
public void Connect(string deviceIdentifier)
{
var connection = OperationContext.Current.GetCallbackChannel<IImageExchangeClient>();
if (!_connectedDevices.ContainsKey(deviceIdentifier))
{
_connectedDevices.Add(deviceIdentifier, connection);
}
else
{
_connectedDevices[deviceIdentifier] = connection;
}
Console.WriteLine("\nDevice connected: {0}", deviceIdentifier);
}
}
and finally this is my UWP code where I trying to call Connect method
public async void InitializeImageExchangeClient()
{
var endpoint = new EndpointAddress(new Uri("net.tcp://localhost:4322/WcfService/Services/ImageExchangeService/tcp"));
var InstanceContext = new InstanceContext(new ImageExchangeCallback());
var client = new ImageExchangeService.ImageExchangeServiceClient(buildBinding(), endpoint);
var channelFactory = (DuplexChannelFactory<IImageExchangeService>)(client.ChannelFactory);
var proxy = channelFactory.CreateChannel(InstanceContext);
await proxy.ConnectAsync(DeviceIdentifier);
}
I have also tried other approach of cal this method like:
var client = new ImageExchangeServiceClientBase(InstanceContext, buildBinding(), endpoint);
await client.OpenAsync();
await client.ConnectAsync(DeviceIdentifier);
buildBinding() function looks like this:
private NetTcpBinding buildBinding()
{
var binding = new NetTcpBinding()
{
MaxReceivedMessageSize = int.MaxValue,
MaxBufferPoolSize = int.MaxValue,
ReaderQuotas = new System.Xml.XmlDictionaryReaderQuotas()
{
MaxArrayLength = int.MaxValue,
MaxBytesPerRead = int.MaxValue,
MaxDepth = int.MaxValue,
MaxNameTableCharCount = int.MaxValue,
MaxStringContentLength = int.MaxValue
},
OpenTimeout = TimeSpan.MaxValue,
ReceiveTimeout = TimeSpan.MaxValue,
};
binding.Security.Mode = SecurityMode.None;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.Security.Message.ClientCredentialType = MessageCredentialType.None;
return binding;
}
Actual result is the method Connect is not firing up, and when I toggle breakpoint on this method it is not hitted.
Other non-duplex services are working fine without a problem.
When I implemented this service in WPF application the method is calling properly and everything works fine, the problem is when I trying to implement this in UWP architecture.
Thanks for help in advance.
I am using a DuplexChannelFactory to connect my client to my server and what I want to do now is connect the server to each client that will register on the server. But every time I launch a client, my "init()" function is ran twice. And my DuplexChannelFactory on the server side doesn't work.
Here is how I open my server for clients :
host = new ServiceHost(typeof(NewServeur.NewServeur));
host.Open();
with its App.Config :
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="MEX">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MEX" name="NewServeur.NewServeur">
<endpoint address="IProxyNewServeur" binding="netTcpBinding"
bindingConfiguration="configWin" name="NetTcpEndpoint" contract="ProxyNewServeur.IProxyNewServeur" />
<endpoint address="MEX" binding="mexTcpBinding" bindingConfiguration=""
name="MexTcpEndpoint" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="net.tcp://192.156.142.176:8080/" />
</baseAddresses>
</host>
</service>
</services>
<bindings>
<netTcpBinding>
<binding name="configWin">
<security mode="None"></security>
</binding>
</netTcpBinding>
</bindings>
</system.serviceModel>
Here is how I connect my client to my server :
void init()
{
ServiceCablingCallback ServiceCablingCallback = new ServiceCablingCallback();
ServiceCablingCallback.ClientNotified += ServiceCablingCallback_ClientNotified;
this._instanceContext = new InstanceContext(ServiceCablingCallback);
this.factory = new DuplexChannelFactory<ProxyNewServeur.IProxyNewServeur>(_instanceContext, "configClient");
this._serviceCablingClient = factory.CreateChannel();
this._clientId = _serviceCablingClient.Subscribe();
}
with its App.Config
<system.serviceModel>
<client>
<endpoint address="net.tcp://192.156.142.176:8080/IProxyNewServeur"
binding="netTcpBinding" bindingConfiguration="configWin" contract="ALSTEF.Cabling.ProxyNewServeur.IProxyNewServeur"
name="configClient" />
</client>
<bindings>
<netTcpBinding>
<binding name="configWin">
<security mode="None" />
</binding>
</netTcpBinding>
</bindings>
This works fine, but now I want to do the reverse thing, meaning connecting the server to the client. In order to do so, I added those lines before the last line of my client :
host = new ServiceHost(typeof(Service), new Uri(_serviceCablingClient.getIp()));
host.Open();
with getIp() returning the Ip address + the port 4242 of my client.
and this to the client App.config
<behaviors>
<serviceBehaviors>
<behavior name="MEX">
<serviceMetadata />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="MEX" name="Client.Model.Service">
<endpoint address="IClientFunction" binding="netTcpBinding" bindingConfiguration="ClientConfig"
name="NetTcpEndpoint" contract="ProxyNewServeur.IClientFunction" />
<endpoint address="MEX" binding="mexTcpBinding" bindingConfiguration=""
name="MexTcpEndpoint" contract="IMetadataExchange" />
</service>
</services>
<!-- in the bindings html tag -->
<binding name="ClientConfig">
<security mode="None" />
</binding>
And I modified the _serviceCablingClient.Subscribe() by adding those lines (so in the server)
public Guid Subscribe()
{
ProxyNewServeur.INewServeurCallback callback =
OperationContext.Current.GetCallbackChannel<ProxyNewServeur.INewServeurCallback>();
System.ServiceModel.Channels.RemoteEndpointMessageProperty endpointProperty =
OperationContext.Current.IncomingMessageProperties[System.ServiceModel.Channels.RemoteEndpointMessageProperty.Name] as System.ServiceModel.Channels.RemoteEndpointMessageProperty;
Guid clientId = Guid.NewGuid();
if (callback != null)
{
lock (clientsCallback)
{
clientsCallback.Add(clientId, callback);
}
}
/* code I added */
string addr = "net.tcp://" + endpointProperty.Address + ":" + "4242" + "/IClientFunction";
ClientCallback cb = new ClientCallback();
var Okvp = new KeyValuePair<Guid, DuplexChannelFactory<ProxyNewServeur.IClientFunction>>(clientId,
new DuplexChannelFactory<ProxyNewServeur.IClientFunction>(new InstanceContext(cb), "configServer",
new EndpointAddress(addr)));
this.DictClient.Add(Okvp, Okvp.Value.CreateChannel());
this.DictClient[Okvp].CreateCallbackChannel();
/* end code I added */
}
And I added this to the server App.config
<client>
<endpoint binding="netTcpBinding" bindingConfiguration="ClientConfig" contract="ProxyNewServeur.IClientFunction" name="configServer" />
</client>
<!-- in the bindings html tag -->
<binding name="ClientConfig">
<security mode="None" />
</binding>
Here is how I define my ProxyServeur file
namespace ProxyNewServeur
{
[ServiceContract(CallbackContract = typeof(INewServeurCallback))]
public interface IProxyNewServeur
{
[OperationContract]
Guid Subscribe();
[OperationContract]
string getIp();
}
[ServiceContract]
public interface INewServeurCallback
{
[OperationContract(IsOneWay = true)]
void HandleMessage(Message message);
}
[ServiceContract(CallbackContract = typeof(IClientCallback))]
public interface IClientFunction
{
[OperationContract(IsOneWay = true)]
void CreateCallbackChannel();
}
[ServiceContract]
public interface IClientCallback
{
[OperationContract(IsOneWay = true)]
void BroadcastToServer(bool isActive, Guid ClientId);
}
}
Now When I launch a client the line
DictClient[Okvp].CreateCallbackChannel();
won't work and I will go twice in the
init()
{ /* code*/
}
function.
I have no idea why this is happening. I did the exact same thing in a test project and it worked fine.
EDIT
As it turns out, you cannot have a DuplexChannelFactory<> and a ServiceHost in the same method. So what I did is that I added a new Class "DoubleConnection" that have only one attribute.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
public class DoubleConnection : ProxyNewServeur.IClientFunction
{
public ServiceHost host;
public void CreateCallbackChannel()
{}
public void isActive()
{}
}
and in the init() function I removed
host = new ServiceHost(typeof(Service), new Uri(_serviceCablingClient.getIp()));
host.Open();
and added
varClass = new DoubleConnection();
varClass.host = new ServiceHost(typeof(DoubleConnection), new Uri(_serviceCablingClient.getIp()));
varClass.host.Open();
I works fine now but I still don't know why you cannot have a DuplexChannelFactory<> and a ServiceHost in the same method.
I have a Windows Service which represents the WCF-Host and a WPF-Client-Application wich represents the WCF-Client.
The communication should be duplex so I went with WSDualHttpBinding.
At first I install and start my Service which opens a WCF connection after that I start my WPF app and I get the following error (I translated it):
No default endpoint was found to the contract
\ " WCFCloudManagerFolderWatcherService.Interfaces.IFilesDuplex \ " in the service model client configuration section
refers. This may be caused by: For the purposes of no configuration file was found
or in the client element no endpoint element was found , which corresponded to this contract .
Contracts:
IFilesDuplex-Contract:
[ServiceContract(Namespace = "http://Microsoft.ServiceModel.Samples", SessionMode = SessionMode.Required,
CallbackContract = typeof(IFilesDuplexCallback))]
public interface IFilesDuplex
{
[OperationContract(IsOneWay = true)]
void Update();
}
IFilesDuplexCallback:
interface IFilesDuplexCallback
{
[OperationContract(IsOneWay = true)]
void Equals(string[] result);
}
ClientSide
CallbackHandler:
class CallbackHandler : IFilesDuplexCallback
{
public event Action<string[]> ReceivedList = delegate { };
public void Equals(string[] result)
{
this.ReceivedList(result);
}
}
The Client itself:
class FilesDuplexClient : DuplexClientBase<IFilesDuplex>, IFilesDuplex
{
public FilesDuplexClient(InstanceContext callbackCntx)
: base(callbackCntx)
{
}
public void Update()
{
base.Channel.Update();
}
}
And the Code from the Main Window, where the error is thrown:
CallbackHandler ch = new CallbackHandler();
ch.ReceivedList += ch_ReceivedList;
// Construct InstanceContext to handle messages on callback interface
InstanceContext instanceContext = new InstanceContext(ch);
// Create a client
FilesDuplexClient client = new FilesDuplexClient(instanceContext);
client.Update();
Serverside (Windows Service)
FileProtocoll-Class (Server code)
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class FileProtocoll : IFilesDuplex
{
IFilesDuplexCallback Callback
{ get { return OperationContext.Current.GetCallbackChannel<IFilesDuplexCallback>(); } }
void IFilesDuplex.Update()
{
//....
Callback.Equals(null);// just a dummy
//...
}
}
Code in the OnStart-Method (in a Thread):
// Step 1 Create a URI to serve as the base address.
Uri baseAddress = new Uri("http://localhost:8899/CloudManager/CommunicationChannel1");
// Step 2 Create a ServiceHost instance
if (selfHost != null)
{
selfHost.Close();
}
selfHost = new ServiceHost(typeof(FileProtocoll), baseAddress);
try
{
// Step 5 Start the service.
selfHost.Open();
}
catch (CommunicationException ce)
{
selfHost.Abort();
}
Code in the OnStop-Method (in a Thread):
if (selfHost != null)
{
if (selfHost.State != CommunicationState.Closed)
{
selfHost.Close();
}
selfHost = null;
}
App.config:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<system.serviceModel>
<services >
<service behaviorConfiguration="ServiceBehavior"
name="WCFCloudManagerFolderWatcherService.Communication.FileProtocoll">
<endpoint address="http://localhost:8899/CloudManager /CommunicationChannel1"
binding="wsDualHttpBinding" contract="WCFCloudManagerFolderWatcherService.Interfaces.IFilesDuplex">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex"
binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="ServiceBehavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="true "/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
I finally got it.
Had to make a few changes to my Client app.config and had to turn off security.
app.config(client):
<!-- WCF Client information-->
<system.serviceModel>
<bindings>
<wsDualHttpBinding>
<binding name="WSDualHttpBinding_IFilesDuplex">
<security mode="None"/>
</binding>
</wsDualHttpBinding>
</bindings>
<client>
<endpoint
address="http://localhost:8899/CloudManager/CommunicationChannel1"
binding="wsDualHttpBinding"
bindingConfiguration="WSDualHttpBinding_IFilesDuplex"
contract="WCFCloudManagerFolderWatcherService.Interfaces.IFilesDuplex"
name="WSDualHttpBinding_IFilesDuplex">
<identity>
<userPrincipalName value="localhost"/>
</identity>
</endpoint>
</client>
and in the app.config for the serverside I also hat to set
<security mode="None"/>
Now the connection works.
I am developing a WCF service using WsHttpBinding and an SSL certificate for security. Works perfectly in my local IIS, but when I publish I get the following error message;
The protocol 'https' is not supported.
Here is my web.config file..
<system.serviceModel>
<services>
<service name="PeopleService.Service.PeopleService">
<host>
<baseAddresses>
<add baseAddress="https://www.mywebsite.com/service/"/>
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="BasicBinding" contract="PeopleService.Service.IPeopleService" name="BasicEndpoint"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="BasicBinding">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
I am using a ServiceHost factory to add my endpoints, so that I can load the SSL certificate from a physical file rather than from the certificate store.
public class PeopleServiceHost : ServiceHost
{
public PeopleServiceHost(params Uri[] addresses) : base(typeof(PeopleService), addresses)
{
}
protected override void InitializeRuntime()
{
Description.Behaviors.Find<ServiceDebugBehavior>().IncludeExceptionDetailInFaults = true;
Description.Behaviors.Find<ServiceDebugBehavior>().HttpsHelpPageUrl = new Uri("https://www.mywebsite.com/service/PeopleService.svc/mex");
ServiceMetadataBehavior metadataBehavior = new ServiceMetadataBehavior();
metadataBehavior.HttpsGetEnabled = true;
metadataBehavior.HttpsGetUrl = new Uri("https://www.mywebsite.com/service/PeopleService.svc/mex");
Description.Behaviors.Add(metadataBehavior);
var serviceCredentials = new ServiceCredentials();
serviceCredentials.ServiceCertificate.Certificate = new X509Certificate2(AppDomain.CurrentDomain.BaseDirectory + "\\mywebsite.pfx", "password123", X509KeyStorageFlags.MachineKeySet);
Description.Behaviors.Remove((typeof(ServiceCredentials)));
Description.Behaviors.Add(serviceCredentials);
base.InitializeRuntime();
}
}
I've been trying to solve this problem for days, but to no avail. I've contacted by host and they have advised me that HTTPS is definitely supported and enabled in IIS.
Any help is really appreciated. Thanks.
I have a problem connecting to my WCF service with clientCredentialType="UserName".
When I run the code below I get an error
FaultException: An error occurred when verifying security for the message.
When playing around with some of the binding values I also get Access is denied..
Fiddler says there is no authorization header and I cannot find the username or password in the request either.
Here are excerpts from my config:
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
<services>
<service name="InventoryServices.MobileAPI" behaviorConfiguration="customBehaviour">
<endpoint address=""
binding="basicHttpBinding"
bindingConfiguration="secureHttpBinding"
contract="InventoryServices.IMobileAPI"/>
<endpoint address="mex"
binding="mexHttpsBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="customBehaviour">
<serviceSecurityAudit auditLogLocation="Application" serviceAuthorizationAuditLevel="Failure" messageAuthenticationAuditLevel="Failure" suppressAuditFailure="true" />
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpsGetEnabled="true"/>
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom"
customUserNamePasswordValidatorType="InventoryLibrary.Helpers.UserAuthentication,InventoryLibrary"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<bindings>
<basicHttpBinding>
<binding name="secureHttpBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="Basic" proxyCredentialType="Basic" realm="MyRealm"/>
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
</bindings>
My username/password validator looks like so:
public class UserAuthentication : UserNamePasswordValidator {
public override void Validate(string userName, string password) {
EntitiesContext db = new EntitiesContext();
db.Logs.Add(new DomainModels.Log() {
DateLogged = DateTime.Now,
Message = "hit auth",
Type = DomainModels.LogType.Info
});
db.SaveChanges();
try {
if (userName == "test" && password == "test123") {
Console.WriteLine("Authentic User");
}
}
catch (Exception ex) {
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
I have this as a simple test on my service:
[OperationContract]
[XmlSerializerFormat]
void Test();
[PrincipalPermission(SecurityAction.Demand, Name = "test")]
public void Test() {
}
I have a self signed SSL certificate on my server and I can access my service/metadata.
Then I have added a service reference in a console application, and attempt to connect to the service with this code below:
class Program {
static void Main(string[] args) {
Stuff.InitiateSSLTrust();
BasicHttpBinding binding = new BasicHttpBinding();
binding.Security.Mode = BasicHttpSecurityMode.Transport;
binding.Security.Transport.Realm = "MyRealm";
ServiceReference1.MobileAPIClient serviceProxy = new ServiceReference1.MobileAPIClient(binding, new EndpointAddress("https://xx.xx.xx.xx/InventoryServices.MobileApi.svc"));
serviceProxy.ClientCredentials.UserName.UserName = "test";
serviceProxy.ClientCredentials.UserName.Password = "test123";
try {
var a = serviceProxy.Login("a", "b");
}
catch (Exception ex) {
var ex2 = ex;
}
}
}
public class Stuff {
public static void InitiateSSLTrust() {
try {
//Change SSL checks so that all checks pass
ServicePointManager.ServerCertificateValidationCallback =
new RemoteCertificateValidationCallback(
delegate { return true; }
);
}
catch (Exception ex) {
}
}
}
I've checked the event viewer on the server and this error appears with each request:
MessageSecurityException: Security processor was unable to find a security header in the message. This might be because the message is an unsecured fault or because there is a binding mismatch between the communicating parties. This can occur if the service is configured for security and the client is not using security.
You are specifying the client side to use BasicHttpSecurityMode.Transport whereas the service is expecting BasicHttpSecurityMode.TransportWithMessageCredential. This is a problem because the service is looking for the client credentials in the SOAP Message Header and the client will not send them with the binding configured this way.
Hence, this is why the username/password pair is not present in the Message Header as you are witnessing. So the event viewer was correct that there was a binding mismatch between the communicating parties.
Also set the ClientCredentialType on the client to BasicHttpMessageCredentialType.UserName for Message level security. By default BasicHttpBinding uses None which are anonymous clients.
Here's a code snippet describing the above changes:
var basicHttpBinding = new BasicHttpBinding(
BasicHttpSecurityMode.TransportWithMessageCredential);
basicHttpBinding.Security.Message.ClientCredentialType =
BasicHttpMessageCredentialType.UserName;
This can also be caused by the time being out of sync between client and server. If a certificate or signed token is invalid based off of time, the same An error occurred when verifying security for the message. message may be returned.
Just edit the .csproj file after adding the service reference and point these dependencies from 4.4.* to 4.6.*
<ItemGroup> <PackageReference Include="System.ServiceModel.Duplex" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Http" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.NetTcp" Version="4.6.*" />
<PackageReference Include="System.ServiceModel.Security" Version="4.6.*" />
</ItemGroup>
and add this
binding.Security.Mode = System.ServiceModel.BasicHttpSecurityMode.TransportWithMessageCredential;
binding.Security.Message.ClientCredentialType = BasicHttpMessageCredentialType.UserName;