WCF service contract not supported in test client - c#

I'm new to wcf and learning how to build one, with callbacks. I got an example from the following link:
http://architects.dzone.com/articles/logging-messages-windows-0
I tried implementing the wcf but when i run this in as a test by pressing f5, the test client says:
The service contract is not supported in the wcf client.
Service:
[ServiceBehavior(ConcurrencyMode = ConcurrencyMode.Reentrant, InstanceContextMode = InstanceContextMode.PerCall)]
public class RatsService : IRatsService
{
public static List<IRatsServiceCallback> callBackList = new List<IRatsServiceCallback>();
public RatsService()
{
}
public void Login()
{
IRatsServiceCallback callback = OperationContext.Current.GetCallbackChannel<IRatsServiceCallback>();
if (!callBackList.Contains(callback))
{
callBackList.Add(callback);
}
}
public void Logout()
{
IRatsServiceCallback callback = OperationContext.Current.GetCallbackChannel<IRatsServiceCallback>();
if (callBackList.Contains(callback))
{
callBackList.Remove(callback);
}
callback.NotifyClient("You are Logged out");
}
public void LogMessages(string Message)
{
foreach (IRatsServiceCallback callback in callBackList)
callback.NotifyClient(Message);
}
Service Interface
[ServiceContract(Name = "IRatsService", SessionMode = SessionMode.Allowed, CallbackContract = typeof(IRatsServiceCallback))]
public interface IRatsService
{
[OperationContract]
void Login();
[OperationContract]
void Logout();
[OperationContract]
void LogMessages(string message);
// TODO: Add your service operations here
}
public interface IRatsServiceCallback
{
[OperationContract]
void NotifyClient(String Message);
}
App.config:
<system.serviceModel>
<services>
<service name="RatsWcf.RatsService">
<endpoint address="" binding="wsDualHttpBinding" contract="RatsWcf.IRatsService">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/Design_Time_Addresses/RatsWcf/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
Just wondering what could be wrong here.

There's nothing wrong. The WCF Test Client is a tool which can be used to test many types of WCF services, but not all of them - duplex contracts being one category which is not supported. You'll need to create some sort of client app to test that. In your client app you'll need to write a class which implements the callback interface, so that it can receive the messages initiated by the service.
For example, this is a very simple duplex client / service which uses WCF duplex:
public class DuplexTemplate
{
[ServiceContract(CallbackContract = typeof(ICallback))]
public interface ITest
{
[OperationContract]
string Hello(string text);
}
[ServiceContract(Name = "IReallyWantCallback")]
public interface ICallback
{
[OperationContract(IsOneWay = true)]
void OnHello(string text);
}
public class Service : ITest
{
public string Hello(string text)
{
ICallback callback = OperationContext.Current.GetCallbackChannel<ICallback>();
ThreadPool.QueueUserWorkItem(delegate
{
callback.OnHello(text);
});
return text;
}
}
class MyCallback : ICallback
{
AutoResetEvent evt;
public MyCallback(AutoResetEvent evt)
{
this.evt = evt;
}
public void OnHello(string text)
{
Console.WriteLine("[callback] OnHello({0})", text);
evt.Set();
}
}
public static void Test()
{
string baseAddress = "net.tcp://" + Environment.MachineName + ":8000/Service";
ServiceHost host = new ServiceHost(typeof(Service), new Uri(baseAddress));
host.AddServiceEndpoint(typeof(ITest), new NetTcpBinding(SecurityMode.None), "");
host.Open();
Console.WriteLine("Host opened");
AutoResetEvent evt = new AutoResetEvent(false);
MyCallback callback = new MyCallback(evt);
DuplexChannelFactory<ITest> factory = new DuplexChannelFactory<ITest>(
new InstanceContext(callback),
new NetTcpBinding(SecurityMode.None),
new EndpointAddress(baseAddress));
ITest proxy = factory.CreateChannel();
Console.WriteLine(proxy.Hello("foo bar"));
evt.WaitOne();
((IClientChannel)proxy).Close();
factory.Close();
Console.Write("Press ENTER to close the host");
Console.ReadLine();
host.Close();
}
}

Related

C# windows service - expose web interface

I have created a web service that exposes web interface.
the service run in console mode and i see the web interface
public ServiceHost serviceHost = null; public ServiceHost serviceHost = null;;
private readonly TestService s;
public Service()
{
InitializeComponent();
s = new TestService();
}
protected override void OnStart(string[] args)
{
Logger.Info("Start event");
if (serviceHost != null)
{
serviceHost.Close();
}
// Create a ServiceHost for the CalculatorService type and
// provide the base address.
string baseAddress = "http://localhost:8000/Service";
serviceHost = new ServiceHost(typeof(Service1), new System.Uri(baseAddress));
serviceHost.AddServiceEndpoint(typeof(WindowsServiceTemplate.IService1),
new BasicHttpBinding(), baseAddress);
// Check to see if the service host already has a ServiceMetadataBehavior
ServiceMetadataBehavior smb = serviceHost.Description.Behaviors.Find<ServiceMetadataBehavior>();
// If not, add one
if (smb == null)
smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
serviceHost.Description.Behaviors.Add(smb);
// Add MEX endpoint
serviceHost.AddServiceEndpoint(
ServiceMetadataBehavior.MexContractName,
MetadataExchangeBindings.CreateMexHttpBinding(),
"mex"
);
// Open the ServiceHostBase to create listeners and start
// listening for messages.
serviceHost.Open();
s.Start();
}
protected override void OnStop()
{
Logger.Info("Stop event");
if (serviceHost != null)
{
serviceHost.Close();
serviceHost = null;
}
s.Stop();
}
protected override void OnShutdown()
{
Logger.Info("Windows is going shutdown");
Stop();
}
public void Start()
{
OnStart(null);
}
}
}
and app.config file :
<system.serviceModel>
<services>
<!-- Note: the service name must match the configuration name for the service implementation. -->
<service name="WindowsServiceTemplate.IService1" behaviorConfiguration="MyServiceTypeBehaviors" >
<!-- Add the following endpoint. -->
<!-- Note: your service must have an http base address to add this endpoint. -->
<endpoint contract="IMetadataExchange" binding="mexHttpBinding" address="mexHttpBinding" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MyServiceTypeBehaviors" >
<!-- Add the following element to your service behavior configuration. -->
<serviceMetadata httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
the configuration file inside app.config (console application project)
i am able to access
http://localhost:8000/Service
but when i try to call the test method
http://localhost:8000/Service/test
i get 404 error.
what am i missing?
Use Webhttpbinding to create the service and webservicehost to host service. I have made a demo, wish it is useful to you.
public partial class Service1 : ServiceBase
{
ServiceHost sh = new ServiceHost(typeof(MyService), new Uri("http://localhost:5900"));
public Service1()
{
InitializeComponent();
}
protected override void OnStart(string[] args)
{
if (sh.State==CommunicationState.Opened)
{
Log("Service open Fail");
}
else
{
WebHttpBinding webHttpBinding = new WebHttpBinding();
ServiceEndpoint se = sh.AddServiceEndpoint(typeof(IService), webHttpBinding, "");
se.EndpointBehaviors.Add(new WebHttpBehavior());
sh.Open();
Log("Service is ready....");
}
}
protected override void OnStop()
{
if (sh.State==CommunicationState.Opened)
{
sh.Close();
Log("Service closed successfully");
}
}
private void Log(string text)
{
using (StreamWriter sw=new StreamWriter(#"D:\log.txt",true))
{
sw.WriteLine($"{text}----Time:{DateTime.Now.ToShortTimeString()}");
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
[WebGet]
string SayHello();
}
public class MyService : IService
{
public string SayHello()
{
return "Hello Stranger";
}
}
}
Install.
Result.
Here is an official document.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/how-to-create-a-basic-wcf-web-http-service
Feel free to let me know if there is anything I can help with.

Cannot add server reference: Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it

I am making a WCF Service application on localhost and am having trouble with adding a service reference to a client application (in the same Visual Studio solution)
I am getting an error which says: "Contract requires Duplex, but Binding 'BasicHttpBinding' doesn't support it or isn't configured properly to support it." when I try to add the service reference. I am also able to start the service and it opens my browser automatically. From that point clicking on ScadaService.svc shows the same error.
When I change the service name to [ProjectName].ScadaService I get a different error, which says that there is no endpoint listening at 'http://localhost:11303/ScadaService.svc/$metadata'.
I have pasted my entire code in a new project class by class with no success.
The only contract that doesn't have a callback function has basicHttpBinding and changing it to wsDualHttpBinding does not work.
Web.config file
<?xml version="1.0"?>
<configuration>
<appSettings>
<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true" />
</appSettings>
<system.web>
<compilation debug="true" targetFramework="4.6.1" />
<httpRuntime targetFramework="4.6.1"/>
</system.web>
<system.serviceModel>
<services>
<service name="Service1">
<endpoint address="RealTimeUnit" binding="basicHttpBinding" contract="Commons.ServiceContracts.IRTUService"/>
<endpoint address="RealTimeUnit/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="DatabaseManager" binding="wsDualHttpBinding" contract="Commons.ServiceContracts.IDatabaseService"/>
<endpoint address="DatabaseManager/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="Trending" binding="wsDualHttpBinding" contract="Commons.ServiceContracts.ITrendingService"/>
<endpoint address="Trending/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="AlarmDisplay" binding="wsDualHttpBinding" contract="Commons.ServiceContracts.IAlarmService"/>
<endpoint address="AlarmDisplay/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- 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>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
<!--
To browse web app root directory during debugging, set the value below to true.
Set to false before deployment to avoid disclosing web app folder information.
-->
<directoryBrowse enabled="true"/>
</system.webServer>
</configuration>
Service contracts:
[ServiceContract(CallbackContract = typeof(IAlarmCallback))]
public interface IAlarmService
{
[OperationContract]
void AlarmInit();
}
[ServiceContract]
public interface IAlarmCallback
{
[OperationContract(IsOneWay = true)]
void RaiseAlarm(Tag tag, double value);
}
[ServiceContract(CallbackContract = typeof(IDatabaseCallback))]
public interface IDatabaseService
{
[OperationContract]
void DatabaseInit();
[OperationContract]
void AddSimulationUnit(int address, SignalType signalType, int scanPeriod);
[OperationContract]
void RemoveSimulationUnit(int index);
[OperationContract]
void AddTag(Tag tag);
[OperationContract]
void ModifyTag(string tagId, Tag newTag);
[OperationContract]
void RemoveTag(string tagId);
}
[ServiceContract]
public interface IDatabaseCallback
{
[OperationContract(IsOneWay = true)]
void GetTags(List<Tag> tags);
[OperationContract(IsOneWay = true)]
void TagAdded(Tag tag);
[OperationContract(IsOneWay = true)]
void TagModified(string tagId, Tag newTag);
[OperationContract(IsOneWay = true)]
void TagRemoved(string tagId);
}
[DataContract]
public enum SignalType
{
[EnumMember] Sine,
[EnumMember] Cosine,
[EnumMember] Ramp,
[EnumMember] Triangular,
[EnumMember] Rectangular,
[EnumMember] Digital
}
[ServiceContract]
public interface IRTUService
{
[OperationContract]
void RTUInit(string iD, string publicKeyPath);
[OperationContract]
void RTUDelete(string iD, byte[] signature);
[OperationContract]
void RTScan(int address, double value, string iD, byte[] signature);
}
[ServiceContract(CallbackContract = typeof(ITrendingCallback))]
public interface ITrendingService
{
[OperationContract]
void InitTrending();
}
[ServiceContract]
public interface ITrendingCallback
{
[OperationContract(IsOneWay = true)]
void GetTags(List<Tag> tags);
[OperationContract(IsOneWay = true)]
void TagAdded(Tag tag);
[OperationContract(IsOneWay = true)]
void TagModified(string tagId, Tag newTag);
[OperationContract(IsOneWay = true)]
void TagRemoved(string tagId);
[OperationContract(IsOneWay = true)]
void NewScan(string tagId, double value);
}
Not sure whether it could help, but the only problem I meet with your code is that duplicate OperationName. I couldn't reproduce your problem, after I change the OperationName , I could add reference to the service.
In addition, I remove your enum type SignalType and replace it with int.
Below is my contract.
[DataContract]
public class Tag
{
[DataMember]
public string Name { get; set; }
}
[ServiceContract(CallbackContract = typeof(IAlarmCallback))]
public interface IAlarmService
{
[OperationContract]
void AlarmInit();
}
[ServiceContract]
public interface IAlarmCallback
{
[OperationContract(IsOneWay = true)]
void RaiseAlarm(Tag tag, double value);
}
[ServiceContract(CallbackContract = typeof(IDatabaseCallback))]
public interface IDatabaseService
{
[OperationContract]
void DatabaseInit();
[OperationContract]
void AddSimulationUnit(int address, int signalType, int scanPeriod);
[OperationContract]
void RemoveSimulationUnit(int index);
[OperationContract]
void AddTag(Tag tag);
[OperationContract]
void ModifyTag(string tagId, Tag newTag);
[OperationContract]
void RemoveTag(string tagId);
}
[ServiceContract]
public interface IDatabaseCallback
{
[OperationContract(IsOneWay = true)]
void GetTags(List<Tag> tags);
[OperationContract(IsOneWay = true)]
void TagAdded(Tag tag);
[OperationContract(IsOneWay = true)]
void TagModified(string tagId, Tag newTag);
[OperationContract(IsOneWay = true)]
void TagRemoved(string tagId);
}
[ServiceContract]
public interface IRTUService
{
[OperationContract]
void RTUInit(string iD, string publicKeyPath);
[OperationContract]
void RTUDelete(string iD, byte[] signature);
[OperationContract]
void RTScan(int address, double value, string iD, byte[] signature);
}
[ServiceContract(CallbackContract = typeof(ITrendingCallback))]
public interface ITrendingService
{
[OperationContract]
void InitTrending();
}
[ServiceContract]
public interface ITrendingCallback
{
[OperationContract(IsOneWay = true,Name = "TrendGetTags")]
void GetTags(List<Tag> tags);
[OperationContract(IsOneWay = true, Name = "TrendTagAdd")]
void TagAdded(Tag tag);
[OperationContract(IsOneWay = true, Name = "TrendTagModified")]
void TagModified(string tagId, Tag newTag);
[OperationContract(IsOneWay = true, Name = "TrendTagRemoved")]
void TagRemoved(string tagId);
[OperationContract(IsOneWay = true, Name = "TrendNewScan")] // change the operation name
void NewScan(string tagId, double value);
}
My service is empty.
public class ScadaService : IRTUService,IDatabaseService,ITrendingService,IAlarmService
{
public void AddSimulationUnit(int address, int signalType, int scanPeriod)
{
}
// ignore other method
}
My svc
<%# ServiceHost Language="C#" Debug="true" Service="Service.callback.ScadaService" %>
My web.config.The same Metaservicebehavior with yours
<service name="Service.callback.ScadaService">
<endpoint address="RealTimeUnit" binding="basicHttpBinding" contract="ServiceInterface.callback.IRTUService"/>
<endpoint address="RealTimeUnit/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="DatabaseManager" binding="wsDualHttpBinding" contract="ServiceInterface.callback.IDatabaseService"/>
<endpoint address="DatabaseManager/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="Trending" binding="wsDualHttpBinding" contract="ServiceInterface.callback.ITrendingService"/>
<endpoint address="Trending/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<endpoint address="AlarmDisplay" binding="wsDualHttpBinding" contract="ServiceInterface.callback.IAlarmService"/>
<endpoint address="AlarmDisplay/Mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
</service>

Can I get/set data into WCF Service by Host?

I have WCF Service hosted on WindowsServiceHost (to communicate WindowsFormsApp <> WindowsServiceHost)
Is there any way get data from WCFService to WindowsServiceHost?
And in other way (set data from WindowsServiceHost to WCFService)
That is what have i done:
I've made a project of WCF Service Library, implemented interface, contracts etc.
I created new project - Windows service and added reference to project from #1 and to System.ServiceModel
Configured app.conf:
<system.serviceModel>
<bindings>
<netTcpBinding>
<binding name="netTcp">
<security mode="Message">
</security>
</binding>
</netTcpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="mexBehavior" name="KSPDJOBWinWCFService.KSPDJOBWinWCFService" >
<endpoint address="KSPDJOBWinWCFService" binding="netTcpBinding" contract="KSPDJOBWinWCFService.IKSPDJOBWinWCFService" bindingConfiguration="netTcp" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8079"/>
<add baseAddress="net.tcp://localhost:8090"/>
</baseAddresses>
</host>
</service>
</services>
I've hosted the WCF in OnStart method of Windows Service
protected override void OnStart(string[] args)
{
host = new ServiceHost(typeof(KSPDJOBWinWCFService.KSPDJOBWinWCFService));
host.Open();
}
Added new solution with WinformsClient app (as WCF Client) and tested communication - all working fine.
The problem is when i send a value from WinFormsClient to WCF Service, and want to read it from Windows Service aplication
Thanks for any Help.
You could hold the WCF service instance in a global variable and work with events. In this sample the WCF Service KSPDJOBWinWCFService exposes an event EventA and the Service Host will handle it. This is the place where you can process the values sent by your WCF Client.
public partial class Service : ServiceBase
{
private ServiceHost _host;
private KSPDJOBWinWCFService _instance;
protected override void OnStart(string[] args)
{
try
{
_instance = new KSPDJOBWinWCFService();
_instance.EventA += HandleEventA;
_host = new ServiceHost(_instance);
_host.Open();
}
catch (Exception ex)
{
// Logging
}
}
public void HandleEventA(object sender, CustomEventArgs e)
{
// do whatever you want here
var localVar = e.Value;
}
protected override void OnStop()
{
try
{
if (_instance != null)
{
_instance.Dispose();
}
_host.Close();
}
catch (Exception ex)
{
// Logging
}
}
}
The WCF Service then fires this event together with the values sent from the WCF client:
public class KSPDJOBWinWCFService : IKSPDJOBWinWCFService
{
public event EventHandler<CustomEventArgs> EventA;
public bool SomeWcfOperation(int value)
{
EventA?.Invoke(this, new CustomEventArgs(value));
return true;
}
}
Create event args that fulfill your needs:
public class CustomEventArgs : EventArgs
{
public int Value { get; set; }
public CustomEventArgs(int value)
{
Value = value;
}
}
You can also expose values with public properties in your WCF Service. But events are also necessary.

How to limit secure protocol in wcf service

I need to write WCF service using TLS 1.2.I need to use only this security protocol and (as i think) refuse connections with other secure protocol types. I have created certificate. Bind it to port. Https works well. I read everywhere that i need to write next string of code:
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
Ok, i wrote it, but had no effect. Service side code:
using System;
using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;
using System.Net;
using System.ServiceModel;
using System.Runtime.Serialization;
using static System.Console;
namespace ConsoleHost
{
public class DistributorValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (string.IsNullOrEmpty(userName) || string.IsNullOrEmpty(password))
throw new SecurityTokenException("Both username and password required");
if (userName != "login" || password != "pass")
throw new FaultException($"Wrong username ({userName}) or password ");
}
}
public class Service1 : IService1
{
public string GetData(int value)
{
return $"You entered: {value}";
}
public CompositeType GetDataUsingDataContract(CompositeType composite)
{
if (composite == null)
{
throw new ArgumentNullException(nameof(composite));
}
if (composite.BoolValue)
{
composite.StringValue += "Suffix";
}
return composite;
}
}
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
[OperationContract]
CompositeType GetDataUsingDataContract(CompositeType composite);
}
[DataContract]
public class CompositeType
{
[DataMember]
public bool BoolValue { get; set; } = true;
[DataMember]
public string StringValue { get; set; } = "Hello ";
}
class Program
{
static void Main(string[] args)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
ServiceHost host = new ServiceHost(typeof(Service1));
host.Open();
WriteLine("Press any key to stop server...");
ReadLine();
}
}
}
App.config contains:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<system.serviceModel>
<services>
<service name="ConsoleHost.Service1">
<host>
<baseAddresses>
<add baseAddress = "https://localhost:8734/Service1/" />
</baseAddresses>
</host>
<endpoint address="" binding="wsHttpBinding" contract="ConsoleHost.IService1" bindingConfiguration="securityBinding">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpsBinding" contract="IMetadataExchange"/>
</service>
</services>
<bindings>
<wsHttpBinding>
<binding name="securityBinding">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
<!--establishSecurityContext="false" />-->
</security>
</binding>
</wsHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="True" httpsGetEnabled="True"/>
<serviceDebug includeExceptionDetailInFaults="False" />
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="ConsoleHost.DistributorValidator,ConsoleHost"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
Client side code:
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Ssl3;
Service1Client client = new Service1Client();
client.ClientCredentials.UserName.UserName = "login";
client.ClientCredentials.UserName.Password = "pass";
Console.WriteLine(client.GetData(10));
}
catch (Exception ex)
{
Console.WriteLine("Exception: " + ex.Message);
if (ex.InnerException != null)
{
Console.WriteLine("Inner: " + ex.InnerException.Message);
if (ex.InnerException.InnerException != null)
Console.WriteLine("Inner: " + ex.InnerException.InnerException.Message);
}
}
Console.ReadLine();
}
}
}
As you can see on service side i have set security protocol to Tls 1.2. On client side i have set security protocol to Ssl3. I am waiting that service will refuse client connection, because server must work and accept clients who will work with only Tls 1.2 security protocol. But i'm not getting this result. Client connects and works well. What's the problem?
I understand that i can change some settings on IIS to use only Tls 1.2. But i am making self hosting wcf service and that's the problem.
It can't be done for server using ServicePointManager.SecurityProtocol option, that's used to connection to sth through a specific security protocol. You can't turn off some security protocol for an separate application, you able to allow or dissallow connections for whole server. If u want disable all protocols except TLS 1.2 u have to open registry windows and find out the next key:
HKLM\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols\
And set the next values for each protocol in key [Server]: DisabledByDefault = 1, Enabled = 0
How to enable TLS

WCF Error: The operation cannot be completed because the pipe was closed

I am getting an error when the client reference is used a second time for calling the underlying method. On first call, It works perfectly. I have googled it and did so many tries like setting timeouts but nothing worked. Any suggestions will be highly appreciated. Also, if more details are required please let me know, I will post the required code.
A MDI Child form will call this method.
Debugger shows CommunicationException.
Trace Viewer shows message: The operation cannot be completed because the pipe was closed. This may have been caused by the application on the other end of the pipe exiting.
Contract
[ServiceContract(Namespace = "http://Company/ManagementInformationSystemServices/", SessionMode = SessionMode.Required)]
public interface IPrincipalService
{
#region Service contracts for Reports
[OperationContract]
[FaultContract(typeof(ProcessExecutionFault))]
Parcel InsertParcel(Parcel singleParcel, out bool Exists);
[OperationContract]
[FaultContract(typeof(ProcessExecutionFault))]
Parcel GetByParcelId(int id);
#endregion
}
Contract Implementation
[ServiceBehavior(UseSynchronizationContext = false, ConcurrencyMode = ConcurrencyMode.Multiple, InstanceContextMode = InstanceContextMode.Single)]
public class PrincipalService : IPrincipalService
{
#region Constructor
public PrincipalService()
{
}
#endregion
#region Public Methods
#region Parcel Methods
public Parcel InsertParcel(Parcel singleParcel, out bool Exists)
{
bool ExistsInner = false;
try
{
ParcelComponent parcelComponent = new ParcelComponent();
singleParcel = parcelComponent.Insert(singleParcel, out ExistsInner);
Exists = ExistsInner;
return singleParcel;
}
catch (Exception ex)
{
throw new FaultException<ProcessExecutionFault>
(new ProcessExecutionFault(LogResource.InsertParcelExistsError, ex), ex.Message);
}
}
public Parcel GetByParcelId(int id)
{
try
{
ParcelComponent parcelComponent = new ParcelComponent();
return parcelComponent.GetById(id);
}
catch (Exception ex)
{
throw new FaultException<ProcessExecutionFault>
(new ProcessExecutionFault(LogResource.ReadParcelError, ex), ex.Message);
}
}
#endregion
#endregion
}
Server Configuration
<system.serviceModel>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
<services>
<service behaviorConfiguration="serviceBehavior" name="ManagementInformationSystem.Services.PrincipalService">
<host>
<baseAddresses>
<add baseAddress="net.pipe://localhost/ManagementInformationSystemServices" />
</baseAddresses>
</host>
<endpoint address="PrincipalService"
binding="netNamedPipeBinding"
contract="ManagementInformationSystem.Services.Contracts.IPrincipalService" />
<endpoint address="PrincipalService/mex"
binding="mexNamedPipeBinding"
contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</serviceBehaviors>
</behaviors>
<diagnostics wmiProviderEnabled="true">
</diagnostics>
Client Configuration
<system.serviceModel>
<bindings>
<netNamedPipeBinding>
<binding name="NetNamedPipeBinding_IPrincipalService" />
</netNamedPipeBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="endpointBehavior">
<dataContractSerializer maxItemsInObjectGraph="2147483647"/>
</behavior>
</endpointBehaviors>
</behaviors>
<client>
<endpoint address="net.pipe://localhost/ManagementInformationSystemServices/PrincipalService"
binding="netNamedPipeBinding" bindingConfiguration="NetNamedPipeBinding_IPrincipalService"
contract="PrincipalServiceReference.IPrincipalService" name="NetNamedPipeBinding_IPrincipalService">
<identity>
<userPrincipalName value="company-238\company" />
</identity>
</endpoint>
</client>
<diagnostics wmiProviderEnabled="true">
</diagnostics>
Service Helper Class and I am getting Communication Exception here
public static class ServiceHelper<T>
{
public static ChannelFactory<T> _channelFactory = new ChannelFactory<T>(GlobalResource.PrincipalServiceEndPointName);
public static void Use(UseServiceDelegate<T> codeBlock)
{
IClientChannel proxy = (IClientChannel)_channelFactory.CreateChannel();
bool success = false;
try
{
codeBlock((T)proxy);
proxy.Close();
success = true;
}
catch (CommunicationException ex)
{
throw ex;
}
catch (TimeoutException ex)
{
throw ex;
}
finally
{
if (!success)
{
proxy.Abort();
}
}
}
}

Categories

Resources