best practice for return value in WCF services - wcf

I have a WCF service sitting in the cloud.
And my application makes several calls to this WCF service.
Is it a best practise:
1] to always use return value as bool which indicates if the operation was sucessful or not.
2] returning the values you meant to return as the OUT parameters

I would:
return an atomic value (bool, string, int) if appropriate
return a complex type (a class instance) if I need to return more than one value - make sure to mark that class with [DataContract] and its properties with [DataMember]
a SOAP fault FaultException<T> when an error occurs; the <T> part allows you to define your own custom error classes, and again - don't forget to mark them with [DataContract] / [DataMember] and declare them as FaultContract on your operations

1] to always use return value as bool which indicates if the operation was sucessful or not
Yes, if the operation isnĀ“t time consuming AND the return status is always relevant:
Waiting on a return value can affect both client and service host(server) performance/scalability. Ex. in a Request-Responsecall, Requests can keep connections open for a long preriod of time waiting for operation completion. You could implement in a way similar to "HTTP 202 Accepted" status code usage(i.e operation received arguments and has started(patially), but does wait for the completion)
No, if the operation logic only makes sense if synchronous.
No, if you are keen on refactorability/maintainability ex. when you want to return include an error message/code in the return.
2] returning the values you meant to return as the OUT parameters
Yes, this makes the service operation more wsdl compliant and easy to read.

Related

Spring Webflux HttpResponse

class Test{
public Mono<ServerResponse> test(ServerRequest req){
Mono<String> data = Mono.just("test");
System.out.print(data);
return ServerResponse.ok.body(data, String.class);
}
}
When the client makes a request, "MonoJust" is printed at line 4,
but "test" is returned in the Http Response Body.
I know that a publisher doesn't produce data before a subscription, so why does the Http Response contain "test" not "MonoJust"?
This behaviour might look a bit odd because you've just used Mono to wrap an actual value - but this is not what reactor (and reactive frameworks in general) are designed for.
Remember that Mono is a publisher which may or may not emit an element in the future, not just a wrapper for a given value. When you return ServerResponse.ok.body(), you're explicitly stating that you want the body to contain the result emitted by the publisher that you're passing in - the method then returns another publisher, Mono<ServerResponse>, that publishes the required server response when your data publisher emits a value.
System.out.print on the other hand is implicitly calling the toString() method on Mono, which needs to produce a value now, without blocking or waiting (it's returning a String after all, not a Mono<String>.) It can't print the value since it won't necessarily be there, so instead it just prints the name of its class (MonoJust in this case refers to the fact you've instantiated the Mono with Mono.just().)

Is getLastErrorCode() good API design for returning error codes?

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;
}
}

General advice on returning success messages in WCF WebMethods

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.

WCF Service Contract

I have a problem using an custom data type in a WCF service method, below is my sample code
[ServiceContract()]
public class SampleServise : ISampleServise
{
void object GetSomething(ICustomData objectData)
{
// Do Something
}
}
What shall I do with ICustomData class interface?
Thanks
Afshin
WCF is based on message passing, and that message passing is modelled using XML schema (XSD). As such, whatever can be expressed in XML schema can be used in WCF.
This also means: interfaces are not supported. You need to use actual, concrete types for the parameters in your WCF service methods.
In your case, create a concrete class that implements ICustomData and then use that class as the parameter type.
For a good reference, read MSDN Designing Service Contracts which states for parameters:
Parameters and Return Values
Each operation has a return value and a parameter, even if these are
void. However, unlike a local method, in which you can pass references
to objects from one object to another, service operations do not pass
references to objects. Instead, they pass copies of the objects.
This is significant because each type used in a parameter or return
value must be serializable; that is, it must be possible to convert an
object of that type into a stream of bytes and from a stream of bytes
into an object.

Handling WCF Faults

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