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.
Related
I'm working on integrating with the Azure Batch API and construct a client object based on credentials I pass through. What I want to know is how can I test to see whether the connection is valid and the credentials are correct? I can't see anything on the API to do this. You can just create the BatchClient object and then call operations on it to list jobs, pools etc, all of which fail with a complex error if your initial credentials were wrong. I want to be able to test for incorrect credentials before I attempt any other operations. Does anyone know how to do this?
var client = BatchClient.Open(new BatchSharedKeyCredentials(
string.Format("https://{0}.{1}.batch.azure.com",
_primaryBatchAccountName,
_primaryRegion),
_primaryBatchAccountName,
_primaryBatchAccountKey));
This is the code to create the client object. But it doesn't throw any error even if you pass it completely wrong values. You only get the error when you try and do anything with it.
The BatchClient doesn't keep a persistent connection "open." It just issues REST requests to the target endpoint whenever required (i.e. when you use a method).
To the best of my knowledge, there is no way to determine if you have the "right" credentials values or endpoint data until you try to use the BatchClient to actually communicate with the server. This is because it's not really possible for the client to know what endpoints are valid, nor is it possible for it to know what a "valid" credential looks like, or if the credential you specified is correct (the server must verify that).
The best recommendation I can come up with is to just try to issue a simple API call (like a ListJobs or something) and ensure that it completes successfully. That should validate that your BatchClient is working.
i have a service method which return users based on some conditions which is serialized and passed as string.
public user GetUser(string RequestXML){ }
The problem is that the "RequestXMl" must be encrypted as well as the response object using AES256 on the both the server and client application.
Is this really necessary to do this or WCF provides enough security to make a WCF service secure. ? or how to achieve this
Note :- i could not find any resources on the internet for this question may be because this a foolish idea or it has never been attempted.
You should be ideally passing the parameters in object format and the same for the return parameters.
These method parameters are by default serialised in WCF and applying the message security should fix them up as you require by encrypting.
You may also try to use the transport security system, SSL in case of more sensitive information.
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.
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 a WCF REST-service that is used by a mobile application used in different countries. It's accepting and returning JSON, and I use StructureMap.
The idea is to create one service instance for all countries, but I need to know what country is calling the service and do some logic on that in the service (for example, determine the connection string to be used).
however, I want to avoid that country code has to be passed with each service request. What are my options here?
Can I, for example, have one endpoint for each country? But in that case, how can I know what endpoint/country code was used to call the service?
Maybe other possibilities?
Multiple endpoints could be a solution, but you need a reliant way of determining which endpoint was actually used. Given the "disconnected" nature of WCF REST services (by that I mean the usage of non WCF types to do the communication and just using the WCF attributes), this would require you to write a WebHostFactory that specifies the country on creation of the service for a given endpoint. What you could to is inspect the WebOperationCurrent.Current instance to get access to information hidden from your method signature. For example:
Uri requestRoot = WebOperationContext.Current.IncomingRequest.UriTemplateMatch.BaseUri;
if (requestRoot.PathAndQuery.Contains("en-us")) {
// use english locale
}
else if (requestRoot.PathAndQuery.Contains("de-de")) {
// use german locale
}
You would need a better strategy to determine the actual country/language, but the basic idea is to re-host the same service under multiple paths and inspect those paths within the request using the current WebOperationContext instance.
Edit
From the comments above, I would like to add that you have access to the UserAgent string for the current request using the WebOperationContext. So you could also inspect those information looking for a clue about the requested language. But keep in mind that those "implicit" information are only clues but never clear indications about what the user wants.