I have a class library that communicates with my WCF service. The class library can then be used in any of my applications. I am curious as to what would be the best practice in handling the errors. I have thought of two scenarios but wanted to get some feedback from the community. The idea is not only to make sure it's appropriate for .NET solutions, but any other language that might not use the dll but rather call the service directly via a SOAP style call.
Option #1
Create a result object which will return to the caller API. Such as.
Public abstract BaseResponse
{
[DataMember]
Public bool IsSuccess { get; set;}
[DataMember]
Public string ErrorMsg { get ;set ;}
}
Public GetProductResponse : BaseResponse
{
[DataMember]
Public Product p { get;set;}
}
Option #2 : Throw a SOA Fault and allow the end user handle it however they choose. I could handle it in my API - however a direct call to the service would require that end user to code against the fault and handle it correctly.
Typically what I end up doing is having a business layer that will throw application specific exceptions. In the event that I want to expose this as a web service, I'll put a very thin layer on top of that that exposes those business services as WCF services. This layer will do nothing more than pass calls down to the business layer and return results as DataContract or MessageContract objects. In this very thin WCF layer, I'll catch exceptions from the business layer and map them to SOAP faults. This allows any .Net application to consume the business layer directly and catch exceptions as well as .Net or non-.Net applications to consume the web service and catch SOAP faults.
I usually use Option 2 (soap faults, WCF FaultContracts) then I am doing an internal service, where I know the client is also WCF, and I can make sure FaultExceptions are handled correctly.
When I am making an external/customer-facing service, I usually use option 1, splitting up my message into a "header" and a "body" and have the header contain an error message. I find this easier for other people to understand when telling them how to use your web service, and easier for non-WCF users to implement.
Both ways are fine really, as any decent SOAP tool for whatever language should handle SOAP faults, but you never know...
If you are building a restful webservice yo could use the http status code. And regardless of the service flavour the error handlers in WCF makes the code substantially more readable since it allows a single try/catch definition for methods.
There is a simple example here http://bit.ly/sCybDO
I would use option #2 every time. Faults are a standardised part of the SOAP specification, so any compliant framework should handle them appropriately. If a client is using a framework that doesn't have built in handling, then they will have to write custom code to do it, but that is the case with option #1 anyway, since they will have to understand your custom error semantics.
Unless there is a really good reason, I would always used the standardised approach - it give you the best chance of interoperability.
Related
I am unsure where to place my business logic. I have a WCF service which exposes its methods to my client.
Should my business logic go in the service method
public User GetUser(int id)
{
//Retrieve the user from a repository and perform business logic
return user;
}
or should it be in a separate class where each WCF service method will in turn call the business layer methods.
public User GetUser(int id)
{
return _userLogic.GetUser(id);
}
My personal preference is to have WCF as a very thin layer on top of a separate business layer. The WCF layer does nothing more than make calls to the business layer, similar to what you have shown in option 2. This gives you some flexibility in the event that you want to have your business layer consumed by something other than WCF clients (for example, a WPF application calling your business layer directly rather than via WCF).
WCF services are already, by default, designed for reuse. I see no reason not to have some logic in your services, though keep in mind things like the Single Responsibility Principle so you don't end up with a service that does a dozen things.
Even then, if you end up parceling out your functionality into smaller classes, it's not a bad idea at all to host those classes as WCF services. You can then use them in-proc (via pipes) when needed or across machine boundaries (tcp) or even as web services. Create facades as needed to provide access to the functionality of your other, smaller services.
There's no real need to avoid putting any logic in WCF service classes.
I think that the decision depends on your business needs. WCF is a mechanism to transport data (objects) between server and client. If you like your businsess logic runs on server, you should let WCF exposes the object after running your business logic.
It should go in a separate set of classes. Your WCF layer should only contain logic that directly pertains to how the product of the service is delivered.
In your case, I see that you have a WCF method that returns a User (I assume this is a custom class) why have a separate method to return the UserID instead of populating that property as part of returning the User object?
For reuse/testability/maintenance/readability you should always put you BL in a separate layer.
I have a WCF Service that exposes two endpoints. One with a WebHttpBinding (acting as a REST service for mobile clients) and one with a NetTcpBinding (used for desktop .NET clients)
Let's say that a client accesses the service method GetData. If there is no data I will return ´null´ (or false or ´0´ depending on what has been called). If the client is a mobile client accessing the WebHttpBinding-endpoint, I would like to change the HttpStatusCode to something other than OK.
Is there a way of doing this and still keeping my service implementation general (not putting any http-specific code there)? I know that I can use IDispatchMessageInspector to intercept the message and change the status code, and only do this for the WebHttpBinding-endpoint, but then I wouldn't really know what to change the status code to...
Is there anyone who has a suggestion as to how I can solve this?
Update:
I'm starting to think that there really is no way to do this in a nice way, since the only place I actually really know what when wrong is in the service implementation.
Edit: the nice way: Seperation of concerns (SoC). The REST implementation only adds REST concerns to the service and inherits the base implementation which does the whole business logic.
I'm hosting some SOAP services with WCF. How can I turn off these services via config for the purposes of maintenance, etc., and provide a friendly message to the service consumer with something like "The service you've requested is down for maintenance."?
You would have to have a second service, that offered the same interface, same methods etc., that would all return that friendly message instead of a real result.
That might get a bit trickier when those service methods don't just return a string but a complex data object - where do you put that "friendly" message??
In reality I think this cannot really be done - since your services typically aren't "seen" by actual people, you cannot just put up an app_offline.htm file or anything like that.
Try to have as little downtime as possible, by e.g. setting up your new version of the service on a new port and testing it there, until you're confident enough to switch over.
With WCF, it's mostly an exercise of updating / copying around the appropriate config, so your service should never really be unavailable for any extended period of time (hopefully!).
If you really must, what you could do, is just have a replacement service that will always throw a FaultContract<ServiceDownForMaintenance> - but then all the clients calling your service would have to know about this and they would have to handle this case and present an error or information message. Your service can't really provide that...
How about this: create a custom ServiceBehavior to intercept my incoming requests to the service. Then, have the custom behavior check a user-defined flag in my config file, something like <add key="IsMyServiceUp" value="true" /> and if that value returns as false then throw a ServiceException with my friendly message and HTTP code of 503 - Service Unavailable.
Does that sound reasonable? Then all I have to do is change the flag in my config file to specify where the service is up or down.
Okay, so I've created a new Custom Behavior that implements IOperationBehavior. In the Validate method, I've got
public void Validate(OperationDescription operationDescription)
{
bool isServiceUp = Boolean.Parse(ConfigurationManager.AppSettings["IsOrderServiceUp"].ToString());
if (!isServiceUp)
{
throw new ServiceException(ServiceErrorCode.Generic_Server_Exception,
ServiceErrors.Generic_Server_Exception,
SoapFaultCode.Server);
}
}
The other implemented methods ApplyClientBehavior, ApplyDispatchBehavior and AddBindingParameters are all empty.
I have decorated one of my service operations with [ServiceStatusValidation] which is the class name of my custom behavior.
When I start the service and navigate to the operation with this decoration, I do NOT get the exception I've thrown. SOAP UI shows nothing as returned in the response pane, and my consuming REST facade gives a generic 400 error with The exception message is 'The server did not provide a meaningful reply; this might be caused by a contract mismatch, a premature session shutdown or an internal server error.'.
Any ideas? Should I be doing this logic in one of the other methods that I didn't implement instead of the Validate method?
In some enterprise-like project (.NET, WCF) i saw that all service contracts accept a single Request parameter and always return Response:
[DataContract]
public class CustomerRequest : RequestBase {
[DataMember]
public long Id { get; set; }
}
[DataContract]
public class CustomerResponse : ResponseBase {
[DataMember]
public CustomerInfo Customer { get; set; }
}
where RequestBase/ResponseBase contain common stuff like ErrorCode, Context, etc. Bodies of both service methods and proxies are wrapped in try/catch, so the only way to check for errors is looking at ResponseBase.ErrorCode (which is enumeration).
I want to know how this technique is called and why it's better compared to passing what's needed as method parameters and using standard WCF context passing/faults mechanisms?
The pattern you are talking about is based on Contract First development. It is, however not necessary that you use the Error block pattern in WCF, you can still throw faultexceptions back to the client, instead of using the Error Xml block. The Error block has been used for a very long time and therefore, a lot of people are accustom to its use. Also, other platform developers (java for example) are not as familiar with faultExceptions, even though it is an industry standard.
http://docs.oasis-open.org/wsrf/wsrf-ws_base_faults-1.2-spec-os.pdf
The Request / Response pattern is very valuable in SOA (Service Oriented Architecture), and I would recommend using it rather than creating methods that take in parameters and pass back a value or object. You will see the benefits when you start creating your messages. As stated previously, they evolved from Contract First Development, where one would create the messages first using XSDs and generate your classes based on the XSDs. This process was used in classic web services to ensure all of your datatypes would serialize properly in SOAP. With the advent of WCF, the datacontractserializer is more intelligent and knows how to serialize types that would previously not serialize properly(e.g., ArrayLists, List, and so on).
The benefits of Request-Response Pattern are:
You can inherit all of your request and responses from base objects where you can maintain consistency for common properties (error block for example).
Web Services should by nature require as little documentation as possible. This pattern allows just that. Take for instance a method like public BusScheduleResponse GetBusScheduleByDateRange(BusDateRangeRequest request); The client will know by default what to pass in and what they are getting back, as well, when they build the request, they can see what is required and what is optional. Say this request has properties like Carriers [Flag Enum] (Required), StartDate(Required), EndDate(Required), PriceRange (optional), MinSeatsAvailable(Option), etc... you get the point.
When the user received the response, it can contain a lot more data than just the usual return object. Error block, Tracking information, whatever, use your imagination.
In the BusScheduleResponse Example, This could return Multiple Arrays of bus schedule information for multiple Carriers.
Hope this helps.
One word of caution. Don't get confused and think I am talking about generating your own [MessageContract]s. Your Requests and Responses are DataContracts. I just want to make sure I am not confusing you. No one should create their own MessageContracts in WCF, unless they have a really good reason to do so.
I have a WPF appliction that uses WCF services to make calls to the server.
I use this property in my code to access the service
private static IProjectWcfService ProjectService
{
get
{
_projectServiceFactory = new ProjectWcfServiceFactory();
return _projectServiceFactory.Create();
}
}
The Create on the factory looks like this
public IProjectWcfService Create()
{
_serviceClient = new ProjectWcfServiceClient();
//ToDo: Need some way of saving username and password
_serviceClient.ClientCredentials.UserName.UserName = "MyUsername";
_serviceClient.ClientCredentials.UserName.Password = "MyPassword";
return _serviceClient;
}
To access the service methods I use somethingn like the following.
ProjectService.Save(dto);
Is this a good approach for what I am trying to do? I am getting an errorthat I can't track down that I think may be realted to having too many service client connections open (is this possible?) notice I never close the service client or reuse it.
What would the best practice for WCF service client's be for WPF calling?
Thanks in advance...
You're on the right track, I'd say ;-)
Basically, creating the WCF client proxy is a two-step process:
create the channel factory
from the channel factory, create the actual channel
Step #1 is quite "expensive" in terms of time and effort needed - so it's definitely a good idea to do that once and then cache the instance of ProjectWcfServiceFactory somewhere in your code.
Step #2 is actually pretty lightweight, and since a channel between a client and a service can fall into a "faulted state" when an exception happens on the server (and then needs to be re-created from scratch), caching the actual channel per se is less desirable.
So the commonly accepted best practice would be:
create the ChannelFactory<T> (in your case: ProjectWcfServiceFactory) once and cache it for as long as possible; do that heavy lifting only once
create the actual Channel (here: IProjectWcfService) as needed, before every call. That way, you don't have to worry about checking its state and recreating it as needed
UPDATE: "what about closing the channel?" asks Burt ;-) Good point!!
The acccepted best practice for this is to wrap your service call in a try....catch....finally block. The tricky part is: upon disposing of the channel, things can do wrong, too, so you could get an exception - that's why wrapping it in a using(....) block isn't sufficient.
So basically you have:
IProjectWcfService client = ChannelFactory.CreateChannel();
try
{
client.MakeYourCall();
}
catch(CommunicationException ce)
{
// do any exception handling of your own
}
finally
{
ICommunicationObject comObj = ((ICommunicationObject)client);
if(comObj.State == CommunicationState.Faulted)
{
comObj.Abort();
}
else
{
comObj.Close();
}
}
And of course, you could definitely nicely wrap this into a method or an extension method or something in order not to have to type this out every time you make a service call.
UPDATE:
The book I always recommend to get up and running in WCF quickly is Learning WCF by Michele Leroux Bustamante. She covers all the necessary topics, and in a very understandable and approachable way. This will teach you everything - basics, intermediate topics, security, transaction control and so forth - that you need to know to write high quality, useful WCF services.
Learning WCF http://ecx.images-amazon.com/images/I/41wYa%2BNiPML._BO2,204,203,200_PIsitb-sticker-arrow-click,TopRight,35,-76_AA240_SH20_OU01_.jpg
The more advanced topics and more in-depth look at WCF will be covered by Programming WCF Services by Juval Lowy. He really dives into all technical details and topics and presents "the bible" for WCF programming.