I have a simple WCF service:
namespace Vert.Host.VertService
{
[ServiceContract]
public interface IRSVP
{
[OperationContract]
bool Attending();
[OperationContract]
bool NotAttending();
}
public class RSVPService : IRSVP
{
public RSVPService()
{
}
public bool Attending()
{
return true;
}
public bool NotAttending()
{
return true;
}
}
}
I'd like to self-host in a console application like so:
class Program
{
public static void Main()
{
// Create a ServiceHost
using (ServiceHost serviceHost = new ServiceHost(typeof(RSVPService)))
{
// Open the ServiceHost to create listeners
// and start listening for messages.
serviceHost.Open();
// The service can now be accessed.
Console.WriteLine("The service is ready.");
Console.WriteLine("Press <ENTER> to terminate service.");
Console.WriteLine();
Console.ReadLine();
}
}
}
So I'm using this app.config
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6"/>
</startup>
<system.serviceModel>
<services>
<service name="Vert.Host.VertService.RSVPService">
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/Vert" />
</baseAddresses>
</host>
<endpoint
address="/RSVP"
binding="basicHttpBinding"
contract="Vert.Host.VertService.IRSVP" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="">
<serviceMetadata httpsGetEnabled="true" httpGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
</configuration>
As I understand it, this setup would leave me with http://localhost:8080/Vert/RSVP/Attending as a valid REST URI to call from an arbitrary HTTPClient, but the call is hanging indefinitely or coming back with a 0 No Response (I'm using Advanced REST client)
What am I missing?
You are RIGHT in all of your setup...right up to the point where you stopped typing code and started telling me what you have. :)
What you've created is a std WCF service and you can get to it using a Service proxy or a ChannelFactory, but it will communicate with you as-is using SOAP.
You need this tutorial to turn this webservice into a RESTFUL service giving back Json/pox.
Related
i was trying to create basic WCF service and host it on a console application.
Here's my code of WCF project.
ISampleService.cs
using System.ServiceModel;
namespace MultipleSeviceContractAppl
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the interface name "ISampleService" in both code and config file together.
[ServiceContract]
public interface ISampleService
{
[OperationContract]
string DoWork();
}
}
SampleService.cs
namespace MultipleSeviceContractAppl
{
// NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "SampleService" in both code and config file together.
public class SampleService : ISampleService
{
public string DoWork()
{
return "Message from WCFservice";
}
}
}
App.config
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="MultipleSeviceContractAppl.SampleService" behaviorConfiguration="mexBehaviour">
<endpoint address="SampleService" binding="netTcpBinding" contract="MultipleSeviceContractAppl.ISampleService">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/"/> <!--For metadata exchange-->
<add baseAddress="net.tcp://localhost:8737/" /> <!--Endpoint, netTCP binding, For data exchange-->
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
WCF Hosting on console appl - Program.cs
using System;
using System.ServiceModel;
namespace ConsumeWCFApplicationAppl
{
class Program
{
static void Main()
{
using (ServiceHost host = new ServiceHost(typeof(MultipleSeviceContractAppl.SampleService)))
{
host.Open();
Console.WriteLine("Host started #" + DateTime.Now.ToString());
Console.ReadKey();
}
}
}
}
in console application at line host.Open();, following exception was thrown.
An unhandled exception of type 'System.InvalidOperationException'
occurred in System.ServiceModel.dll Additional information: Service
'MultipleSeviceContractAppl.SampleService' has zero application
(non-infrastructure) endpoints. This might be because no configuration
file was found for your application, or because no service element
matching the service name could be found in the configuration file, or
because no endpoints were defined in the service element. Help me to
figure out my mistake. Thanks
You need to replicate the config in your console app and add reference to DLL of the service model assemblies to this project...
<behaviors>
<serviceBehaviors>
<behavior name="mexBehaviour">
<serviceMetadata httpGetEnabled="false"/>
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="MultipleSeviceContractAppl.SampleService" behaviorConfiguration="mexBehaviour">
<endpoint address="SampleService" binding="netTcpBinding" contract="MultipleSeviceContractAppl.ISampleService">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8733/"/> <!--For metadata exchange-->
<add baseAddress="net.tcp://localhost:8737/" /> <!--Endpoint, netTCP binding, For data exchange-->
</baseAddresses>
</host>
</service>
</services>
I'm learning WCF, I started creating a very basic host app which defines a class with one method as follows:
[ServiceContract()]
public interface IMath
{
[OperationContract]
int Add(int a, int b);
}
public class MathCalcs : IMath
{
public MathCalcs()
{
Console.WriteLine("Service await two numbers...");
}
public int Add(int a, int b)
{
return a + b;
}
}
and that is how I configured the App.config file:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<services>
<service name="ConsoleHost.MathCalcs" behaviorConfiguration="MathServiceMEXBehavior">
<endpoint address="http://localhost:8080/MathCalcs"
binding="basicHttpBinding"
contract="ConsoleHost.IMath"/>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080/MathCalcs"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="MathServiceMEXBehavior">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
</configuration>
Then I called the service from Main
using (ServiceHost host = new ServiceHost(typeof(MathCalcs)))
{
host.Open();
Console.WriteLine("***The service is ready***");
}
Console.ReadLine();
But it fails to view the metadata of the service through the URI http://localhost:8080/MathCalcs, I'm sure I'm following the steps right as the book I'm reading from and as a preceding example works fine, the only difference is that I didn't separate the service logic (the interface and the class) in a stand alone class library.
What am I missing?
The following line of code
Console.ReadLine();
must be inside the braces of the using clause!
When that is done, retry finding the WSDL metadata.
Here is a related post that I think may lead you in the right direction.
WCF service showing blank in browser
I am trying to host two services using a single console app. However, when I am trying to do so, only one service gets hosted, while the other does not.
Program.cs:
namespace WWWCFHost
{
class Program
{
static void Main(string[] args)
{
using (ServiceHost host = new ServiceHost(typeof(WWWCF.Login)))
{
host.Open();
Console.WriteLine("Service1 Started");
}
using (ServiceHost host1 = new ServiceHost(typeof(WWWCF.UserRegistration)))
{
host1.Open();
Console.WriteLine("Service2 Started");
Console.ReadLine();
}
}
}
}
App.config
<configuration>
<system.serviceModel>
<services>
<service name="WWWCF.Login" behaviorConfiguration="WWWCF.mexBehaviour1">
<endpoint address="Login" binding="basicHttpBinding" contract="WWWCF.ILogin">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8080"/>
</baseAddresses>
</host>
</service>
<service name="WWWCF.UserRegistration" behaviorConfiguration="WWWCF.mexBehaviour2">
<endpoint address="UserRegistration" binding="basicHttpBinding" contract="WWWCF.IUserRegistration">
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange">
</endpoint>
<host>
<baseAddresses>
<add baseAddress="http://localhost:8090"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="WWWCF.mexBehaviour1">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
<behavior name="WWWCF.mexBehaviour2">
<serviceMetadata httpGetEnabled="true"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>
As in the code above, I am trying to host one service on port 8080 and the other on port 8090. When I run the application, the first service starts and then closed automatically and the second service remains started. How can I host both the services simultaneously ?
I have gone through the link : Two WCF services, hosted in one console application
I have gone through other threads as well.But they do not solve my issue.
Will be happy to provide any further details if required.
Your first service jumps out of the using block and so is disposing too early. Try this...
using (ServiceHost host = new ServiceHost(typeof(WWWCF.Login)))
using (ServiceHost host1 = new ServiceHost(typeof(WWWCF.UserRegistration)))
{
host.Open();
Console.WriteLine("Service1 Started");
host1.Open();
Console.WriteLine("Service2 Started");
Console.ReadLine();
}
Take a look at this: http://msdn.microsoft.com/en-us//library/yh598w02.aspx
You're instantly closing the first, since it's in the using. You need to set it up so the first using scope doesn't end until after the ReadLine() call.
Try:
using (ServiceHost host = new ServiceHost(typeof(WWWCF.Login)))
{
host.Open();
Console.WriteLine("Service1 Started");
using (ServiceHost host1 = new ServiceHost(typeof(WWWCF.UserRegistration)))
{
host1.Open();
Console.WriteLine("Service2 Started");
Console.ReadLine();
}
}
In my book, it wants me to expose two endpoints using two bindings: WsHttpBinding & NetTCPBinding and host the service in a host application.
I use the following code in C# to try to connect to my service:
Uri BaseAddress = new Uri("http://localhost:5640/SService.svc");
Host = new ServiceHost(typeof(SServiceClient), BaseAddress);
ServiceMetadataBehavior Behaviour = new ServiceMetadataBehavior();
Behaviour.HttpGetEnabled = true;
Behaviour.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
Host.Description.Behaviors.Add(Behaviour);
Host.Open();
On the service side I have:
[ServiceContract]
public interface IService...
public class SService : IService....
Then in my Config file I have:
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="Behavior">
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="WsHttpBehaviour" name="SService.SService">
<endpoint
address=""
binding="wsHttpBinding"
bindingConfiguration="WsHttpBindingConfig"
contract="SService.IService" />
<endpoint
address=""
binding="netTcpBinding"
bindingConfiguration="NetTCPBindingConfig"
contract="SService.IService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:5640/SService.svc" />
<add baseAddress="net.tcp://localhost:5641/SService.svc" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
But when I try to add service reference to my host application, it says unable to download metadata from the address. I don't understand what is wrong and the teacher never taught this.. I decided to go ahead and look it up and learn ahead of time. I used the Editor to create the WebConfig shown above.
Can anyone point me in the right direction? I added Metadata behaviour through the editor and I set the HttpGetEnabled to true.
I can find a few issues with your code that can cause this issue:
Host = new ServiceHost(typeof(SServiceClient), BaseAddress). Pass here typeof(SService.SService) instead of typeof(SServiceClient). Change like this:
Host = new ServiceHost(typeof(SService.SService))
<service behaviorConfiguration="WsHttpBehaviour". I guess this should be "Behavior" as you have defined that. Since you have metadata enabled in config, you may remove the lines of code which add a ServiceMetadataBehavior to your servicehost.
Here is a sample that you can use for reference:
<system.serviceModel>
<services>
<service name="ConsoleApplication1.Service">
<endpoint address="" binding="wsHttpBinding" contract="ConsoleApplication1.IService" />
<endpoint address="" binding="netTcpBinding" contract="ConsoleApplication1.IService" />
<host>
<baseAddresses>
<add baseAddress="http://<machinename>:5640/SService.svc" />
<add baseAddress="net.tcp://<machinename>:5641/SService.svc" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<serviceMetadata httpGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="False"/>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
ServiceHost host = new ServiceHost(typeof(Service));
host.Open();
Console.ReadLine();
}
}
[ServiceContract]
public interface IService
{
[OperationContract]
string DoWork();
}
public class Service : IService
{
public string DoWork()
{
return "Hello world";
}
}
}
Metadata will be automatically available at the http baseaddress defined in the config.
I'm running a WCF service hosted in a WPF app, and am trying to raise an event in the host when a message is sent to the service, but am having great difficulty.
My code is as follows:
Service -
namespace BatService
{
[ServiceContract]
public interface IBatServ
{
[OperationContract]
void UseGadget(string name);
}
[ServiceBehavior(InstanceContextMode=InstanceContextMode.Single)]
public class BatServ : IBatServ
{
public void UseGadget(string name)
{
OnUsedGadget(name);
}
public static event EventHandler<BatArgs> UsedGadget;
public static void OnUsedGadget(string name)
{
if (UsedGadget != null)
UsedGadget(null, new BatArgs() { BatGadget = name });
}
}
public class BatArgs : EventArgs
{
public string BatGadget;
}
}
Host -
namespace BatHostWPF
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
ServiceHost host = new ServiceHost(typeof(BatServ));
BatServ.UsedGadget += new EventHandler<BatArgs>(BatServ_UsedGadget);
host.Open();
}
void BatServ_UsedGadget(object sender, BatArgs e)
{
MessageBox.Show(e.BatGadget + " was used!");
}
}
}
Service App.config -
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.web>
<compilation debug="true" />
</system.web>
<!-- When deploying the service library project, the content of the config file must be added to the host's
app.config file. System.Configuration does not support config files for libraries. -->
<system.serviceModel>
<services>
<service name="BatService.BatServ">
<endpoint address="" binding="wsHttpBinding" contract="BatService.IBatServ">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8732/Design_Time_Addresses/BatService/Service1/" />
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information,
set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="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>
</system.serviceModel>
</configuration>
Host's App.config -
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior name="NewBehavior0">
<serviceMetadata httpGetEnabled="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="NewBehavior0" name="BatService.BatServ">
<clear />
<endpoint address="net.pipe://localhost/battserv" binding="netNamedPipeBinding"
bindingConfiguration="" contract="BatService.IBatServ" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8888/batserv" />
</baseAddresses>
</host>
</service>
</services>
</system.serviceModel>
</configuration>
As you can probably guess, I'm expecting to see a MessageBox when I call UseGadget() from a client. Whenever I try to test it out with VS's WcfTestClient.exe, nothing seems to happen at all. Where am I going wrong?
It turns out my endpoints weren't configured correctly. This page helped me solve my problems - http://www.switchonthecode.com/tutorials/wcf-tutorial-basic-interprocess-communication
I'm not sure if you can "raise events" in wcf, but you can create duplex communication architectures. The netTCPBinding, netNamedPipBinding and wsDualHttpBinding support this functionality.
Here is a video demonstration how to do callbacks with the wsDualHttpBinding
http://www.youtube.com/watch?v=NO2JsLrP75E
I've never done this with netNamedPipeBinding, but i assume the procedure is similar.
Remember to update your app.config files and service references when you're done with your implementation.
Hope that helps!