WCF generic faultException becomes non-generic
-
viernes, 27 de julio de 2012 13:39
Good morning everyone,
In our project (WCF 4.0) we have created several faults to address certain types of business logic errors. We have a multi-level services architecture, so in the lowest level I can throw faults that should go through the upcoming layers until the client.
The problem is that we are throwing some faults from any level and when the fault must pass another level of services, the faults stop being generic and they become non-generic faults.
I have checked and all the method signatures include the faults (as an attribute) that might come from itself or from the lower levels.
Any hints, tips or tricks will be appreciated.
I need to do, I need to know.
Todas las respuestas
-
viernes, 27 de julio de 2012 17:56
Can u provide some example what you are trying to do ....
You cant return FaultExcetion<T> ... it gotta be some type of faultexception ....
Tanvir Huda Application Architect/Consultant http://thetechnocrate.wordpress.com/
-
viernes, 27 de julio de 2012 20:18
Hi Tanvir,
Sure, I'll provide some example.
First, I have a shared DLL that holds the fault I throw, this is how it looks:
[DataContract(Namespace = "uri://MyDomain/fault/Basic")] public class MissingRecordFault : FaultBaseClass { }In one facade service I have a "Save" operation that calls an other service where all the CRUD operations are located:
Facade service (interface):
[OperationContract] [FaultContract(typeof(SomeFault))] [FaultContract(typeof(AnotherFault))] [FaultContract(typeof(MissingRecordFault))] void SaveItems(Items[] itemsToSave);
CRUD service (interface):
[OperationContract] [FaultContract(typeof(MissingRecordFault))] void DeleteItem(Item item);
CRUD Service (implementation):
public void DeleteItem(Item item){ //...more code here if(RecordDoesNotExist){ throw new FaultException<MissingRecordFault>(new MissingRecordFault()); } }So if the DeleteItem method throws a fault, this will bubble up to the facade service (save method) and it will go to the client, where the client is getting a non-generic exception, I mean the client catches a FaultException, he is not able to catch a FaultException<MissingRecordFault> as intended.
try{ service.SaveItems(myItems); } catch(FaultException<MissingRecordFault>){ //It does not stop here } catch(FaultException){ //Here it does enter and it is not supposed to do it. }
So it seems like the fault is loosing its generic type somewhere in between the facade service and the client.I need to do, I need to know.
-
sábado, 28 de julio de 2012 14:48
Hi
I have coded the same and it is working fine ....I have created a Crud Service and Business Service ... Business Service has a reference to CRUD Service and crud service method generate FaultException<MissingRecordFault> ... Business Service catch that fault and regenerate the fault to client ... Client has a reference to Business Service. MissingRecordFault is created a separate class library and shared across the service ... See the below
Service for CRUD .... Just throwing an exception
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using Contracts; namespace CrudService { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together. public class TestCrudService : ITestCrudService { public string DeleteItem(int value) { throw new FaultException<MissingRecordFault>(new MissingRecordFault { FaultReason = "Record missing.Not found in the repository" }); } } }
Service for Business layer
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Serialization; using System.ServiceModel; using System.ServiceModel.Web; using System.Text; using Contracts; namespace TestBusinessService { // NOTE: You can use the "Rename" command on the "Refactor" menu to change the class name "Service1" in code, svc and config file together. public class Service1 : IService1 { public string GetData(int value) { try { TestCrudService.TestCrudServiceClient client = new TestCrudService.TestCrudServiceClient(); client.DeleteItem(1); return "done"; } catch (FaultException<MissingRecordFault> ex) { throw new FaultException<MissingRecordFault>(new MissingRecordFault { FaultReason = ex.Detail.FaultReason }); } catch (Exception ex) { throw ex; } } } }
Client
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel;
using ConsoleApplication1.TBS;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
try
{
TBS.Service1Client clt = new TBS.Service1Client();
clt.GetData(1);
}
catch (FaultException<MissingRecordFault> ex)
{
Console.WriteLine(ex.Detail.FaultReason);
}
Console.Read();
}
}
}
Generic Fault Exception
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.Serialization;
using System.ServiceModel;
namespace Contracts
{
[DataContract]
public class MissingRecordFault
{
[DataMember]
public string FaultReason;
}
}
Tanvir Huda Application Architect/Consultant http://thetechnocrate.wordpress.com/
-
domingo, 29 de julio de 2012 18:10
Well, thanks a lot for the effort Tavir, it seems like there is something else causing the problem.
Thanks again.
I need to do, I need to know.
-
domingo, 29 de julio de 2012 23:52May be you are getting some communication exception from Service A to Service B. Enable Tracing in your services, that will tell you whats going wrong.
Tanvir Huda Application Architect/Consultant http://thetechnocrate.wordpress.com/
-
lunes, 30 de julio de 2012 13:22
Well, something I noticed is that the client gets a FaultException (non-generic type) and the action of the exception has the namespace of the MissingRecordFault ("uri://MyDomain/fault/Basic"), does it say anything?
Service A is getting the right fault (generic fault FaultException<MissingRecordFault>) from service B.
I need to do, I need to know.
-
martes, 31 de julio de 2012 2:23
did you add reference to your fault contract in your client as well ....
If you have done that then MissingRecordFault will refernce to that library not the proxy one i suppose .
You are getting "Uri//mydomain/fault/Basic" becuase you have declared a namespace in your DataContract. You can remove this attribute from your datacontract and try again to find out whether that makes any difference.
Tanvir Huda Application Architect/Consultant http://thetechnocrate.wordpress.com/
- Marcado como respuesta LeoTangModerator domingo, 05 de agosto de 2012 3:39
-
martes, 07 de agosto de 2012 11:46
Hi,
Yes, client has a reference to the dll where the fault is defined and I have not tried to remove the namespace from the fault definition, I am going to try some other things and we'll tell you how it went.
I need to do, I need to know.
-
viernes, 26 de abril de 2013 14:12Have you found a solution?

