When I run my WPF that uses my WCF Service Library through visual studio I get a WCF Service Host startup at the same time with my service starting my WCF Service Library, however when I click on the exe for my WPF in the debug folder it doesn't startup is there anyway to make it start in code as the following code I have believed would work doesn't.
try
{
host = new ServiceHost(typeof(Service1), new Uri("http://" + System.Net.Dns.GetHostName() + ":8733/DatabaseTransferWcfServiceLibaryMethod/Service1/"));
host.Open();
}catch(AddressAlreadyInUseException)
{
}
I'm trying not to use service references.
I'm no expert at this, but perhaps you're missing the binding. Here is the simplest example I can create of hosting and consuming a WCF service in code (you'll need to add references to System, System.Runtime.Serializaton, and System.ServiceModel, but otherwise, this code is complete).
using System;
using System.Runtime.Serialization;
using System.ServiceModel;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
// Create the host on a single class
using
( ServiceHost host
= new ServiceHost
( typeof(MyService)
, new Uri("http://localhost:1234/MyService/MyService")
)
){
// That single class could include multiple interfaces to
// different services, each must be added here
host.AddServiceEndpoint
( typeof(IMyService)
, new WSHttpBinding(SecurityMode.None)
// Each service can have it's own URL, but if blank use the
// default above
, ""
);
// Open the host so it can be consumed
host.Open();
// Consume the service (this cuold be in another executable)
using
( ChannelFactory<IMyService> channel
= new ChannelFactory<IMyService>
( new WSHttpBinding(SecurityMode.None)
, "http://localhost:1234/MyService/MyService"
)
){ IMyService myService = channel.CreateChannel();
Console.WriteLine(myService.GetValue());
}
// Clean up
host.Close();
}
}
}
[ServiceContract]
public interface IMyService
{ [OperationContract] int GetValue();
}
public class MyService : IMyService
{ public int GetValue()
{ return 5;
}
}
}
Okay the error was way away from where I thought it was the error was it was running on my user interface thread so needed to add.
[ServiceBehavior( UseSynchronizationContext = false)]
If anyone else has this problem i hope this helps.
Related
I'm trying to implement a self-host WCF service in a console app. The first step is that I tried to implement a helloworld app first. However, It seems I couldn't reference the key word or class in System.ServiceModel. Can anyone tell me what I did wrong? Below is my code. Keyword "ServiceHost" cannot be found now.
using System;
using System.ServiceModel;
namespace selfHost
{
[ServiceContract]
public interface IHelloWorldService
{
[OperationContract]
string SayHello(string name);
}
public class HelloWorldService : IHelloWorldService
{
public string SayHello(string name)
{
return string.Format("Hello, {0}", name);
}
}
class Program
{
static void Main(string[] args)
{
Uri baseAddress = new Uri("http://localhost:8080/hello");
// Create the ServiceHost.
using (ServiceHost host = new ServiceHost(typeof(HelloWorldService), baseAddress))
{
// Enable metadata publishing.
ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since
// no endpoints are explicitly configured, the runtime will create
// one endpoint per base address for each service contract implemented
// by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
// Close the ServiceHost.
host.Close();
}
}
}
}
This is no longer supported in .Net Core. Looking at: https://github.com/dotnet/wcf/issues/2559
You can downgrade to .Net framework if you can or use another 3rd party library for servicehost.
Based on your code, I did a demo using the .NET framework, I didn't find any error, but if you're using the .NET Core, it doesn't work, have you tried re-referencing the System.ServiceModel ?
There is a link about System.ServiceModel References ,hope it use for you.
System.ServiceModel References
I’ve created an object that I would like to pass in a WCF call… but inside ServiceReference1… this object is redefined… is there a way to just use the original object everywhere… it seems like people have done this but I can’t figure out what I am doing wrong.
The object is used as a parameter to a function in the service contract.
[OperationContract(IsOneWay = true)]
void UpdateInformation(MyObject myObject);
The error that I get when I try to call the function from my client is “Argument 1: cannot convert from ‘MyNameSpaceDTO.MyObject' to ‘MyNameSpace.ServiceReference1.MyObject’”
The object is in it’s own class library dll and it is marked with [DataObject] and [DataMember] attributes.
namespace MyNameSpaceDTO
{
[DataContract]
public class MyObject
{
[DataMember]
public string Name { get; set; }
….
But, also ends up in Reference.cs after adding the Service Reference as:
[System.Diagnostics.DebuggerStepThroughAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("System.Runtime.Serialization", "4.0.0.0")]
[System.Runtime.Serialization.DataContractAttribute(Name="MyObject", Namespace="http://schemas.datacontract.org/2004/07/MyNameSpaceDTO")]
[System.SerializableAttribute()]
public partial class MyObject : object, System.Runtime.Serialization.IExtensibleDataObject, System.ComponentModel.INotifyPropertyChanged {
[System.NonSerializedAttribute()]
private System.Runtime.Serialization.ExtensionDataObject extensionDataField;
[System.Runtime.Serialization.OptionalFieldAttribute()]
private string NameField;
...
Also, I do have the following set in the Advanced section of the Add Service Reference:
[x] Reuse types in referenced assemblies
(o) Reuse types in all referenced assemblies
For consuming a WCF service you often see samples (and they're undoubtedly advisable!) where you're instructed to add that service via the Add Service Reference dialog. By referencing a service that way your client application creates proxy classes form the WSDL exposed by the service.
As a result you end up having e.g. a class MyNameSpaceDTO.MyObject in your contract-assembly and a MyNameSpace.ServiceReference1.MyObject in your client application which was generated form the WSDL. This may seem somewhat redundant.
One situation in which you may need this behaviour could be the following: Imagine you'd want to consume an arbitrary public web service which you don't control. You have no access to the contract-assembly which defines the types etc. In that situation creating your own local proxy classes from the exposed WSDL is optimal since it's your only way to get the needed types and so on.
But your concrete situation seems to be a little bit different. I think what you're looking for is a shared contract. Since you're in control of the client and server code (and both live happily side by side in the same solution), you're in the comfortable situation to just share the contract:
So instead of adding a service reference within your client-app (via Add Service Reference), you'd just reference the contract-assembly (via the usual Add Reference dialogue). By doing this there'll by only one MyNameSpaceDTO.MyObject since the second one is never created and not needed. This approach is called contract sharing.
Please take a look at that example:
EDIT:
Please note some changes: The most important one is that you usually wouldn't want to share the assembly which holds your implementation logic of your service. So I extracted that part from the Contract-assembly and put it in a separate Implementation-assembly. By doing so, you simply share the interfaces and types and not the implementation logic. This change is reflected in the screenshot above, too.
You could set up that small solution with the following classes:
Contract - IService1.cs:
[ServiceContract]
public interface IService1
{
[OperationContract]
string GetData(int value);
}
Implementation - Service1.cs:
public class Service1 : IService1
{
public string GetData(int value)
{
return string.Format("You entered: {0}", value);
}
}
Host - Program.cs:
class Program
{
static void Main(string[] args)
{
var baseAddress = new Uri("http://localhost:8732/Design_Time_Addresses/Service1/");
using (var host = new ServiceHost(typeof(Service1), baseAddress))
{
// Enable metadata publishing.
var smb = new ServiceMetadataBehavior();
smb.HttpGetEnabled = true;
smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
host.Description.Behaviors.Add(smb);
// Open the ServiceHost to start listening for messages. Since no endpoints are
// explicitly configured, the runtime will create one endpoint per base address
// for each service contract implemented by the service.
host.Open();
Console.WriteLine("The service is ready at {0}", baseAddress);
Console.WriteLine("Press <Enter> to stop the service.");
Console.ReadLine();
host.Close();
}
}
}
Client - Program.cs:
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Press <Enter> to proceed.");
Console.ReadLine();
var binding = new BasicHttpBinding();
var endpoint = new EndpointAddress("http://localhost:8732/Design_Time_Addresses/Service1/");
var channelFactory = new ChannelFactory<IService1>(binding, endpoint);
// Create a channel.
IService1 wcfClient1 = channelFactory.CreateChannel();
string s = wcfClient1.GetData(42);
Console.WriteLine(s);
((IClientChannel)wcfClient1).Close();
Console.WriteLine("Press <Enter> to quit the client.");
Console.ReadLine();
}
}
I am starting out with WCF. I have created two console apps (server and client) that work without any issues but since moving them onto forms I'm having all kinds of problems. I had a look here and elsewhere on the net, I can't seem to find anything that can help me with my issue. I honestly don't understand the issue but I think it may have something to do with my datatypes (they're under different namespaces)?
Here's my Server code:
public partial class Form1 : Form
{
ModelDataServer Server;
public ScraperForm()
{
InitializeComponent();
Server = new ModelDataServer(); // Opened Here
Server.Scraper = this;
}
}
[ServiceContract]
public interface IModelData
{
[OperationContract]
ArrayList GetData();
}
[ServiceBehavior(UseSynchronizationContext=false)]
public class ModelDataServer : IModelData
{
ServiceHost Host;
public DataModel Model { private get; set; }
public ModelDataServer()
{
Host = new ServiceHost(typeof (ModelDataServer),
new Uri[]
{
new Uri("http://localhost:8000")
});
Host.AddServiceEndpoint(typeof(IModelData),
new BasicHttpBinding(),
"ModelData");
Host.Open(); // Error Points Here!!!
}
public ArrayList GetData()
{
return Model.GetData();
}
public void CloseServer()
{
Host.Close();
}
}
Here's my Client code:
[ServiceContract]
public interface IModelData
{
[OperationContract]
ArrayList GetData();
}
[ServiceBehavior(UseSynchronizationContext = false)]
public class ModelDataClient
{
ChannelFactory<IModelData> HttpFactory;
IModelData HttpProxy;
public ModelDataClient()
{
HttpFactory = new ChannelFactory<IModelData>(
new BasicHttpBinding(),
new EndpointAddress("http://localhost:8000/ModelData"));
HttpProxy = HttpFactory.CreateChannel();
}
public ArrayList GetData()
{
return HttpProxy.GetData();
}
}
Here's the error I'm recieving (points to where I'm opening the ServiceHost):
The ChannelDispatcher at 'http://localhost:8000/ModelData' with contract(s) '"IModelData"' is unable to open its IChannelListener.
P.S. I have been struggling to get delegates to work outside of something I've done in a tutorial. If anyone can suggest a better way that uses delegates instead of passing my form class into the other class that would be great.
Yes, this is most likely related to namespace issues. For illustration issues, let's assume your server project's namespace is ServerApp, and your client's namespace is ClientApp. You define IModelData in both applications, which means you have ServerApp.IModelData and ClientApp.IModelData. Even though the code is identical, these are two separate interfaces (because of the namespace).
So you're trying to pass ClientApp.IModelData to the service, and it's expecting ServerApp.IModelData.
You can solve this by moving the interface IModelData to its own assembly and having the server app and the client app both reference this third assembly. That's what we do at work - all of our service contracts are in a separate assembly (two, actually, but that's a different story).
A couple of other things to note:
Unless your client is also hosting a service, you can remove the [ServiceContract] attribute from the class. Clients don't need that.
In your server app, what is Server.Scraper = this; for? It appears to be assigning the Form to a property Scraper in the service, but I don't see that property in your code. Additionally, services don't really use properties (I think I saw somewhere that you could do it, but it wasn't intuitive). I don't think you'd want to assign the entire form to the service, as service's in and of themselves don't usually have UIs - they supply data and receive data from the service.
I am trying to make a simple windows service that maintains a queue of integers and accepts new integers from other applications via a WCF call. My current implementation seems to maintain separate queues for each application which communicates with it, which is not what I want.
I started by following the instructions at from Microsoft on How to: Host a WCF Service in a Managed Windows Service.
My WindowsService class looks like this:
public class MyWindowsService : ServiceBase{
public ServiceHost serviceHost = null;
public MyWindowsService(){
ServiceName = "AdHocReportService";
}
public static void Main(){
ServiceBase.Run(new MyWindowsService());
}
protected override void OnStart(string[] args){
if (serviceHost != null)
serviceHost.Close();
serviceHost = new ServiceHost(typeof(MyService));
serviceHost.Open();
}
protected override void OnStop(){
if (serviceHost != null){
serviceHost.Close();
serviceHost = null;
}
}
}
In my Service class I have a queue and an Add method. The add method returns the count of items in the queue after the add. The code looks like this:
public class MyService : IMyService
{
private Queue<int> myQueue= new Queue<int>();
public int Add(int reportId)
{
myQueue.Enqueue(reportId);
return myQueue.Count;
}
}
Lastly, I test my service using the following code in a ConsoleApp:
MyServiceClient client = new MyServiceClient();
int count = client.Add(10);
Console.WriteLine(count); //prints 1
count = client.Add(25);
Console.WriteLine(count); //prints 2
Console.ReadLine();
I would expect this to print 1 and 2 the first time my test is run, then 3 and 4 the second time, and then 5 and 6 the third and so on. However, it simply returns 1 and 2 each time, as if the Console App is instantiating the object itself and not operating on the object inside the Windows Service. What am I not understanding?
I think you want a singleton WCF service. See here.
By default, the instance mode for a WCF service is per-call. So an instance of your service is being created by the host for each call you make.
Note: When using a singleton service, your operations need to be thread safe. So I suggest switching from a Queue to a ConcurrentQueue, so you can handle multiple concurrent clients.
Alternative: Use a MSMQ binding. This will ensure you that all of your incoming messages are queued out of process, therefore persisted between restarts too.
While answering another question I bumped into this interesting situation Where WCF is happy to cast an interface with different number of members and from Different namespaces where normal .net runtime can't.
Can any one explain how WCF is able to do it and how to configure/force WCF to behave same as normal .net runtime. Please note that I know I should have only one interface and blah.. blah..
here is working code
using System;
using System.Runtime.Serialization;
using System.IO;
using System.ServiceModel;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
namespace MyClient
{
[ServiceContract]
public interface IService
{
[OperationContract]
string Method(string dd);
[OperationContract]
string Method2(string dd);
}
}
namespace MyServer
{
[ServiceContract]
public interface IService
{
[OperationContract]
string Method(string dd);
}
}
namespace MySpace
{
public class Service : MyServer.IService
{
public string Method(string dd)
{
dd = dd + " String from Server.";
return dd;
}
}
class Program
{
static void Main(string[] args)
{
string Url = "http://localhost:8000/";
Binding binding = new BasicHttpBinding();
ServiceHost host = new ServiceHost(typeof(Service));
host.AddServiceEndpoint(typeof(MyServer.IService), binding, Url);
host.AddDefaultEndpoints();
host.Open();
// Following line gives error as it should do.
//MyClient.IService iservice = (MyClient.IService)new MySpace.Service();
// but WCF is happy to do it ;)
ChannelFactory<MyClient.IService> fac = new ChannelFactory<MyClient.IService>(binding);
fac.Open();
MyClient.IService proxy = fac.CreateChannel(new EndpointAddress(Url));
string d = proxy.Method("String from client.");
fac.Close();
host.Close();
Console.WriteLine("Result after calling \n " + d);
Console.ReadLine();
}
}
}
There is no inconsistency.
// Following line gives error, as it should do, because the .NET types
// MyClient.IService and MySpace.Service are not related.
MyClient.IService iservice = (MyClient.IService)new MySpace.Service(); // ERROR !!
// Likewise, a WCF client proxy defined using MyService.IService as the contract
// cannot be cast to the unrelated .NET type MyClient.IService
ChannelFactory<MyService.IService> fac1 = new ChannelFactory<MyService.IService>(binding);
fac1.Open();
MyClient.IService proxy = (MyClient.IService)fac1.CreateChannel(new EndpointAddress(Url)); // ERROR !!
// but the service can be consumed by any WCF client proxy for which the contract
// matches the defined service contract (i.e. they both expect the same XML infoset
// in the request and response messages). There is no dependency between the .NET type
// used in the client code and the .NET type used to implement the service.
ChannelFactory<MyClient.IService> fac = new ChannelFactory<MyClient.IService>(binding);
fac.Open();
// Next line does not error because the ChannelFactory instance is explicitly
// specialised to return a MyClient.IService so the .NET type is the same... there is no cast
MyClient.IService proxy = fac.CreateChannel(new EndpointAddress(Url));
// NOTE: Thus far we have not done anything with the service in this case.
// If we call Method() it should succeed, since the contract matches. If we call
// Method2() the channel will fault as there is no matching operation contract in the service.
The .NET type system is a completely different concept to the WCF notion of service/operation/message/data contract. Just as well, otherwise you could never write a WCF client for a WCF service you didn't write yourself.
However, as the middle example shows, if you reuse the .NET type for the service contract in both service and client code, your expectation will be met.
Your MyClient.IService has the same method as MyServer.IService does WCF's channel factory thinks that the contract matches on the exposed url and hence processes the request.
Try changing your MyClient.IService method name and you can see it fail. Namespace are logical seperations as we know.
When you create a WCF Service and expose the wsdl it doesn't have any of your namespaces, unless you specify one in your configuration using bindingNamespace attribute in your endpoint element. Just try a sample and generate a proxy from the wsdl to see that the proxy doesn't have any namespace.
As long as the IService in your MyClient and MyServer namespace match your WCF code above would work
In regards to your code below:
MyClient.IService iservice = (MyClient.IService)new MySpace.Service();
You are trying to cast MySpace.Service explicitly to MyClient.IService where your "Service" doesnt implement your MyClient.IService and is correct according to OOP. Since you have all the code in a single file and is self hosted might be giving you the confusion.