WCF service throwing weird exception - c#

after 2 days of trying to find out why my service isn't working I finally find the cause. Everytime I try to throw a new FaultException<AuthenticationException>, the server isn't actually throwing this but catching it itself.
So what is happening is that when I throw the exception the server is crashing with an unhandled System.ServiceModel.FaultException1`.
Here is my custom exception class:
[DataContract]
public class AuthenticationException
{
private string validationError;
[DataMember]
public string ValidationError
{
set { validationError = value; }
get { return validationError; }
}
public AuthenticationException()
{
}
public AuthenticationException(string valError)
{
validationError = valError;
}
}
And my interface:
[ServiceContract]
public interface IAuthenticator
{
[OperationContract]
[FaultContract(typeof(AuthenticationException))]
Account authenticateApplication(string userName, string Password);
What can cause this?
Edit: This is how I am throwing the exception:
catch (Exception)
{
throw new FaultException<AuthenticationException>(new AuthenticationException("There was a general error during the process."), new FaultReason("Error"));
}

Maybe your IIS server is not configured to allow passing exception to the client.
Follow the step 2 "Enable detailed errors for remote clients." of this post

Related

Returning meaningful error messages from a .NET Core API

Scenario
I have a .NET Core 2.2 web API with an exception handling middleware. Whenever an exception occurs in the application (inside the MVC layer) it gets caught by the exception middleware and returned as an internal server error back to the frontend and logged to kibana.
The problem
This is all fine and well when things go wrong, but sometimes I want to notify the calling application of specifically what went wrong. I.e., "Could not find record in database!" or "Failed to convert this to that!"
My Solution
I've used application Exceptions (not great - I know) to piggy back off the error middleware to return this to the frontend. This has been working fine, but has created a lot of noise around the code by having to throw a whole bunch of exceptions. I'm not satisfied with this approach and convinced that there must be a better solution.
My application architecture: I'm following a traditional n-tier application layout being services (business logic) and repositories (DAL) all speaking to each other. I would preferably like to elegantly bubble up any issues back to the user in any of these layers.
I've been thinking about this for a while now and am not sure what the best way to go about it is. Any advice would be appreciated.
I use a kind of the operation result pattern (non-official pattern).
The principle is to return a new Type containing:
Whether the operation was a success.
The result of the operation if was successful.
Details about the Exception that caused the failure.
Consider the following class:
public class OperationResult
{
protected OperationResult()
{
this.Success = true;
}
protected OperationResult(string message)
{
this.Success = false;
this.FailureMessage = message;
}
protected OperationResult(Exception ex)
{
this.Success = false;
this.Exception = ex;
}
public bool Success { get; protected set; }
public string FailureMessage { get; protected set; }
public Exception Exception { get; protected set; }
public static OperationResult SuccessResult()
{
return new OperationResult();
}
public static OperationResult FailureResult(string message)
{
return new OperationResult(message);
}
public static OperationResult ExceptionResult(Exception ex)
{
return new OperationResult(ex);
}
public bool IsException()
{
return this.Exception != null;
}
}
Then you could easily adapt OperationResult or create a class that inherits from OperationResult, but uses a generic type parameter.
Some examples:
The Operation Result Pattern — A Simple Guide
Error Handling in SOLID C# .NET – The Operation Result Approach
As per the Microsoft's standards, it is ideal to use ProblemDetails object in case of 4xx/5xx exceptions -
Following is the customised RequestDelegate method which you can use in ApiExceptionHandler to handle exceptions.
public async Task RequestDelegate(HttpContext context)
{
var exception = context.Features.Get<IExceptionHandlerFeature>().Error;
var problemDetails = new ProblemDetails
{
Title = "An unexpected error occurred!",
Status = GetStatusCode(exception),
Detail = _env.IsDevelopment() ? exception.Message : "An unexpected error occurred!",
Instance = $"{Environment.MachineName}:{context.TraceIdentifier}:{Guid.NewGuid()}"
};
_logger.LogError($"Exception thrown. StatusCode: {problemDetails.Status}. Instance: {problemDetails.Instance}", exception);
context.Response.StatusCode = problemDetails.Status.Value;
context.Response.WriteJson(problemDetails, "application/problem + json");
await Task.CompletedTask;
}

Cannot perform simple GET request to Nancy self-hosted: RuntimeBinderException and ViewNotFoundException

My code:
public class MyWebService : IDisposable
{
private readonly NancyHost _host;
public MyWebService(int port = 7017)
{
var uri = new Uri(string.Format("http://localhost:{0}", port));
_host = new NancyHost(uri);
_host.Start();
}
public void Dispose()
{
if (_host != null)
{
_host.Stop();
_host.Dispose();
}
}
}
internal class MyWebModule : NancyModule
{
public MyWebModule()
{
Get["/"] = _ => "Received GET request";
}
}
When running following HTTP request: GET http://localhost:7017/ using Insomnia REST client, I'm getting following cryptic exceptions:
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'Cannot convert type 'Nancy.ErrorHandling.DefaultStatusCodeHandler.DefaultStatusCodeHandlerResult' to 'Nancy.Response''
at CallSite.Target(Closure , CallSite , Object )
With Source: Anonymously Hosted DynamicMethods Assembly
followed up by
Nancy.ViewEngines.ViewNotFoundException
at Nancy.ViewEngines.DefaultViewFactory.GetRenderedView(String viewName, Object model, ViewLocationContext viewLocationContext)
without any additional infromation on exception.
The REST client then shows error 404.
What have I defined wrong? I've followed the following example: building-a-simple-http-server-with-nancy
If you run your code under debugger - ensure that thrown exception is actually unhandled. Code might throw exceptions and your debugger (if configured to do so) might break on them, even if those exceptions are handled (by some catch block). Since you receive 404 reply after all and not crash - I guess those exceptions are part of "normal" nancy flow and so are handled.
As for 404 - your module is internal and Nancy will not discover it. Make it public instead:
public class MyWebModule : NancyModule
{
public MyWebModule()
{
Get["/"] = _ => "Received GET request";
}
}

Error Handling with WCF Service and Client Application

In my case, I have a WCF Service (MyService.svc). I also have a client application that is instantiating and consuming the service contract.
What is the best way to handle exceptions at the service level and "transmit" them over to the client in an orderly and self-describing way?
If I have an unhandled exception on the WCF service, it seems as though that bubbles back to the client application as a CommunicationException.
But what's the best way to throw an exception at the service-level and have that same exception transmitted to the client-level? Or if I don't handle an exception at the service-level (or just re throw it at the service-level) how can that get explicitly directed to the client?
Or is that not typically how this SOA would work? What's the "right way" here?
Thanks!
First, if you want to pass the exception over the protocol, you have to wrap it in a faultexception, otherwise you will get a server error.
Use the FaultContract attribute over methods to enable faultContract and define the message you want to pass using creating a Message contract:
public interface IMyService
{
[OperationContract]
[FaultContract(typeof(Message))]
void WCFOperation();
}
[DataContract(Namespace = "http://www.mycompany.pt/myservice")]
public class Message
{
String _code;
[DataMember]
public String Code
{
get { return _code; }
set { _code = value; }
}
String _text;
[DataMember]
public String Text
{
get { return _text; }
set { _text = value; }
}
}
To convert exceptions to FaultExceptions, i use the following helper:
class Helper
{
internal static System.ServiceModel.FaultException<Message> ConvertToSoapFault(MyException ex)
{
FaultCode fc = new FaultCode(ex.Code);
return new FaultException<Message>(new Message(){ Text= ex.Message, Code= ex.Code});
}
internal static System.ServiceModel.FaultException ConvertToSoapFault(Exception ex)
{
return new FaultException(ex.Message);
}
}
Finally, at the operationContract implementation, simple do this:
public void WCFOperation()
{
try
{
...
}
catch (Exception ex)
{
Helpers.publishError(ex);
throw Helpers.ConvertToSoapFault(ex);
}
}

WCF error "Sequence contains no elements" - "Collection was Out Of fixed size"

I am new in WCF. I'm starting to create a WCF project that save people's information in EF database.
I had lots of errors and fixed them by searching in various sites but recently I have been stopped by some errors and can't fix them.
My project is n-tier with Entity framework data model. There is 4 layer for server.
DAL(Contain EF dataModel)-->BLL(Class library for insert/update/Delete Functions)-->Service Layer(wcf class library)-->Host Layer(windows service)
I host my service in a Windows Service. The service binding is nettcpbinding. I configure service true so no problem here.
i have a Project with name "Common"(class library) that All 4 project access to it and as you know i create a code generator and pasted generated class to common.(Separate class model with DAL).
Now the cient has just (Host Layer) service reference.in client, I have all entity classes in service class.
The problem occurs when I want to insert object to data base. See Code below :
Server Side (This Is in BLL And Service Layer):
namespace BLL
{
public static class bz
{
public static class People
{
public static void myInsert(Common.People p, out bool Result)
{
Result = false;
Common.EFContainer cntx = new Common.EFContainer();
cntx.ContextOptions.ProxyCreationEnabled = false;
cntx.ContextOptions.LazyLoadingEnabled = false;
if (p.FirstName == "" || p.FirstName == null)
{
throw new Exception("Fill Fist Name") ;
}
// ... more validate
//-->I Do not use first or single etc in validating<--
try
{
cntx.Peoples.AddObject(p);
cntx.SaveChanges();
Result = true;
}
catch (Exception ex)
{
throw ex;
}
}
}
public static class Gender
{
public static List<Common.Gender> GetData()
{
Common.EFContainer cntx = new Common.EFContainer();
cntx.ContextOptions.ProxyCreationEnabled = false;
cntx.ContextOptions.LazyLoadingEnabled = false;
return cntx.Genders.ToList();
}
}
}
}
namespace ServiceLayer
{
[ServiceContract(SessionMode = SessionMode.Required)]
public interface IService
{
[FaultContract(typeof(NormalExeption))]
[OperationContract]
bool AddToPeople(Common.People p);
[OperationContract]
List<Common.Gender> GetGenders();
}
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = System.ServiceModel.ConcurrencyMode.Single)]
public class myService : IService
{
[OperationBehavior]
public bool AddToPeople(Common.People p)
{
try
{
BLL.bz.People.myInsert(p, out result);
return result;
}
catch (Exception ex)
{
var exep = new NormalExeption(ex.Message, ex.Source, 0, Icons.Error);
throw new FaultException<NormalExeption>(exep, new FaultReason(new FaultReasonText(ex.Message)));
}
}
[OperationBehavior]
public List<Common.Gender> GetGenders()
{
return BLL.bz.Gender.GetData();
}
}
}
Client side :
ServiceRef.People p = new ServiceRef.People();
ServiceRef.myServiceClient client=new ServiceRef.myServiceClient();
p.FirstName="S";
//... Fill Other Fields
p.Childs=new List<ServiceRef.Child>();
p.Childs.Add(new ServiceRef.Child(){FirstName="A"});
p.Gender=client.GetGenders.first();
//... --->No Error Happen Till Here Error Is After This in Service<---
try
{
client.AddToPeople(p);
}
Catch(FaultException fe)
{
messagebox.show(fe.Detail.Message);
}
My Problems :
Both errors occur in client side after I insert the people object.
When i use Poco Code Generator For My EF I receive this error:
Collection Was Out Of Fixed Size
This error occurs in poco classes definition.
When I use Self Tracking Code Generator For my EF I receive this error:
Sequence contains no elements
I think This error occurs in contex.addobject(p) and I don't use any Single Or First in my code that return this exception.
Some one help me - which code generator can I use that doesn't have these errors or how can I fix these errors? I have VS 2010.
Edit: The service works when the server send objects to client but when client inserts it fails. In the client service reference config I changed the collection type to:
System.Collection.Generic.List

Wcf service exception good practices

I am developing a distributed application. In it, there are roles and sets of permissions that I must validate.
Is a good pratice to throw an exception, in per example, unauthorized access?
Or should I send some message back to the client?
On your service operation, you can specify a FaultContract that will serve both purposes like so:
[OperationContract]
[FaultContract(typeof(MyServiceFault))]
void MyServiceOperation();
Note that MyServiceFault must be marked with DataContract and DataMember attributes, in the same way you would a complex type:
[DataContract]
public class MyServiceFault
{
private string _message;
public MyServiceFault(string message)
{
_message = message;
}
[DataMember]
public string Message { get { return _message; } set { _message = value; } }
}
On the service-side, you are then able to:
throw new FaultException<MyServiceFault>(new MyServiceFault("Unauthorized Access"));
And on the client-side:
try
{
...
}
catch (FaultException<MyServiceFault> fault)
{
// fault.Detail.Message contains "Unauthorized Access"
}
Well, you can catch all exceptions in the WCF service implementations methods and rethrow them as FaultExceptions. By doing it this way, the exception will be rethrown on the client with a message of your choosing:
[OperationContract]
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (Exception ex)
{
// Log the exception including stacktrace
_log.Error(ex.ToString());
// No stacktrace to client, just message...
throw new FaultException(ex.Message);
}
}
To avoid having unexpected errors relayed back to the client, it's also a good practice to never throw Exception instances in code on the server-side. Instead create one or more of your own exception types and throw them. By doing so, you can distinguish between unexpected server processing errors and errors that are thrown due to invalid requests etc:
public List<Customer> GetAllCustomers()
{
try
{
... code to retrieve customers from datastore
}
catch (MyBaseException ex)
{
// This is an error thrown in code, don't bother logging it but relay
// the message to the client.
throw new FaultException(ex.Message);
}
catch (Exception ex)
{
// This is an unexpected error, we need log details for debugging
_log.Error(ex.ToString());
// and we don't want to reveal any details to the client
throw new FaultException("Server processing error!");
}
}
Throwing general Dot Net Exceptions would make the service client proxies and the server channel to go in faulted state if you are not using basicHTTPBinding ...To avoid that you should always throw FaultException from the service...
from you catch block just use:
throw new FaultException("Your message to the clients");

Categories