How to do WCF Hosting in a console app? - wcf

How do I host my WCF class library in a console app? I have a WCF service within a class library and I wanted to test the service outside my project with a test app.(I have to do it outside the project)

Create a simple console app, add a reference to your WCF service assembly, and then basically write these few lines:
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(Namespace.YourWCFService)))
{
host.Open();
Console.WriteLine("Service host running......");
foreach (ServiceEndpoint sep in host.Description.Endpoints)
{
Console.WriteLine(" endpoint {0} ({1})",
sep.Address, sep.Binding.Name);
}
Console.ReadLine();
host.Close();
}
}
All you do is instatiate a ServiceHost and pass it the type of a service (implementation) class, and then basically call .Open() on it.
The Console.ReadLine() just wait until someone presses ENTER and then terminates the service host.
That's all there is! (of course, you need to specify service address and bindings in a app.config for the service host console app for it to work)

You may create ServiceHost in your console application with your existing service contract (from your class library).
After the service is running, your test project can access your WCF Service as usual.

Consider using the WCF Service Host application: http://msdn.microsoft.com/en-us/library/bb552363.aspx
You can simply point the host to your service class library and configuration file and it will host your service for you.

Related

Call Service Fabric service from console application using WCF HTTPS endpoint

I have a service hosted in a Service Fabric cluster in Azure (not locally) and I'm trying to call a method in it using a console application on my local machine. Using WCF for communication, I have a HTTPS endpoint set up in my application on a specific port, and have configured load balancing rules for the port in the Azure portal. The cluster has 6 nodes and the application is the only one deployed on the cluster.
Have followed the ServiceFabric.WcfCalc on GitHub (link), which works on a local cluster using HTTP endpoints, but can't call a method on the service using HTTPS endpoints once it has been deployed. What do I need to do to get it working? Have tried following the example here but don't know how to configure this for HTTPS with a service on multiple nodes for a console application to access.
Thanks in advance.
EDIT Here's my client code which I am using to call the service method. I pass the fabric:/ URI into the constructor here.
public class Client : ServicePartitionClient<WcfCommunicationClient<IServiceInterface>>, IServiceInterface
{
private static ICommunicationClientFactory<WcfCommunicationClient<IServiceInterface>> communicationClientFactory;
static Client()
{
communicationClientFactory = new WcfCommunicationClientFactory<IServiceInterface>(
clientBinding: new BasicHttpBinding(BasicHttpSecurityMode.Transport));
}
public Client(Uri serviceUri)
: this(serviceUri, ServicePartitionKey.Singleton)
{ }
public Client(
Uri serviceUri,
ServicePartitionKey partitionKey)
: base(
communicationClientFactory,
serviceUri,
partitionKey)
{ }
public Task<bool> ServiceMethod(DataClass data)
{
try
{
//It hangs here
return this.InvokeWithRetry((c) => c.Channel.ServiceMethod(data));
}
catch (Exception)
{
throw;
}
}
}
When debugging my console application on my local machine, the application hangs on the InvokeWithRetry call which calls the method in my service in Service Fabric. The application does not throw any exceptions and does not return to the debugger in Visual Studio.
Make sure you run every service instance /replica with a unique url.
Make sure you call the WebHttpBinding constructor using WebHttpSecurityMode.Transport.
Make sure you register the url using the same port number (443 likely) as in you service manifest endpoint declaration.
Make sure the endpoint is configured as HTTPS.
The warning you see in Service Fabric is telling you that there is already another service registered to listen on port 443 on your nodes. This means that Service Fabric fails to spin up your service (since it throws an exception internally when it is trying to register the URL with http.sys). You can change the port for your service to something else that will not conflict with the existing service, e.g.:
<Resources>
<Endpoint Name="CalculatorEndpoint" Protocol="https" Type="Input" Port="44330" />
</Endpoints>
If you log in to Service Fabric Explorer on https://{cluster_name}.{region}.cloudapp.azure.com:19080 you should be able to see what other applications and services are running there. If you expand services all the way down to node you should be able to see the registered endpoints, including ports, for existing services.
Bonus
You can query the cluster using FabricClient for all registered endpoints
var fabricClient = new FabricClient();
var applicationList = fabricClient.QueryManager.GetApplicationListAsync().GetAwaiter().GetResult();
foreach (var application in applicationList)
{
var serviceList = fabricClient.QueryManager.GetServiceListAsync(application.ApplicationName).GetAwaiter().GetResult();
foreach (var service in serviceList)
{
var partitionListAsync = fabricClient.QueryManager.GetPartitionListAsync(service.ServiceName).GetAwaiter().GetResult();
foreach (var partition in partitionListAsync)
{
var replicas = fabricClient.QueryManager.GetReplicaListAsync(partition.PartitionInformation.Id).GetAwaiter().GetResult();
foreach (var replica in replicas)
{
if (!string.IsNullOrWhiteSpace(replica.ReplicaAddress))
{
var replicaAddress = JObject.Parse(replica.ReplicaAddress);
foreach (var endpoint in replicaAddress["Endpoints"])
{
var endpointAddress = endpoint.First().Value<string>();
Console.WriteLine($"{service.ServiceName} {endpointAddress} {endpointAddress}");
}
}}}}}
Just run that with the proper FabricClient credentials (if it is a secured cluster) and you should see it listing all endpoints for all services there. That should help you find the one that has an endpoint for :443

Can't get WCF service to send XML Document to BizTalk Receive Location

I'm new to BizTalk and WCF services and am trying to figure out how to use a WCF service to deliver XML data to Biztalk. I think I'm close but when I call the WCF service operation, the operation executes successfully but does not appear to generate any kind of a message in Biztalk. Am I wrong in assuming that simply calling an operation is enough to trigger a message to BizTalk?
Below is my code and some details about my BizTalk configuration:
WCF service:
public interface IService1
{
[OperationContract, XmlSerializerFormat]
XmlDocument GetXMLDocument(string sourceXML);
}
public class Service1 : IService1
{
public XmlDocument GetXMLDocument(string sourceXML)
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(sourceXML);
return doc;
}
}
Calling application (button click calls the service):
protected void Button2_Click(object sender, EventArgs e)
{
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateNode(XmlNodeType.Element, "Patients", "test"));
SendDoc(doc);
}
protected void SendDoc(XmlDocument doc)
{
//use a Service Client Object to call the service
objServiceClientobjService.GetXMLDocument(doc.OuterXml);
}
BizTalk configuration:
Receive Port:
Port type: One-Way
Receive Location:
Type: WCF-Custom with basicHTTP binding
Endpoint Address is the same as the IIS hosted WCF Service
Receive Pipeline Type: XMLReceive
Your implementation is not correct. There is no link between your WCF service and BizTalk. If you want to receive xml in BizTalk then you need to expose either an Orchestration or Xml Schema as WCF service using BizTalk WCF Web Service Publishing Wizard. This gets installed with BizTalk. Please see link for more details: msdn link
The solution I always use, is to expose an endpoint. Take a look at this example:

Hosting WCF service on linux

Is there Any way of hosting WCF service on Linux.
I read about wine but i didn't see any example of hosting WCF service with it.
P.S : I have tried mono and mod_mono but to no avail.
You can host it in a stand-alone console application like so:
using System;
using System.ServiceModel;
using Service;
namespace Host
{
class MainClass
{
public static void Main (string[] args)
{
Console.WriteLine ("WCF Host!");
var binding = new BasicHttpBinding ();
var address = new Uri ("http://localhost:8080");
var host = new ServiceHost (typeof(GreeterWcfService));
host.AddServiceEndpoint (
typeof(IGreeterWcfService), binding, address);
host.Open ();
Console.WriteLine ("Type [Enter] to stop...");
Console.ReadLine ();
host.Close ();
}
}
}
Where GreeterWcfService is the WCF service class itself and IGreeterWcfService is the service contract.
Full working example solution in GitHub - with separate projects for the service, the hosting and a client. Check it out.
Its possible but you should refer to this link for understanding current state and known issues - http://www.mono-project.com/docs/web/wcf/. It's limited now. For eg. if you wish to use WSHttpBinding its not supported currently.

Running UI From WCF Hosted Inside WindowService

I have a Window Service thats hosts wcf:
protected override void OnStart(string[] args)
{
if (serviceHost != null)
{
serviceHost.Close();
}
serviceHost = new ServiceHost(typeof('myservicetype'));
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
serviceHost.AddServiceEndpoint
(typeof('myservicetype'),
binding, ConfigurationManager.AppSettings["myconfig"]
);
serviceHost.Open();
Console.ReadLine();
}
the wcf listen to requests, one of the request is to open notepad on the server,
this doesnt work because the service is running on session 0(no gui...),
how can i fix this?
You can open notepad regardless of what you're using (windows app, service etc) if the identity associated with the service got enough permissions.
You can then use Process.Start("notepad.exe", yourTextFile);
Or just Process.Start(yourTextFile); if notepad is the default program for handling text files.

When running mstest against a WCF service, WcfSvcHost fails to run and tests fail. Tests pass when debugged

Using Visual Studio 2010, I have written a simple WCF service and some integration tests that I want to run against it. I build my proxy for the tests at runtime in code rather than using configuration.
My tests pass in debug but not when run!
FAIL if run - go Test/Run/Tests in current context ( as the WCF Service it calls has not been hosted)
PASS in debug - go Test/Debug/Tests in current context ( as the WCF project has WCF Options/Start WCF Service Host when debugging another project in the same solution)
Is there a way to get WCFServiceHost to start when the tests are run normally?
Thanks,
Andy
Test method BulkLoaderIntegrationTests.IntegrationTests.ImportEntries_withGoodPCMs_reportsCreatedOk threw exception:
System.ServiceModel.EndpointNotFoundException: Could not connect to net.tcp://localhost:8001/OLELoader. The connection attempt lasted for a time span of 00:00:00.9687686. TCP error code 10061: No connection could be made because the target machine actively refused it 127.0.0.1:8001. ---> System.Net.Sockets.SocketException: No connection could be made because the target machine actively refused it 127.0.0.1:8001
I disabled 'Start WCF Service Host' when debugging another project in the same solution.
I added a static method in [ClassInitialize] to 'self host' the WCF service within the Test context for the duration of the testing.
[ClassInitialize]
public static void Init(TestContext t)
{
IntegrationTests.InitService();
}
[ClassCleanup]
public static void CleanUp()
{
IntegrationTests.host.Close();
}
private static bool ServiceIsStarted = false;
private static ServiceHost host;
private static void InitService()
{
if (!ServiceIsStarted)
{
// Create the ServiceHost.
host = new ServiceHost(typeof (OLEImport),
new Uri(IntegrationTestHelper.BaseAddress));
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
host.Open();
ServiceIsStarted = true;
}
}