WCF Service FaultContract Understanding - c#

I have a WCF service and I have a FaultContract. I have a Reason in the FaultContract so I have something like this.
FltInfo.Reason = "This is a test";
throw new FaultException<FaultInfo>(FltInfo, new FaultReason(FltInfo.Reason));
Obviously, you see I have the FaultInfo class defined for my data contract. But what would I need to do or how would I do it if I want to get like the fault code, details, or a level (criticality type) aspect with it?
If I didn't include some of those would I still get a soap fault message?
Also, wouldn't the triggering of the faultexception from a TRY-CATCH (or what have you) terminate the communication in the send/receive aspect? Meaning if I have 1 message coming through the receive and that 1 message has a list of let's say 100 items (an array for instance), if I am processing through the array of 100 and I get to let's say the 30th item but it triggers the fault. Would I not lose everything (all 100) because a response was never done and only a fault?
Thanks

You can add the fault code,et using the various constructors of fault exception. And yes, if you leave them blank, you will get WCF default values. You are additionally correct that if you throw a fault exception when processing a single item in the list you will break out of the normal path and will return just your fault.
You can modify this by including your response type in part of the fault and some how marking a single part as invalid. Or your service can have a wrapper response type that allows you to mark specific parts of the data returned as invalid it it makes since to do so in your solution.

Related

WCF Stripping detail from System.SecurityException

I am implementing IErrorHandler for a WCF service, with the intention of automatically logging the messages.
During testing I decided to throw a System.SecurityException with an inner exception and some user defined data:
try
{
LevelTwo();
}
catch (Exception innerEx)
{
var outerEx = new SecurityException("Is security special?", innerEx);
outerEx.Data.Add("foo", "bar");
throw outerEx;
}
Yet when it hits my ProvideFault method in my error handler it has already been converted to a System.ServiceModel.FaultException with a Message of "Access is denied". The original message, exception type, data and inner exception have all been lost, and I cannot log them. Other exception types work as expected, exposing all those properties for logging.
I presume that there is a framework implementation of IErrorHandler that is hit first, and converts it, stripping the detail and providing a generic message, which is all well and good generally, but not when I want to log the details.
Somebody has posted the same issue on MSDN but didn't get any particularly good answers.
Ideally I would like to change the order of the error handlers so that mine is hit first - is this possible?
If not - is it possible to remove the existing handler, and if so, are there any undesirable consequences?
EDIT
Following Christian's advice below it appears that the exception is getting caught by the code in SyncMethodInvoker.Invoke()
catch (System.Security.SecurityException e)
{
DiagnosticUtility.TraceHandledException(e, TraceEventType.Warning);
throw DiagnosticUtility.ExceptionUtility.ThrowHelperError
(AuthorizationBehavior.CreateAccessDeniedFaultException());
}
I think this means that Security Exceptions are a very special case, and that there probably isn't a good way around this, but I would appreciate any suggestions.
I'm not a proper computer right now, so I cannot test it myself, but I think WCF indeed converts any SecurityException into what you observe.
If you look at the complete call stack of your "rethrown" SecurityExceptions, you should see stack frames hinting at the location where they originate. With that information you can look into http://sourceof.net/ to look at the relevant code.
Having that said, there are multiple implementations of IOperationInvoker in WCF that handle the different calling styles (async, sync, etc.) of service operations.
For an example see:
http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Dispatcher/SyncMethodInvoker.cs,181
http://referencesource.microsoft.com/#System.ServiceModel/System/ServiceModel/Dispatcher/AsyncMethodInvoker.cs,140
So, I think the order of IErrorHandlers is nothing that helps with this issue, as the exception gets converted/stripped/replaced before error handlers are even called.
I would consider creating my own fault type for security issues, like a SecurityFault type and then throwing that as FaultException<SecurityFault>(...). That fault type could have all the properties you want. Additionally, since the fault type is a DataContract and the properties are DataMembers, you don't risk getting serialization issues, because you may inadvertently put non-serializable data into the exception's Data.

WCF FaultException<SqlException> caught as CommunicationException

I have a WCF service where I am catching an SqlException and then returning it as a FaultException like this
throw new FaultException<SqlException>(...);
And on the client side, I am catching it like this
catch (FaultException<SqlException> e)
{
// do something with exception
}
catch (FaultException<Exception> e)
{
// do something with exception
}
I don't believe I have a problem in my web.config on the service side or the app.config on the client side (a winform client) as I am able to catch FaultException<ArgumentException>, FaultException<Exception>, etc. but not FaultException<SqlException>
I have not found anything indicating that I can't pass SqlExceptions down to the client, my operation contract is properly configured with things like [FaultContract(typeof(SqlException))], and [FaultContract(typeof(Exception))]
Anyone seen this or know for a fact that I can't (or maybe need to do something special to) pass faults of type SqlException down to the client? Thank you.
throw new FaultException<Exception> is not really how the WCF fault system is intended to be used. The type you specify is serialized across the wire in the <Detail> element of a SOAP fault. Normally, this type is a WCF data contract class that you write, e.g.
[DataContract]
public class MyFault {
[DataMember]
public string Message {get; set;}
}
throw new FaultException<Exception> happens to work because Exception is [Serializable], and the DataContractSerializer is capable of handling [Serializable] types as well as [DataContract] types.
However, there are serious limitations to this approach. The DataContractSerializer does not handle [Serializable] types very well. Only fields of primitive types (string, int, etc) will be transmitted correctly. That is just about OK for a very simple exception type, but for a complex type like SqlException, it's not good enough.
My suggested solution is: create your own dedicated data contract to pass back the data from SqlException that you require, then throw that instead. In fact, do this for all exception types, it's more secure and better practice. I use Enterprise Library Exception Shielding to handle this automatically. All that gets passed back to the client is a single GUID value identifying the error data in the server log.
Alternatively, if you are determined to go down the exception route, see this detailed article.
I ran into this problem because I had a breakpoint in the wrong place. I removed all breakpoints with Debug..Delete all Breakpoints (Ctrl-Alt-F9), and all of the CommunicationException exceptions disappeared and were replaced with the correct messages coming back.
Yes, the timeout is 60 seconds, so this never should have occurred, so it was probably some weird artifact of Visual Studio 2012.

WCF Exception handling with batch operations

I need an hint on this architectural problem.
My application calls different wcf services that perform specific tasks returning a list of model objects.
Say, I have a service which polls stock exchange titles returning a List<SeTitle>. [Purely fictional example, I'm reading a book on this subject]
If an exception happens in one or few elements of this list I have two options in the wcf service:
catch the exception, log it and return the List<>, but in this way I'll lose evidence of all the faulty items in my application.
throw an exception on first error, but in this way I won't receive any info even if only one item was "faulty".
My will is to go for a third option, meaning that I'll always return my List but with the evidence of faulty items.
My idea is to let all my model object extend a simple interface like (pardon names, they are horrible)
public interface IWcfReturnObject
{
public List<WarningModel> Warnings;
}
and
public class SeTitle : IWcfReturnObject
in a such a way each element of the list could have an associated List of Warnings/Error to be returned to the application and then to the interface.
My questions are:
Is my question clear to understand?! ;)
Do you think my desire (receive all element from wcf with warnings attached) is architecturally good?
Do you think it exists a better approach to solve this problem?
Thanks
M.
EDIT: I was doing research and looking at the first answer I think it is useful to give one solution I found on the NET
Possible Solutions
My way
Log with some kind of correlation and refer it on the business layer as decyclone suggested
AggregateException
I think you should log your exceptions/errors/warnings instead of sending them along with result data. You can always refer to log and maybe create an interface to see error log. But, common result data should not be mixed with exception data.

web service exception handling

I have a WebMethod that receives following types of parameters:
[WebMethod]
User(long userid,int number)
When Client sends parameter with different types from I want, I have to catch this error and write to database etc.
For example ArgumentExceptions...
How can I solve this?
Thanks.
Have you tried what happens when a client uses the wrong types?
I would expect the SOAP library to trap this and raise an exception.
Inside your own method you can only check the values of the incoming parameters. And that works just like inside a normal (non-web) method.
You can use the following approach:
Each web method will always return some sort of WebMethodResult.
For example
[WebMethod]
public WebMethodResult DoSomethng(guid p_userId)
{
IfMethodIsSuccessful()
{
WebMethodResultSuccess successResult = new WebMethod();
// Add required information into web method result object
return successResult;
}
else
{
WebMethodResultFailure failedResult = new WebMethodResultFailure();
return failedResult;
}
}
Idea here is that whenever web method is called it will return some sort of object.
In this case the WebMethodResult will be the parent class and WebMethodResultSuccess and WebMethodResult failure would inherit from the parent class.
Instead of IsMethodIsSuccessfull you can add your own logic, wrap everything into a try catch block and return success/failure results.
If you call the web methods from the java script or jquery, the exception won't be passed back to the client unless you use SOAP or some sort of alternative. By sending back custom objects, you can read them through javascrip/jquery and display appropriate message to the user.
Hope this makes sense.
In terms of logging, you should probably write a generic exception handling layer or look into open source alternatives.
You woulc catch specific exception and pass it to exception handling layer. Within that layer (dll) you'll log the exception either in the database or write into a flat file. DB is probably a better option since the data can be easily analysed.
Another alternative is to log into windows event log, but I personally don't like this because it's not that easy to produce statistics on the exceptions and I think it has a limit in size.

Web Service returning object with null fields

Never seen this one before.
WebService.Implementation imp = new WebService.Implementation();
WebService.ImplementationRequest req = new WebService.ImplementationRequest();
return imp.GetValue(req);
The object that imp returns is not null. It's returning an ImplementationResponse, as expected. But all of the fields in that object are null. Which is not expected. The WebService, currently, just returns some constant dummy data. We've tested this on another developer's machine, works just fine.
I suppose I should also note that the WebService should throw an exception if I pass null into the GetValue method. It doesn't. Not for me.
Any idea what could be wrong with my environment that could make a WebService return an object, but make every value in that object null? And somehow 'magically' return this mystery object when it should be throwing an exception?
That usually happens when there's a discrepancy between the generated code and the xml being returned by the web service so it cannot be deserialized.
Grab the wsdl again, regenerate all the proxy classes and try again. Make sure you are sending the correct dummy data.
Update:
This used to happen to me a lot because the web services weren't managed by my team and we wouldn't get any notice of changes made to the service. We ended up intercepting the soap messages in the web service pipeline for debugging. Here's a great resource to get you on your way.
You don't need to change anything in the pipeline, just grab the soap messages and save them so you have debug later. Most of the times it turned out to be just that, a change in the contract. Other times we wouldn't have a contract so there was no way of knowing of changes without catching the envelopes.
Anyway, even if it's not your problem I think it's a good thing to have.
Are the fields marked with < DataMember()> attributes as they won't serialize otherwise?
<DataMember()> _
Public Property SomeField() As String
Get
Return m_strSomeField
End Get
Private Set(ByVal value As String)
m_strSomeField= value
End Set
End Property
Also, consider using trace viewer to analyse the messages sent between the client and server. For info see:
https://stackoverflow.com/questions/560370/handling-wcf-proxy-null-return-issue
I suppose I should also note that the
WebService should throw an exception
if I pass null into the GetValue
method
You didn't pass null here,you passed in a request object.
Also, you need be able to debug into the web service to see what's going on there. I assume you are implementing this internally, since you can set it to constant dummy value.

Categories

Resources