I'd like to use a web service (created in my main thanks to new ServiceHost(typeof(..)) ) and I would like to retrieve data received by my server to process it in my main.
I've begun with a simple event handler but it is impossible because I have to create an instance instead of using typeof.
Is there another solution?
You can use a singleton WCF service. You need to decorate the service class with [ServiceBehavior] and specify InstanceContextMode.Single, and then you pass an instance of the service class to the ServiceHost constructor.
Related
I have created a SOAP service.
Now i want to consume it in a c# client application. I added the service using 'Add service reference' and service reference is added to client.
All my service entities are in service. And in current scenerio i can't move them to a common library.
Problem is, my service endpoint is accepting List<Foo> as parameter.
Foo has a method Boo.
In client, when i try to Foo.Boo() i get Cannot resolve symbol Boo error.
Unfortunately only methods on the service itself are exposed via a SOAP web service, methods on objects used as parameters or return values are not. If the method relates to a server-side operation then you could expose it at the service root level taking the instance object as parameter, or if it relates to a client-side operation you could consider adding it as a client-side extension method.
I'm going to be creating a service that needs to make a call to a hosted WCF service halfway around the world. This isn't that big of a deal since the number of transactions that will be made is relatively low. However, I need to pass in an instance of a class that will possibly be defined in the WCF to the necessary WCF function.
So my question is, will that instance of the class exist on my server? Or will I be contacting the host server every time I attempt to set a variable in the object?
EXAMPLE:`
public class Dog
{
public string noise;
public int numLegs;
}
public class doSomething
{
public string makeNoise(Dog x)
{
return x.noise;
}
}
`
All of those are defined in the WCF. So when I create an instance of class Dog locally, will that instance exist on my side or the server hosting the WCF service? If I'm setting 1000 instances of Dog, the latency will definitely build up. Whereas if I DON'T have to contact the server every time I make a change to my instance of Dog, then the only time I have to worry about latency is when I pass it into doSomething.makeNoise.
The host creates a new instance of the service class for each request, if you're using the default per-call instantiation method (which is the recommended way).
So either this is the IIS server which hosting your WCF service that creates an instance of your service class, or it is the ServiceHost instance that you've created inside your own self-hosting setup (a console app, a Windows service etc.).
The service class instance is used to handle your request - execute the appropriate method on the service class, send back any results - and then it's disposed again.
There's also the per-session mode in which case (assuming the binding you've chosen support sessions) your first call will create a service-class instance, and then your subsequent calls will go to the same, already created instance (until timeouts come into play etc.).
And there's also the singleton mode, where you have a single instance of the service class that handles all requests - this is however rather tricky to get right in terms of programming, and "challenged" in terms of scalability and performance
You will need to host your WCF service on a public available server (for example IIS). Successful hosting will provide you with a link for the svc file. Clicking on that will give you a link ending in singleWsdl. You need to copy that link. On your client side, the one that requires a reference to the WCF, you will need to Add Service Reference and pass that link. This will generate proxy code with Client objects that you can use to access your WCF ServiceOperation methods.
At a minimum you should have three projects. A website project to host the actual site. A WCF project to host your services. And finally a shared project, which should contain the classes you are concerned with (the models).
Both the website and wcf projects should reference the shared project, this way they both know how the models look.
The wcf project should return serialzed models as json objects, which I usually do by referencing Newtonsoft.Json.
Your website project should expect this json, and deserialize them, also using Newtonsoft.Json. This is why your class (model) should exist in the shared project, so you can use the same class on both sides of your service call.
I want to do something just after my WCF service started. How can do it?
In fact,I should update some variable of my service every 10 minutes. So I put my update code in a thread. But I dont know how start this thread when service started (Is there anything liked Form_Load event in WCF services?)
There is typically no parts of your WCF service that is "just hanging around" in memory ready to do something.... WCF is NOT ASP.NET !
The default setup when hosting in IIS is this:
IIS listens on a specific port/URL for a request - there's not a single trace of your WCF service anywhere in memory
when a first request comes in, IIS will spin up a ServiceHost - a class that can "host" a service
this service host will then look at the request has come in and depending on the target URL, it will decide which service class to instantiate to handle this request. The service class (your service implementation) is then created and the appropriate method on that service class is called and executed, and once that's completed, the service class is disposed
So basically, there are two points where you can hook into:
you could create your own custom ServiceHost class that will do something when it gets instantiated
you can add some "initialization" code to each of your service class methods to handle your needs
It's difficult to keep a thread running on a server. As soon as the last session terminates the application shuts down. Some hosting providers also recycle the app pool on a schedule which kills any chance of keeping a thread running.
That aside, WCF Services don't actually run. They act like web pages triggered by a request. The sensible place to add init code would be in your Application_Start in Global.asax. This would get called once when the application starts (the first request is made).
If you would rather do something on each request to your services, you could hook the Application_BeginRequest event also in Global.asax.
You can create an instanced service, which will call the constructor upon the start of your service:
[ServiceContract]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
public class InstanceService
{
private int _intValue;
public InstanceService()
{
_intValue = 456;
}
[OperationContract]
public int GetData()
{
return _intValue;
}
}
Invoking GetData() on this service will return an integer with a value of 456.
This can be achieved if you are able to control how to host this. If you can, host your WCF service as a Windows service or an ad hoc executable. Then you can achieve what you want with ease. If you are bound to IIS hosting you must do as others have suggested and handle it per request.
Read up on self hosting wcf if IIS is not required.
At client side, I have this class without [DataContract]:
public class UserEntity
{
public string login;
public string password;
}
when I put [DataContract] and refresh the reference of this class at WCF side, then I can't initiate the web service. It says an error:
cannot create metadata...
What's wrong?
Are you sure that you actually know, why you can't refresh the reference? I mean you add [DataMember] - and it fails, you remove it - it works? Or it works several days ago and now you add [DataMember] (and many other stuff) and it not works now?
But anyway, the easiest way to solve "refresh reference" issues - to refresh reference manually with SvcUtil.exe. In this case error message would be much more descriptive the simple "oops! error!".
What is client and server side in your case? What is refreshing reference on the WCF side? Your description is very uncommon. Here is description how to create service with complex data type and WCF Class library:
Create WCF class library
Add data contract to the class library
Add service to class library
Implement service contract and service in the class library
Add host project
Reference WCF class library from host project
Host service from class library in host project
Add Metadata endpoint to your hosted service
Create client project
Run the host project outside the visual studio
Use Add service reference to create proxy on WCF service hosted in your host project
Implment code to call your service through created proxy
As you see there is no modification of data contract on the client side and no refreshing WCF service.
I have a WCF service and methods are exposed as below:
public interface IService
{
[OperationContract]
bool Read();
[OperationContract]
bool Write();
}
public class MyService : IService
{
//Constructor
MyService()
{
//Initialization
}
public bool Read()
{
//Definition
}
public bool Write()
{
//Definition
}
}
I have a desktop based application that consumes the Web service through URL.
This web service can be deployed at multiple location so user can connect to any web service by choosing a url from the combo box.
In the client application I create a Service client dynamically as shown below:
ServiceReference1.DXMyServiceClient _client = null;
_client = new DXMyServiceClient ();
_client.Endpoint.Address = new System.ServiceModel.EndpointAddress(url);
Questions
While debugging I notice whenever I call any methods of web service each time the constructor of MyService is invoked ( if I am connected to the same service).
like for example when I do:
_client.Read();//MyService () constructor is called
_client.Write();//MyService () constructor is called
The problem is I have to do all the initialization again.. like if I connecting to the database then I have to again build the connection string and all stuff..
Is this the natural behavior or I am doing something wrong?
Secondly,
I want to validate user for the valid url ( of web service ). If it is connecting to the valid url or not.. I am doing that through Ping command..
What is the best approach for that!!
Questions While debugging I notice whenever I call any methods
of web service each time the constructor of MyService is invoked
(if I am connected to the same service).
The problem is I have to do all the initialization again..
like if I connecting to the database then I have to again
build the connection string and all stuff..
Yes, that's the default behavior, and the recommended behavior. You should NOT rely on any state on your service side! That is generally not a good idea and can lead to a multitude of problems.
In its recommended "per-call" mode, a WCF service has a ServiceHost() class instance running, which will listen for incoming requests / messages. Each time a request comes in, a new, fresh instance of the service class (that implements your service contract) is constructed to handle the request - just like each time you hit a URL in ASP.NET, your page class is instantiated to handle the request.
Yes, of course - this means you should keep your service classes simple and lean and not do a lot of initialization / state management. Anything that needs to be persisted between service calls should be put in a persistence store, like a database, anyway.
You should look at the ServiceBehaviorAttribute class and it's InstanceContextMode property. It controls the lifetime of your service object.
The problem is I have to do all the
initialization again.. like if I
connecting to the database then I have
to again build the connection string
and all stuff..
Is this the natural behavior or I am
doing something wrong?
By default InstanceContextMode is set to PerSession and ConcurrencyMode is set to Single. However, if you don't use session, basically every time you call service new instance is created. This is desired behavior because it is considered more scalable. If it is a problem for you, you should implement session between subsequent calls then for every session you will get one instance of your service.
Here is a guide how to do that: Using Sessions.