Custom error handling ASP.NET - c#

I want to use custom exception handling, for example
instead of using (Exception ex) i want to use (LoginException ex) or (RegistrationException ex) or (SomeNameException ex)
is it possible to design such custom exception handling in ASP.NET webforms?

Yes but what you need to do is first create your own custom exceptions. You need to derive your exception from the Exception base class. Heres an example:
[Serializable]
public class LoginFailedException: Exception
{
public LoginFailedException() : base()
{
}
public LoginFailedException(string message)
: base(message)
{
}
public LoginFailedException(string message, Exception innerException)
: base(message, innerException)
{
}
protected LoginFailedException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
Then in your code, you would need to raise this exception appropriately:
private void Login(string username, string password)
{
if (username != DBUsername && password != DBPassword)
{
throw new LoginFailedException("Login details are incorrect");
}
// else login...
}
private void ButtonClick(object sender, EventArgs e)
{
try
{
Login(txtUsername.Text, txtPassword.Text);
}
catch (LoginFailedException ex)
{
// handle exception.
}
}

You mean something like:
try{
somefunc();
}catch(LoginException ex){
}catch(RegistrationException ex){
}catch(SomeNameException ex){
}
Or do you mean coding the classes to throw the exceptions?

Related

How do I handle Exception throw by Intercepter in C#

I want to Catch the exceptions thrown by Interceptor, how can I do it?
using autofac6.0.0,.NET 6
Controller>CommandAspect>Commands
The Interceptor can catch Exceptions from Command, but the Controller does not catch Exceptions from the Interceptor.
register
builder.RegisterModule<AutofacScanningModule>();
builder.RegisterType<CommandAspect>();
AutofacScanningModule
public class AutofacScanningModule : Module
{
protected override void Load(ContainerBuilder builder)
{
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
builder
.RegisterAssemblyTypes(assemblies)
.Where(t => t.GetInterfaces().Any(i => i.IsAssignableFrom(typeof(ICommand))))
.EnableClassInterceptors()
.InterceptedBy(typeof(CommandAspect));
base.Load(builder);
}
}
CommandAspect
public class CommandAspect : IInterceptor
{
public CommandAspect()
{
}
public async void Intercept(IInvocation invocation)
{
try
{
invocation.Proceed();
}
catch (Exception ex)
{
//Log Output
throw;
}
}
}
WebController
try
{
type commandType = typeof(CommandClass);
object commandObject = _serviceProvider.GetService(commandType);
commandType.GetMethod("SomeCommand").Invoke(commandObject);
}
catch(Exception ex)
{
//not handled
}
Command
public class CommandClass : ICommand
{
public virtual void SomeCommand()
{
throw new Exception();
}
}
Exception StackTrace
Unhandled exception. System.Exception: Exception of type 'System.Exception' was thrown.
at Sample.SomeCommand.Find(Record record) SomeCommand.cs:line 42
at Castle.Proxies.SomeCommandProxy.Find_callback(Record record)
at Castle.Proxies.Invocations.SomeCommand_Find.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Sample.CommandAspect.Intercept(IInvocation invocation) CommandAspect.cs:line 29
at System.Threading.Tasks.Task.<>c.<ThrowAsync>b__127_1(Object state)
at System.Threading.QueueUserWorkItemCallback.<>c.<.cctor>b__6_0(QueueUserWorkItemCallback quwi)
at System.Threading.ExecutionContext.RunForThreadPoolUnsafe[TState](ExecutionContext executionContext, Action`1 callb
ack, TState& state)
at System.Threading.QueueUserWorkItemCallback.Execute()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
at System.Threading.PortableThreadPool.WorkerThread.WorkerThreadStart()
at System.Threading.Thread.StartCallback()
Resoleved
public class CommandAspect : IInterceptor
{
public CommandAspect()
{
}
public void Intercept(IInvocation invocation)
{
ProcessInterceptAsync(invocation).Wait();
}
private async Task ProcessInterceptAsync(IInvocation invocation)
{
try
{
var proceed = invocation.CaptureProceedInfo();
proceed.Invoke();
}
catch (Exception ex)
{
//Log Output
throw;
}
}
}
You're not doing async interception right. You have to return void from Intercept and set the ReturnValue to the Task result. See the docs here..
Your stack trace shows the exception coming from a different thread, hence it's not being caught. If you set up the interceptor right, I bet it'll work as expected.
You can implement an ErrorHandling middleware to handle this. Since middleware is acting outside the controller, the controller doesn't get to see the error.
Have a look at this link:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/error-handling?view=aspnetcore-6.0

How to override exception message in ASP.NET Web API

I'm having quite a bit of difficulty in getting a custom exception message to return from my Web Api solution. It's a bit more complicated than that:
I want to override the read only property of the exception with my own:
public class CustomException : Exception
{
public CustomException(string message)
: base(message)
{
}
public CustomException(string message, Exception inner)
: base(message, inner)
{
}
}
However, I also have a global exception handler:
public class GlobalExceptionLogger : ExceptionLogger
{
public override void Log(ExceptionLoggerContext context)
{
if (context.Exception.Message == "Password has already been used in the past...1")
{
throw new CustomException("some msg", context.Exception);
}
NLogger.LogError("Global Error Handler", context.Exception);
}
}
When I throw the error I do so like:
if (some condition)) throw new CustomException("some msg");
And then I catch it in the method like:
catch (CustomException ex)
{
throw ex;
}
catch (Exception ex)
{
NLogger.LogError(ex);
throw;
}
How can I set the message to be "some msg"? What I'm trying to do is have the api return 1-2 use case related error messages with customErrors mode set to on.
throw new HttpResponseException(
new HttpResponseMessage
{
StatusCode = code,
ReasonPhrase = phrase,
Content = new StringContent(body)
});

Modify exception data while logging with NLog

I have a global try/catch around my application methods to log unhandled exceptions and show an error message. For logging I use NLog. If I handle an exception and log it manually I set a key 'logged' in the exceptions data object to prevent the second log from the global try/catch.
public partial class App : Application
{
public static void Main(string[] args)
{
try
{
// Application stuff
SomeMethod();
}
catch (Exception ex)
{
if (ex.Data['logged'] == false)
{
logger.Error(ex, "A unhandled exception occured.")
ex.Data['logged'] = true;
}
// Show error dialog
}
}
public static void SomeMethod()
{
try
{
// Method stuff
}
catch (Exception ex)
{
logger.Error(ex, "A handled exception occured.")
ex.Data['logged'] = true;
throw;
}
}
}
I want to simplify the process so that I don't have to call ex.Data['logged'] = true; manually. Is there a way to modify the data property of an exception automatically while logging with NLog? I tried to use a MethodCall-Target but I had no access to the exception reference. The exception could only be passed as a string.
Would it work for you to use NLog to perhaps modify your approach to logging exceptions slightly?
public partial class App
{
private static Logger logger = NLog.LogManager.GetCurrentClassLogger();
public static void Main(string[] args)
{
try
{
SomeMethod();
}
catch (Exception ex)
{
logger.ErrorEx(ex, "message");
}
}
public static void SomeMethod()
{
try
{
// Method stuff
}
catch (Exception ex)
{
logger.ErrorEx(ex, "A handled exception occured.");
throw;
}
}
}
public static class NLogExt
{
public static void ErrorEx(this NLog.Logger logger, Exception ex, string message)
{
if (ex.Data["logged"] as bool? == true) return;
logger.Error(ex, message);
ex.Data.Add("logged", true);
}
}

Exception as FaultContract in WCF?

I'm trying to create a robust way to pass exceptions from the server to the client but I seem to be missing something.
The intention is to use FaultException to wrap actual serializable Exception subclasses caught on the server side, pass them over WCF, then rethrow them at the client side.
Server side code:
[ServiceKnownType(typeof(MyException))]
[ServiceContract]
interface IContract
{
[FaultContract(typeof(MyException))]
[OperationContract]
void Foo();
}
class Service : IContract
{
public void Foo()
{
try
{
Bar();
}
catch (MyException ex)
{
throw new FaultException<MyException>(ex, ex.Message);
}
catch (Exception ex)
{
throw new FaultException(ex.ToString());
}
}
}
Client side code:
try
{
client.Foo();
}
catch (FaultException<MyException> ex)
{
throw ex.Detail;
}
catch (FaultException ex)
{
throw;
}
MyException:
[Serializable]
public sealed class MyException: Exception
{
public MyException(string description)
: base(description)
{
}
public MyException()
{
}
public MyException(string message, Exception innerException)
: base(message, innerException)
{
}
private MyException(SerializationInfo info, StreamingContext context)
: base(info, context)
{
}
}
What I'm observing is that the server side code executes the catch (MyException ex) block but when the fault gets back to the client side, the code goes into the catch (FaultException ex) block and rethrows a normal FaultException, rather than MyException (interestingly, the FaultException does contain the message of the original MyException object).
Note that both the client and server have visibility of MyException, svcutil generates the correct attributes for the client side service contract and the WCF logs don't show any serialization errors.

User made Exception Class

I have to make my own Exception Class for .NET project. Could somebody please help how can I use it in the code? I just to show to MessageBox to user that the images were not found. But I don't know where to do it. Hoping for a good answer.
class RijException : Exception
{
public RijException()
: base() { }
public RijException(string message)
: base(message) { }
public RijException(string format, params object[] args)
: base(string.Format(format, args)) { }
public RijException(string message, Exception innerException)
: base(message, innerException) { }
public RijException(string format, Exception innerException, params object[] args)
: base(string.Format(format, args), innerException) { }
}
Now I want to use it:
try
{
afbeeldingPictureBox.BackgroundImage =
Image.FromFile(#"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png");
}
catch (FileNotFoundException)
{
throw new RijException("Can't find the images");
}
Edit
try
{
try
{
afbeeldingPictureBox.BackgroundImage = Image.FromFile(#"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png");
}
catch (FileNotFoundException)
{
throw new RijException("ImageNotFound");
//MessageBox.Show("Afbeeldingen konden niet worden geladen");
}
}
catch (RijException)
{
MessageBox.Show("Not able to load the image...");
}
Your example could be improved, but before that let's take a more useful example.
Imagine that you have the following code:
class Program
{
static void Main(string[] args)
{
try
{
var processor = new FileProcessor();
processor.Run();
}
catch (RijException exception)
{
//what will I get here.
}
}
}
Which uses the following classes:
public class FileProcessor
{
private string _myFileName;
public void Run()
{
try
{
var fileLoader = new FileLoader();
Process(fileLoader.Load(_myFileName));
}
catch (FileNotFoundException)
{
throw new RijException("Can't find requested file");
}
}
private void Process(object file)
{
//some logic
}
}
public class FileLoader
{
public object Load(string myFileName)
{
//throws FileNotFoundException
}
}
So the call stack will be like this:
If we modify the code in the main method to print the stack trace, what do you think that we get?
try
{
var processor = new FileProcessor();
processor.Run();
}
catch (RijException exception)
{
Console.WriteLine(exception.StackTrace);
}
The correct answer is:
See? The stack trace shows that the error happened in FileProcessor while it really happened in FileLoader. The reason to that is this code:
catch (FileNotFoundException)
{
throw new RijException("Can't find requested file");
}
When you catch an exception and throw another one you must always include the original exception as the inner exception. Otherwise it will be hard to understand where the exception originally occurred.
catch (FileNotFoundException ex)
{
throw new RijException("Can't find requested file", ex); //includes inner
}
Another problem is the exception message: "Can't find requested file". Ask yourself. If you get that message in a log file, would you be able to figure out what went wrong? At least give some context information.
Finally you have another problem. Best practices for designing exceptions says that they should be able to get serialized. To do that you need to include the serialization constructor and mark the exception as serializable:
[Serializable]
public class RijException : Exception
{
public RijException(string message) : base(message)
{
}
public RijException(string message, Exception inner) : base(message, inner)
{
}
//serialization constructor
protected RijException(
SerializationInfo info,
StreamingContext context) : base(info, context)
{
}
Finally I would therefore write your exercise like this:
try
{
var filename = #"..\..\Borden\Stilstaan en parkeren\Parkeren toegelaten.png";
try
{
afbeeldingPictureBox.BackgroundImage = Image.FromFile(filename);
}
catch (FileNotFoundException exception)
{
throw new RijException("Failed to load " + filename, exception);
}
}
catch (RijException)
{
MessageBox.Show("Not able to load the image...");
//now you would have all information required
//to figure out where and why something went wrong.
}
Summary
Always include inner exceptions
Provide useful context information so that you can figure out what went wrong
Make sure that exceptions can be serialized.
It is generally not a great idea to catch an exception that you cannot do much about. Just catching the FileNotFoundException and then throwing a new RijException that essentially conveys the same information is not usually done.
I just to show to MessageBox to user that the images were not found. But I don't know where to do it.
The most direct way to restructure your code to show the message box is
catch (FileNotFoundException)
{
MessageBox.Show("Can't find the images.");
//Don't do this: throw new RijException("Can't find the images");
}
You really do not want your custom RijException to take on the responsibility of displaying the MessageBox.

Categories