I have written a WCF service with some regular functionality (add user, remove, search, update...). The implementation of this functionality is in entity framework (with sql DB).
Now I want to use it in the client side.
And I have some basic questions:
I have many calls to the WCF methods in the client side - should I try catch every time each call?
Every time I want to call a method, for example AddUser(User user), I need to make an instance of my service, like that:
WcfService client = new WcfService();
client.AddUser(user);
And in another place I write:
WcfService client = new WcfService(); //Again making a new instance...
client.UpdateUser(user);
Should I make one instance for all the application for my wcf service?
Or every time to make a new instance before I call to a method? (as in my example above).
Thanks very much !
In many cases, you want to reuse the same client proxy, as this connection method yields the best performance. Reusing the same proxy can be particularly beneficial if you use security features, which have a high initial security negotiation cost. Note: you surely need to check the state of the client proxy before using.
In the event that reusing the same client proxy is not an option, then consider using a ChannelFactory proxy that uses caching.
The following link provides a good explanation along with best practice recommendations:
http://blogs.msdn.com/b/wenlong/archive/2007/10/27/performance-improvement-of-wcf-client-proxy-creation-and-best-practices.aspx
(i)You can make an instance one time for a service, and use the same client whenever you need to make a method call. if you are aborting or closing the connection then you need to create each time.
(ii)It is better if you use try catch methods in each methods, so it will be easy to close the connection and identify the exceptions.
Related
I'm currently logging in with a username and password this way:
var client = new ServiceReference.CalcServiceClient();
client.ClientCredentials.UserName.UserName = "test";
client.ClientCredentials.UserName.Password = "test";
client.DoWork();
This works fine. Now, I'd like to add a way to logout (the user presses a button and a logout request should be send somehow).
Is this possible and if so, what would be the best way to implement this?
If the WCF is configured PerSession, a client.Close(); will do the work.
The process will be:
The client creates the proxy of the WCF service and makes method
calls.
A WCF service instance is created which serves the method response.
The client makes one more method call in the same session.
The same WCF service instance serves the method call.
When the client finishes its activity, the WCF instance is destroyed
and served to the garbage collector for clean up.
With the Close you will trigger the garbage collector clean up.
If the WCF is configured PerCall, there is no need to worry about Close/Logof. I would recommend always perform an explicit Close (and an using), but it's not really necessary in that case.
If the WCF is configured SingleInstance... well, maybe you are doing it wrong :) anyway, you should proceed with a Close().
I have an application that reuses the same WCF channel over and over again. I keep a static reference through a factory object. I wonder if this is good pratice or that I should open x channels and round robin all services calls over these channels instead of using the single channel?
Do these services calls get queued if using only 1 channel or does the same happen when I would use x channels?
You should use a single channel factory for all requests but different channels should be constructed for each request. Never reuse channels. They are not expensive to create and are not thread safe. What is expensive to create is the channel factory. It is thread safe and can be reused. Of course if the channel factory get into a faulted state you might need to reopen it.
#Darin Dimitrov
Reuse the same proxy
In many cases, you would want to reuse the same proxy. This has the best performance. It is especially true when you use security features since the initial security negotiation can have high cost.
proxy equals channel. if you look at this blog post, you can see the following code snippet:
ISimpleContract proxy = factory.CreateChannel();
((IClientChannel)proxy).Open();
Furthermore, if you plan to work with sessions, you don't want to establish a new session for each request (by creating a new channel/proxy each time).
I have a WSDL from which I generated the implementation of ClientBase namely MyService
function void updateData(Data data){
BasicHttpBinding binding = new BasicHttpBinding();
// see there is naked username and password.
EndpointAddress address = new EndpointAddress("http://qa.farwaha.com/eai_enu/start.swe?SWEExtSource=WebService&SWEExtCmd=Execute&UserName=john&Password=johspassword");
MyService service = new MyService(binding, address);
try{
service.update(data);
}finally{
service.close();
}
}
Unfortunately, to call this web service I have to pass User name and password as shown in the code. so, my question is around best practices.
Given that its a Winform Application.
How memory / CPU intensive is creating MyService object?
If you suggest cashing the service, it will hold on to the EndpointAddress; which intern has a string with Username and Password. Which is not a good idea .. any work arounds?
If I keep the code as such, service object will be garbage collected .. and there will be no trace of user name or password (as soon as GC runs)
This is a sample code, I have User Object which stores password in SecureString and every time I have to access the password; I get string from SecureString in an instance private method, use it quickly and let it be garbage collected. I believe if I use a method something like above, it will be safe OR safe enough rather than holding on to reference of Service, What do you suggest !!
To your specific questions:
In your client code, what you're constructing are instances of lightweight proxy classes that wrap the channel infrastructure that serialize messages to/from the service's endpoints. As such, these client proxy classes are cheap and fast to construct because they don't generally do a great deal until you actually send something to the service. One thing to watch out for is when you call services which employ a more complex security scheme - establishing connections to such services can be costly and so it's worth caching or re-using such connections if you can.
"Any workarounds"? Nope! Alas, the service you're consuming is poorly designed - not only do they require username and password to be supplied as part of the service method invocation, but they require that you pass them in the clear over HTTP. You might want to ask them to AT LEAST provide an SSL endpoint so that the username and password can be secured during transit. Better still, they could implement basic-auth to allow you to acquire an HTTP auth cookie that you can attach to subsequent calls against their services.
Yes, the GC will eventually clean-up your proxy instances. Better still, you could wrap your instances in using statements to invoke the Dispose pattern and clean-up deterministically. See my Magic8Ball WCF Service on Codeplex for examples.
Other observations:
Because your service requires your username and passoword, each time you call it, you need to pay some very careful thought to how you're going to obtain and store the username and password.
I would urge you to specify your binding information in the app.config rather than inline in your code. Again, see the Magic8Ball WCF Service: If you create bindings in code and the endpoint changes or if they open up a new endpoint, protocol, encoding and/or binding, you'll have to recompile and redist your entire app. If you specify your bindings in config, you might just be able to get away with shipping an updated app.config.
Hope this helps.
Not sure if this is the right terminology, let me explain what I want.
I have a web service that's available on the network - the web service has 1 web method.
What I want is... if the web service is running and performing tasks and another call is made to this web service, I want the 2nd call to fail or pend for a certain period of time then fail. Because only 1 instance of this web service should be called at once.
I was thinking of writing a value to the application object (like in asp.net) but then I have to be very careful to make sure that this value gets updated, in case of any errors, it might not... so this is dangerous, and would leave the web service in a state where no one can get to it.
Is there not a more dynamic way to determine if the web service is getting called or not?
You cannot do this with legacy ASMX web services. They have no support for different instance schemes.
I believe you can do this with WCF, as you can configure the service to have only a single instance.
If you are using WCF, this is simple. Use the service throttling settings to specify that you want MaxConcurrentCalls = 1 and MaxInstances = 1. You'll also want to set the ConcurrencyMode to Single for your ServiceBehavior.
I dont know much about web services on whether you can configure a web server to only start 1 instance of your web service, but you could try creating a mutex within your web service.
A Mutex is an interprocess synchronization object which can be used to detect if another instance of your web service is running.
So, what you can do is create a mutex with a name, then Wait on it. If more than 1 instance of your web service is alive, then the mutex will wait.
You could implement the check inside of the webmethod since it will be running in the same IIS process
You could create a poor man's mutex and have the first instance create a file and have consecutive instances check the existence of the file. Try Catch your web method and place the deletion of the file in the finally.
If you are WCF I recommend "bobbymcr" answer, but for legacy web service you can use Monitor instead or mutex as mutex is costly (because it is a kernel object) but if you do not care about performance and responsiveness of the service use the Mutex simply.
See this sample for using Monitor class
private static object lockObject = new object();
public void SingleMethod()
{
try
{
Monitor.TryEnter(lockObject,millisecondsTimeout);
//method code
}
catch
{
}
finally
{
Monitor.Exit(lockObject);
}
}
I am very new to web service stuff so please be kind.
I have written a simple POJO class, and deployed it on an axis2 server:
public class Database {
private Project project;
public void login(){
project = new Project();
project.setDescription("Hello there");
project.setName("To me");
}
public Project getProject(){
return project;
}
}
I call the service from a c# client:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr = db.getProject();
When I debug the response is null.
At the java end, when I call getProject, the project object is null.
What's happening?
How do I preserve the state of project between service calls?
For most toolkits, web services are stateless by default. I think axis is no different.
If you want to maintain state between calls then you will need to enable sessions. An example on how to maintain sessions in axis can be found at:
http://kickjava.com/src/test/session/TestSimpleSession.java.htm
On the .NET side you will need to assign a CookieContainer to your request to store the session identifier. See HOW TO: Use CookieContainer to Maintain a State in Web Services for more information.
I think your code would look something like this:
localhost.Database db = new WindowsFormsApplication1.localhost.Database();
// Assign the CookieContainer to the proxy class.
db.CookieContainer = new System.Net.CookieContainer();
db.login();
localhost.getProjectResponse pr = new WindowsFormsApplication1.localhost.getProjectResponse();
pr.CookieContainer = db.CookieContainer;
pr = db.getProject();
I think that should let you do what you want -- but I wouldn't recommend it.
Designing service interfaces is a bit different than designing object oriented interfaces. Service interfaces typically eschew the use of state and instead require the consumer to provide all of the relevant information in the request.
From Service-Oriented Architecture:
Services should be independent,
self-contained requests, which do not
require information or state from one
request to another when implemented.
I would definitely recommend reading that article and perhaps revisiting your design.
I'm not sure why #shivaspk left a comment instead of writing an answer, it is quite correct: web service calls (not just axis calls) are meant to be stateless, so although the project object gets created by
db.login();
when you call
db.getProject();
It is being called on a different instance of your Database class that was created by Axis to service the second call.
There is no really good answer to your question, except for you to rethink what you are trying to do. If you need some kind of authentication (via login), then that authentication needs to be part of every web service call.