I am working on a client that is consuming a WCF service. In various cases, the service simply raises a FaultException with an associated message informing of the reason behind the given fault.
Some of these faults are things that can be handled by our client application, but I'm hesitant to simply try and perform some string matching on the FaultExceptions Message or Reason to determine if it is something we can cater for or not.
I was hoping that the FaultCode on FaultException could be used to identify a specific type of Fault that we could handle, but it seems that this is purely to identify a handful of SOAP faults. Please correct me if my interpretation of this is incorrect.
I know that it could be that a FaultException could be raised, but I feel it is unrealistic to expect that a new type should be created for each reason behind a fault.
How do you handle this situation. As a contrived example. Consider a service that provides the following methods;
RecordDetails GetRecordById(string id)
void Add(RecordDetails record)
void Update(RecordDetailsUpdateRequest rdur)
Now in the example above, if you call GetRecordById with an id that doesn't exist, you receive a FaultException with a Message stating "Record cannot be found". Similarly, if you call Add for a record that already exists, or Update for a record that doesn't exist, you simply get a FaultException with a Message/Reason detailing the reason for failure. I need to know if a record exists or not to determine whether I should update or insert. As I mentioned, I'm hesitant to simply match on strings as I have no control over whether they will remain the same or not.
What would you expect in this situation (a type associated with the FaultException detailing RecordNotFoundException etc) or some generic type associated with FaultException that defines specific details relating to the error. For example, a RecordOperationExcpetion class with members Code (a constant or enum identifier of the reason for failure), along with a user friendly message.
At least this way, I could identify the error cause without having to resort to string matching.
Your thoughts are appreciated.
I would go with what you said above - a type associated with the FaultException. You can create any number of classes represented as a DataContract to handle various faults, and then assign them to the WCF Service operations.
[DataContract]
public class RecordOperationException
{
private int code;
private string message;
[DataMember]
public int Code
{
get
{
return code;
}
set
{
code = value;
}
}
[DataMember]
public string Message
{
get
{
return message;
}
set
{
message = value;
}
}
}
Then you can assign the this class as a FaultException:
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
RecordDetails GetRecordById(string id)
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
void Add(RecordDetails record)
[OperationContract]
[FaultContract(typeof(RecordOperationException))]
void Update(RecordDetailsUpdateRequest rdur)
You can then throw the appropriate FaultException in your methods, as desired.
This will eliminate the need to compare strings (which is a good idea, IMO).
I always use FaultExceptions and advertise them as part of the OperationContract, as your code does.
However, I think that there is more to it than this.
We all know that separation of concerns is a good thing, and the way you can achieve this with your services is by created classes that implement IErrorHandler.
These can then be used with your class and your error handling can be separated from your logic, making a cleaner way to do this. It also means that you don't have to repeat identical blocks all over your code.
This can be used with the generic FaultException as well.
A good resource is: http://msdn.microsoft.com/en-us/library/system.servicemodel.dispatcher.ierrorhandler.aspx
Related
I've the following method:
attemptToGetToken(TokenRequestAttempt attempt);
I use a third party component to get the token but it may fail in some case (in the attempt is not valid or missing parameters).
There is no reason to throw an Exception for this case because it is actually expected to fail.
However, depending on the result, the end-user may acts accordingly.
It means I need to return an Object which allows the user to decide what it can/should do.
The probably most obvious answer would be to simply have such class:
class AttemptResult {
constructor(status, token, errorMessage);
getStatus();
getToken();
getErrorMessage();
isSuccessful();
}
And simply return this object properly populated (I may add specific factory method for success/fail state, but it would be just a tool).
The problem I have with this approach is that the contract is not clear.
In the case of failure, the token would be null but the developper would then have to use the isSuccessful() method to check wether or not the attempt succeed.
But nothing will prevent him to call getToken() and get a null result which may bubble an error somewhere.
So I'm wondering if it wouldn't be better to actually return two kind of object.
interface TokenAttemptResult {}
class FailedTokenAttempt implements TokenAttemptResult {
getError();
}
class SuccessfulTokenAttempt implements TokenAttemptResult {
getToken();
}
Because I implement an empty interface to define a relationship between the both result, I may now use this interface as a return type in my service:
TokenAttemptResult attemptToGetToken(TokenRequestAttempt attempt);
When an user calls the method above, he is in charge to check the return type and act accordingly, it prevents him to call method which should not be supposed to be called and may generate side effects.
What do you think about this kind of design?
Any of you has experimented with it and has any feedbacks?
Please avoid unconstructive answer involving personal preferences without actual arguments, I'm really looking for serious design theories.
Thanks!
The subclassing approach will work, however since interfaces are open, the client has no way of being sure that they have exhaustively checked all possible implementing types of the interface. The OO approach to closing the possible cases is the visitor pattern e.g.
public interface TokenResultVisitor<TResult> {
TResult Visit(FailedTokenAttempt failure);
TResult Visit(SuccessfulTokenAttempt success);
}
and then
interface TokenAttemptResult {
T Accept<T>(TokenResultVisitor visitor);
}
This is a fairly heavyweight approach if you only have two possible cases, so if your language supports first-class functions you can simply define a method which takes two handlers e.g.
interface TokenAttemptResult {
T Handle<T>(success: Result => T, failure: TokenError => T);
}
I am using WCF service with Winform client. I am creating a data cache by calling WCF service multiple times.
one of my service call is failing because of error...
The communication object, System.ServiceModel.Security.SecuritySessionClientSettings1+ClientSecurityDuplexSessionChannel[System.ServiceModel.Channels.IDuplexSessionChannel], cannot be used for communication because it is in the Faulted state.`
code block, which is throwing error...
return _wcfClient.GetGroups().ToList());
This error behavior is random. Sometimes it works without any issue and sometimes it throw given error
I tired to debug the issue but client call never reach to WCF service.
Can anyont help me to understand why this is happening and how can I fix it.
UPdated question with code:
I am using casle windsor DI to resolve dependencies.
that's how registering service with DI...
container.Register(Component.For<IWCFDataService>()
.AsWcfClient(DefaultClientModel.On(
WcfEndpoint.ForContract<IWCFDataService>().FromConfiguration("Binding_IWCFDataService")))
);
Then dependencies will be injected in class constructor
Code to call service
public List<string> SomePRoperty
{
get
{
lock (_lockObjectSomePRoperty)
{
return _localvariable ?? (_localvariable = wcfClientResolvedFromDI.GetGroups().ToList());
}
}
set { _localvariable = value; }
}
This error happens in case you pass an object in an invalid state. For examle, say GetGroups returns a collection of Group objects, such that Group contains an enum field, say, GroupType. Then if the server side prepares the collection with an invalid enum value, say, (GroupType)36252, while C# doesn't throw an exception on such conversion (see Why does casting int to invalid enum value NOT throw exception?), the stricter WCF throw a security-related exception, as if something messed with your values.
What is the best practice regarding returning error codes?
Sometimes we meet situations where a class method operation is unsuccessful, but it is not exceptional. If the reason why it fails are varied, then we need a way to tell the caller why it has failed.
For example, I have Actor::equipItem() method that equips an item to an RPG character object. The reasons for failure could be:
Character level is not high enough.
Character class cannot equip that item.
Character attribute is not sufficient (e.g. not enough strength).
The item is already broken.
The item is a two handed weapon and the character is already wielding a dagger.
etc.
The way I see it, the situations above are not exceptional. I can implement Actor::equipItem() in two ways.
First is returning int codes, like 0 for success and 1 for the level is not enough, 2 for wrong character class and so on.
The second is returning boolean TRUE or FALSE, and implementing Actor::getLastErrorCode() that the caller can inspect if it needs to provide a feedback to the user.
Which of the two is the best practice in terms of OOP and API design? Are there alternatives? Is there a best practice for handling error codes that are not exceptional situations?
Like I said, I agree with cHao that throwing exceptions is the right way to handle this. However, I wanted to comment on how you might decide to process all of those rules. This scenario is a perfect situation for a rules engine, using good ol' polymorphism. (Checking out the chain of responsibility (CoR) design pattern would be good for this.)
You could use a bunch of if statements in your method. Or, better yet, have each if check be its own class that implements something like IEquipItemRule:
public interface IEquipItemRule
{
bool CanEquip();
}
Then, instead of an if statement, your consuming code can process all of the rules like this:
List<IEquipItemRule> equipRules = GetEquipRules(); // This is where the CoR pattern comes in
foreach (IEquipItemRule rule in equipRules)
{
// Note: Instead of throwing immediately, you could collect all of the
// messages and return all of the failure reasons.
if (!rule.CanEquip()) { throw new AppropriateException(rule.Message); }
}
The nice thing about this is that this check can be in its own method. So, if you want to check first to see if this method will succeed, the consumer can call the above code. And when the actual method runs, it can call this checking code as well.
Note: An example of an equipment rule might be something like this:
public class CharacterLevelRule : IEquipItemRule
{
public bool CanEquip()
{
if (characterLevel <= necessaryLevel) { return false; }
return true;
}
}
I'm just looking for some general advice with this one please. My WCF WebMethod needs to work across applications using different software, e.g. ASP.NET --> Java, for example.
I know that in the event of a method failing, I can utilize FaultException(Of MyError) to generate a SOAP Fault, however, what is generally the best way to send a success message?
Take for example the following interface that defines functionality for saving a user into a database:
<ServiceContract()>
Public Interface IService1
<OperationContract()>
Sub SaveUserIntoDataBase(ByVal u As MyAppUser)
End Interface
<DataContract()>
Public Class MyAppUser
<DataMember()>
Public Property FirstName() As String
<DataMember()>
Public Property Surname() As String
End Class
If I needed to send feedback that the user was saved successfully, how would this be generally done? Is there a 'success' equivalent of a FaultException, or is it recommended to just return Boolean or a String?
I suppose a value should always be returned?
There isn't any equivalent success result to exception if execution of service call doesn't fail.
One option is to create some customzed types such as enums and return those based upon different results from underlying source.
The return types of every call may be different or customized to user needs. Returning a boolean value is better than some string value in your case. Also you are using a "Sub", so if its a function then this could be one case.
You can follow some discussion here as well:
Whats the best practice for returning a Boolean and string value
There is no need for a success message. If the operation did not fail, then it was a success.
Use a FaultException to indicate failure.
Soliciting feedback/options/comments regarding a "best" pattern to use for reference data in my services.
What do I mean by reference data?
Let's use Northwind as an example. An Order is related to a Customer in the database. When I implement my Orders Service, in some cases I'll want the reference a "full" Customer from an Order and other cases when I just want a reference to the Customer (for example a Key/Value pair).
For example, if I were doing a GetAllOrders(), I wouldn't want to return a fully filled out Order, I'd want to return a lightweight version of an Order with only reference data for each order's Customer. If I did a GetOrder() method, though, I'd probably want to fill in the Customer details because chances are a consumer of this method might need it. There might be other situations where I might want to ask that the Customer details be filled in during certain method calls, but left out for others.
Here is what I've come up with:
[DataContract]
public OrderDTO
{
[DataMember(Required)]
public CustomerDTO;
//etc..
}
[DataContract]
public CustomerDTO
{
[DataMember(Required)]
public ReferenceInfo ReferenceInfo;
[DataMember(Optional)]
public CustomerInfo CustomerInfo;
}
[DataContract]
public ReferenceInfo
{
[DataMember(Required)]
public string Key;
[DataMember(Required)]
public string Value;
}
[DataContract]
public CustomerInfo
{
[DataMember(Required)]
public string CustomerID;
[DataMember(Required)]
public string Name;
//etc....
}
The thinking here is that since ReferenceInfo (which is a generic Key/Value pair) is always required in CustomerDTO, I'll always have ReferenceInfo. It gives me enough information to obtain the Customer details later if needed. The downside to having CustomerDTO require ReferenceInfo is that it might be overkill when I am getting the full CustomerDTO (i.e. with CustomerInfo filled in), but at least I am guaranteed the reference info.
Is there some other pattern or framework piece I can use to make this scenario/implementation "cleaner"?
The reason I ask is that although we could simply say in Northwind to ALWAYS return a full CustomerDTO, that might work fine in the simplistic Northwind situation. In my case, I have an object that has 25-50 fields that are reference/lookup type data. Some are more important to load than others in different situations, but i'd like to have as few definitions of these reference types as possible (so that I don't get into "DTO maintenance hell").
Opinions? Feedback? Comments?
Thanks!
We're at the same decision point on our project. As of right now, we've decided to create three levels of DTOs to handle a Thing: SimpleThing, ComplexThing, and FullThing. We don't know how it'll work out for us, though, so this is not yet an answer grounded in reality.
One thing I'm wondering is if we might learn that our services are designed at the "wrong" level. For example, is there ever an instance where we should bust a FullThing apart and only pass a SimpleThing? If we do, does that imply we've inappropriately put some business logic at too high of a level?
Amazon Product Advertising API Web service is a good example of the same problem that you are experiencing.
They use different DTOs to provide callers with more or less detail depending on their circumstances. For example there is the small response group, the large response group and in the middle medium response group.
Having different DTOs is a good technique if as you say you don't want a chatty interface.
It seems like a complicated solution to me. Why not just have a customer id field in the OrderDTO class and then let the application decide at runtime whether it needs the customer data. Since it has the customer id it can pull the data down when it so decides.
I've decided against the approach I was going to take. I think much of my initial concerns were a result of a lack of requirements. I sort of expected this to be the case, but was curious to see how others might have tackled this issue of determining when to load up certain data and when not to.
I am flattening my Data Contract to contain the most used fields of reference data elements. This should work for a majority of consumers. If the supplied data is not enough for a given consumer, they'll have the option to query a separate service to pull back the full details for a particular reference entity (for example a Currency, State, etc). For simple lookups that really are basically Key/Value pairs, we'll be handling them with a generic Key/Value pair Data Contract. I might even use the KnownType attribute for my more specialized Key/Value pairs.
[DataContract]
public OrderDTO
{
[DataMember(Required)]
public CustomerDTO Customer;
//in this case, I think consumers will need currency data,
//so I pass back a full currency item
[DataMember(Required)]
public Currency Currency;
//in this case, I think consumers are not likely to need full StateRegion data,
//so I pass back a "reference" to it
//User's can call a separate service method to get full details if needed, or
[DataMember(Required)]
public KeyValuePair ShipToStateRegion;
//etc..
}
[DataContract]
[KnownType(Currency)]
public KeyValuePair
{
[DataMember(Required)]
public string Key;
[DataMember(Required)]
public string Value;
//enum consisting of all possible reference types,
//such as "Currency", "StateRegion", "Country", etc.
[DataMember(Required)]
public ReferenceType ReferenceType;
}
[DataContract]
public Currency : KeyValuePair
{
[DataMember(Required)]
public decimal ExchangeRate;
[DataMember(Required)]
public DateTime ExchangeRateAsOfDate;
}
[DataContract]
public CustomerDTO
{
[DataMember(Required)]
public string CustomerID;
[DataMember(Required)]
public string Name;
//etc....
}
Thoughts? Opinions? Comments?
We've faced this problem in object-relational mapping as well. There are situations where we want the full object and others where we want a reference to it.
The difficulty is that by baking the serialization into the classes themselves, the datacontract pattern enforces the idea that there's only one right way to serialize an object. But there are lots of scenarios where you might want to partially serialize a class and/or its child objects.
This usually means that you have to have multiple DTOs for each class. For example, a FullCustomerDTO and a CustomerReferenceDTO. Then you have to create ways to map the different DTOs back to the Customer domain object.
As you can imagine, it's a ton of work, most of it very tedious.
One other possibility is to treat the objects as property bags. Specify the properties you want when querying, and get back exactly the properties you need.
Changing the properties to show in the "short" version then won't require multiple round trips, you can get all of the properties for a set at one time (avoiding chatty interfaces), and you don't have to modify your data or operation contracts if you decide you need different properties for the "short" version.
I typically build in lazy loading to my complex web services (ie web services that send/receive entities). If a Person has a Father property (also a Person), I send just an identifier for the Father instead of the nested object, then I just make sure my web service has an operation that can accept an identifier and respond with the corresponding Person entity. The client can then call the web service back if it wants to use the Father property.
I've also expanded on this so that batching can occur. If an operation sends back 5 Persons, then if the Father property is accessed on any one of those Persons, then a request is made for all 5 Fathers with their identifiers. This helps reduce the chattiness of the web service.