I would like to write an automated regression test whereby my service is started and I can assert that my client can retrieve some things from the service.
Private Blah proxy;
[SetUp]
public void SetUp()
{
proxy= new Blah();
}
[Test]
public void GetStuff()
{
var result = proxy.GetStuff();
Assert.NotNull(result);
}
This doesn't work because my service isn't running. How would I make start my service before the tests?
For integration/acceptance testing of WCF services I suggest you to use Self Hosted WCF Service. Examples you can find here:
Creating a Self Hosted WCF Service
Self Hosting Windows Communication Foundation Services
Create self-hosted service on fixture setup, and close it on fixture tear down:
EndpointAddress address = new EndpointAddress("http://localhost:8080/service1");
ServiceHost host;
IService1 service;
[TestFixtureSetUp]
public void FixtureSetUp()
{
var binding = new BasicHttpBinding();
host = new ServiceHost(typeof(Service1), address.Uri);
host.AddServiceEndpoint(typeof(IService1), binding, address.Uri);
host.Open();
}
[TestFixtureTearDown]
public void FixtureTearDown()
{
if (host == null)
return;
if (host.State == CommunicationState.Opened)
host.Close();
else if (host.State == CommunicationState.Faulted)
host.Abort();
}
With service hosted you can get service proxy:
var binding = new BasicHttpBinding();
ChannelFactory<IService1> factory =
new ChannelFactory<IService1>(binding, address);
service = factory.CreateChannel();
And your test will look like:
[Test]
public void ShouldReturnSomeStuff()
{
var result = service.GetStuff();
Assert.NotNull(result);
}
Related
What is the problem: System.TimeoutException: 'The request channel timed out while waiting for a reply after 00:00:59.977913. So, basically it can be everything.
What do I have:
I create a simple solution to found a fix. What really make me confused is that console app works just fine, however wpf app with same configuration does not work. Solution include four projects(code made for debugging purpose, please don't judge it):
library with contracts and their implementation.
public class DeviceService : IDeviceService
{
public string GetDevices()
{
return "hello world";
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
library with host.
public class DeviceServiceHostFactory
{
ServiceHost host;
public DeviceServiceHostFactory()
{
ServiceMetadataBehavior metadataBehavior;
BasicHttpBinding binding = new BasicHttpBinding();
Uri address = new Uri("http://localhost:4000/");
host = new ServiceHost(typeof(DeviceService), address);
Type contract = typeof(IDeviceService);
host.AddServiceEndpoint(contract, binding, "");
}
public void Start()
{
host.Open();
}
public void Stop()
{
host.Close();
}
}
desktop app that start service and consume it (does not work)
public partial class MainWindow : Window
{
private DeviceServiceHostFactory _deviceService;
public MainWindow()
{
InitializeComponent();
try
{
_deviceService = new DeviceServiceHostFactory();
_deviceService.Start();
}
catch (Exception ex)
{
_deviceService.Stop();
Console.WriteLine(ex.StackTrace);
}
}
private void Btn_custom_Click(object sender, RoutedEventArgs e)
{
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint =
new EndpointAddress("http://localhost:4000/");
var factory =
new ChannelFactory<IDeviceService>(
binding, endpoint);
var channel = factory.CreateChannel();
txt_custom.Text = channel.GetDevices();
Console.WriteLine();
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
console app (works fine)
class Program
{
static void Main(string[] args)
{
DeviceServiceHostFactory _deviceService = new
DeviceServiceHostFactory();
try
{
_deviceService.Start();
BasicHttpBinding binding = new BasicHttpBinding();
EndpointAddress endpoint =
new EndpointAddress("http://localhost:4000/");
var factory =
new ChannelFactory<IDeviceService>(
binding, endpoint);
var channel = factory.CreateChannel();
Console.WriteLine(channel.GetDevices());
Console.ReadLine();
}
catch (Exception ex)
{
_deviceService.Stop();
Console.WriteLine(ex.StackTrace);
}
}
}
[ServiceContract]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
I really spend a lot of time for this, and I will be very grateful for every solution or thought how can I debug it more advanced.
Hosting wcf service in application with UI is little bit tricky, so I hope this will help someone.
Took it from book Learning WCF: A hands-On Guide By Michele Leroux Bustamante, Chapter 4, so fo more information please find this book.
To host service in Windows application or WPF application, we have to create a new thread to start it in a new synchronization context. It can be done in two ways:
First, is to create service host before the UI thread created. Here service executes in a new synchronization contenxt before application starts.
static class Program
{
static void Main()
{
DeviceServiceHostFactory deviceService = new DeviceServiceHostFactory();
deviceService.Start();
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new MainWindow);
}
}
Second, is to initialize service host on a separate thread, after UI been created
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Thread thread;
thread = new Thread(ServiceInitialize);
thread.IsBackground = true;
thread.Start();
}
private void ServiceInitialize()
{
var service = new DeviceServiceHostFactory();
service.Start();
}
}
This means the messages are processed on threads form the thread pool instead of through the message loop.
First, we should give the current account permissions when we occupy the Operation system ports to host services.
This function could be accomplished by the below command.
Netsh http add urlacl url=https://+:80/MyUri user=DOMAIN\user
https://learn.microsoft.com/en-us/windows/win32/http/add-urlacl
If we don’t want to do this, we could directly run the service with administrator accounts.
Thereby I suspect there is something wrong with the process of hosting the service. Have you tried running the WPF application with an administrator account?
Besides, I suggest you add a namespace in the service contract.
[ServiceContract(Namespace ="MyNamespace")]
public interface IDeviceService
{
[OperationContract]
string GetDevices();
}
Sometimes, it could run into problems when the service contract doesn’t have a namespace property.
Feel free to let me know if the problem still exists.
Here is a simple Service Fabric stateless service with WCF communication and it's client - a console app. It works well on the local cluster, client gets responce from the service. But I don't know how to communicate with a service if I deploy it in the cloud. What should I do to access it from console app?
SF Stateless service with WCF communications:
Contract:
[ServiceContract]
public interface IPresidentialService
{
[OperationContract]
Task<string> GetInfo();
}
Service:
internal sealed class PresidentialService : StatelessService, IPresidentialService
{
public PresidentialService(StatelessServiceContext context) : base(context)
{
}
public Task<string> GetInfo() => Task.FromResult($"Node {Context.NodeContext.NodeName} operating");
protected override IEnumerable<ServiceInstanceListener> CreateServiceInstanceListeners()
{
return new[]
{
new ServiceInstanceListener(context =>
new WcfCommunicationListener<IPresidentialService>(wcfServiceObject: this, serviceContext: context,
endpointResourceName: "WcfServiceEndpoint",
listenerBinding: WcfUtility.CreateTcpListenerBinding()))
};
}
}
}
Client console app:
WCF client:
public class PresidentialServiceClient : ServicePartitionClient<WcfCommunicationClient<IPresidentialService>>
{
public PresidentialServiceClient(
ICommunicationClientFactory<WcfCommunicationClient<IPresidentialService>> communicationClientFactory,
Uri serviceUri, ServicePartitionKey partitionKey = null,
TargetReplicaSelector targetReplicaSelector = TargetReplicaSelector.Default, string listenerName = null,
OperationRetrySettings retrySettings = null) : base(communicationClientFactory, serviceUri, partitionKey,
targetReplicaSelector, listenerName, retrySettings)
{
}
public Task<string> GetInfo() => InvokeWithRetryAsync(client => client.Channel.GetInfo());
}
Client App:
private static void Main(string[] args)
{
var binding = WcfUtility.CreateTcpClientBinding();
var partitionResolver = ServicePartitionResolver.GetDefault();
var wcfClientFactory =
new WcfCommunicationClientFactory<IPresidentialService>(binding,
servicePartitionResolver: partitionResolver);
var serviceUri = new Uri("fabric:/Application5/PresidentialService");
var client = new PresidentialServiceClient(wcfClientFactory, serviceUri, ServicePartitionKey.Singleton);
do
{
Console.WriteLine(client.GetInfo().Result);
Console.ReadKey();
} while (true);
}
Added to ServiceManifest.xml:
<Endpoints>
<Endpoint Name="WcfServiceEndpoint" />
</Endpoints>
UPDATE
Changed ServicePartitionResolver:
var partitionResolver = new ServicePartitionResolver("sfapp.westeurope.cloudapp.azure.com:19000");
Still not works.
UPDATE
Added a load balancer rule for TCP port 777.
When the service is running in the cloud, you can't use the default resolver.
The default ServicePartitionResolver assumes that the client is
running in same cluster as the service. If that is not the case,
create a ServicePartitionResolver object and pass in the cluster
connection endpoints.
Try something like
ServicePartitionResolver resolver = new ServicePartitionResolver("mycluster.cloudapp.azure.com:19000");
https://learn.microsoft.com/en-us/azure/service-fabric/service-fabric-reliable-services-communication-wcf
I've a Duplex TCP IP WCF service. I'm currently unit-testing it.
In everyone of my test, I setup a new server, create a new ChannelFactory, create the InstanceContext and do the call.
Then I trigger the event(it's a Mock on the server side), and the server give me this exception when it tries to reach the client:
Exception thrown: 'System.ObjectDisposedException' in mscorlib.dll
Additional information: Cannot access a disposed object.
Important point, this happens ONLY when I run all the tests in a row(sequentially executed but in the same execution).
There is nothing special about my service:
[ServiceContract(SessionMode = SessionMode.Required, CallbackContract = typeof(IMyServiceCallback))]
public interface IMyService{
[OperationContract]
void SomeVariousMethods();
}
[ServiceContract]
public interface IMyServiceCallback
{
[OperationContract]
void HandleMessageFromServer(String message);
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService{
public MyService(ISomeServerComponent component){
component.OnMessage += OnMessageReceived;
}
public void SomeVariousMethods(){
//...
}
private void OnMessageReceived(object sender, EventArgs<String> e){
IMyServiceCallback callback = OperationContext.Current.GetCallbackChannel<IMyServiceCallback>();
callBack.HandleMessageFromServer(e.Data);//Crash here
}
}
And here is how I'm currently UnitTesting it(not exactly, I've a lot of this that has been extracted in some helpers:
[TestFixture]
public class MyServiceTest:IMyServiceCallback{
private Mock<ISomeServerComponent> _mock;
[OneTimeSetUp]
public void Setup(){
//... Creating a mock for the ISomeServerComponent that the MyService receives
}
[Test]
public void TestSomeVariousMethods(){
string serviceName = nameof(TestSomeVariousMethods);
using(ServiceHost host = CreateServer(_mock.Object,serviceName)){
using (IMyService service = CreateClient(serviceName, this)){
service.SomeVariousMethods();
}
}
}
[Test]
public void TestCallback(){
string serviceName = nameof(TestSomeVariousMethods);
using(ServiceHost host = CreateServer(_mock.Object,serviceName)){
using (IMyService service = CreateClient(serviceName, this)){
_mock.TriggerCallBack();
//Assert-that-the-flag-has-been-set
}
}
}
public void HandleMessageFromServer(String msg){
//Flag that this method has been called
}
private ServiceHost CreateServer(ISomeServerComponent mock, string serviceName){
UnityServiceHost serviceHost = new UnityServiceHost(m_container);//This extends ServiceHost to be able to inject some objects to my services
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ReliableSession.Enabled = true;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.MaxBufferPoolSize = Int64.MaxValue;
binding.MaxBufferSize = Int32.MaxValue;
binding.MaxReceivedMessageSize = Int32.MaxValue;
Uri uri = new Uri(String.Format("net.tcp://{0}:{1}/{2}", IPAddress.Any, 9999, serviceName));
ServiceEndpoint serviceEndpoint = new ServiceEndpoint(ContractDescription.GetContract(typeof(IMyService)), binding, uri);
serviceEndpoint.EndpointBehaviors.Add(new ProtoEndpointBehavior());
serviceHost.AddServiceEndpoint(serviceEndpoint);
return serviceHost;
}
private IMyService CreateClient(string serviceName, IMyServiceCallback callback){
UnityServiceHost serviceHost = new UnityServiceHost(m_container);//This extends ServiceHost to be able to inject some objects to my services
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
binding.ReliableSession.Enabled = true;
binding.Security.Transport.ClientCredentialType = TcpClientCredentialType.None;
binding.MaxBufferPoolSize = Int64.MaxValue;
binding.MaxBufferSize = Int32.MaxValue;
binding.MaxReceivedMessageSize = Int32.MaxValue;
Uri uri = new Uri(String.Format("net.tcp://{0}:{1}/{2}", IPAddress.Loopback, 9999, serviceName));
InstanceContext context = new InstanceContext(callBack);
DuplexChannelFactory channelFactory = new DuplexChannelFactory<T>(context, binding, new EndpointAddress(uri));
return channelFactory.CreateChannel()
}
}
Funny part is that all of this works when I'm ONLY running TestCallback test, but if I run all the test of the class, it fails, like if the second time, the InstanceContext was not creating properly the callback.
Any idea how to avoid this?
I finally found the issue. I feel a little bit stupid, but in fact, in the Service implementation, I was not unregistering from the OnMessage correctly, so when the event was triggered, the previous service instance were trying to communicate with the already closed client.
Hi I'm trying to get dependency injection to work using Castle Windsor in a console app to host WCF service in Azure using the example in:
https://azure.microsoft.com/en-gb/documentation/articles/service-bus-dotnet-how-to-use-relay/
My WCF service works fine using Castle Windsor (Small sample):
public class PersonService : IPersonService
{
private readonly IPersonManager _personManager;
public PersonService(IPersonManager personManager)
{
_personManager = personManager;
}
public Message Create(Person person)
{
Message result = _ personManager.Create(person);
}
}
Castle Windsor (in wcf service Global.asax)
private void BuildWindsorContainer ()
{
var container = new WindsorContainer();
container.Kernel.AddFacility<WcfFacility>();
container.Kernel.Register(
Component.For< IPersonManager >().ImplementedBy<PersonManager >(),
Component.For<IPersonService>()
.ImplementedBy<PersonService>()
.Named("WebS.PersonService"),
);
}
In My hosted Client which calls the WCF service I have:
private static ServiceHost CallPersonService()
{
BuildWindsorContainer ();
var sh = new ServiceHost(typeof (PersonService));
sh.AddServiceEndpoint(typeof (IPersonService), new NetTcpBinding(), "net.tcp://localhost:37050/person");
sh.AddServiceEndpoint(typeof (IPersonService), new NetTcpRelayBinding(),
ServiceBusEnvironment.CreateServiceUri("sb", ServiceNamespace, "person"))
.Behaviors.Add(new TransportClientEndpointBehavior
{
TokenProvider =
TokenProvider.CreateSharedAccessSignatureTokenProvider("RootManageSharedAccessKey", Key)
});
private void BuildWindsorContainer ()
{
var container = new WindsorContainer();
container.Kernel.AddFacility<WcfFacility>();
container.Kernel.Register(
Component.For< IPersonManager >().ImplementedBy<PersonManager >(),
Component.For<IPersonService>()
.ImplementedBy<PersonService>()
.Named("WebS.PersonService"),
);
}
How do I get the dependencies to be injected into service from the client?
var sh = new ServiceHost(typeof (PersonService));
sh.AddServiceEndpoint(typeof (IPersonService), new NetTcpBinding(), "net.tcp://localhost:37050/person");
IPersonManager is null in service when the client runs.
Try
var sh = (ServiceHost)new DefaultServiceHostFactory()
.CreateServiceHost(typeof(PersonService).AssemblyQualifiedName, new Uri[] { });
This question already has answers here:
Run WCF ServiceHost with multiple contracts
(8 answers)
Closed 9 years ago.
Is it possible to host multiple service contracts in one WCF service? If so, how? I've been googling and some posts say you can do it (but not how) and others have said it's just not possible.
When I run the server, I get this error:
The contract name 'ConsoleAppWcfCommon.IBarService' could not be found
in the list of contracts implemented by the service
'ConsoleAppWcfServer.FooService'.
This is my server code:
static void Main(string[] args)
{
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
// I'm stuck here as I have to pick *one* service
ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));
// I can add both endpoints here, but this is what gives me the error.
selfServiceHost.AddServiceEndpoint(typeof(IFooService), new NetTcpBinding(), serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), new NetTcpBinding(), serviceAddress);
selfServiceHost.Open();
Console.ReadLine();
selfServiceHost.Close();
}
And this is the client code:
static void Main(string[] args)
{
NetTcpBinding netTcpBinding = new NetTcpBinding();
EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService");
// Call IFooService
var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress);
IFooService channelFoo = channelFactoryFoo.CreateChannel();
Debug.WriteLine(channelFoo.FooMethod1());
// Call IBarService
var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress);
IBarService channelBar = channelFactoryBar.CreateChannel();
Debug.WriteLine(channelBar.BarMethod1());
}
My goal is to let the client make a call to Foo (or Bar) and only see the methods available to each. In my real application, I have about 10 domain entities with about four operations on each. I'm trying not to have one interface with 40 methods in it. And I don't want to have to host 10 different WCF services to do this.
As marc_s pointed out, the answer was to have one service implementation class that implements both interfaces. Below is the full working code.
Server:
static void Main(string[] args)
{
string serviceAddress = "net.tcp://localhost:8088/FooBarService";
ServiceHost selfServiceHost = new ServiceHost(typeof(FooService));
// The endpoints need to share this binding.
var binding = new NetTcpBinding();
selfServiceHost.AddServiceEndpoint(typeof(IFooService), binding, serviceAddress);
selfServiceHost.AddServiceEndpoint(typeof(IBarService), binding, serviceAddress);
selfServiceHost.Open();
Console.WriteLine("The service is ready.");
Console.WriteLine("Press any key to terminate service.");
Console.WriteLine();
Console.ReadKey();
selfServiceHost.Close();
}
Client:
static void Main(string[] args)
{
NetTcpBinding netTcpBinding = new NetTcpBinding();
EndpointAddress endpointAddress = new EndpointAddress("net.tcp://localhost:8088/FooBarService");
// Call IFooService
var channelFactoryFoo = new ChannelFactory<IFooService>(netTcpBinding, endpointAddress);
IFooService channelFoo = channelFactoryFoo.CreateChannel();
Console.WriteLine(channelFoo.FooMethod1());
// Call IBarService
var channelFactoryBar = new ChannelFactory<IBarService>(netTcpBinding, endpointAddress);
IBarService channelBar = channelFactoryBar.CreateChannel();
Console.WriteLine(channelBar.BarMethod1());
Console.ReadKey();
}
Foo Contract:
[ServiceContract]
public interface IFooService
{
[OperationContract]
string FooMethod1();
[OperationContract]
string FooMethod2();
}
Bar Contract:
[ServiceContract]
public interface IBarService
{
[OperationContract]
string BarMethod1();
[OperationContract]
string BarMethod2();
}
Foo Service:
public class FooService : IFooService, IBarService
{
public string FooMethod1()
{
return "FooMethod1";
}
public string FooMethod2()
{
return "FooMethod2";
}
public string BarMethod1()
{
return "BarMethod1";
}
public string BarMethod2()
{
return "BarMethod2";
}
}