How to display my own exception? - c#

I'm developing a web project where i need to add custom exception classes. For example, how can i display a message from my custom exception class when the session timeout occurs? Please help. Any sample will be helpful.
This is what i written in my exception class so far:
public class CustomException : Exception
{
private string message;
public CustomException ()
{
this.message = "Invalid Query";
}
public CustomException (String message)
{
this.message = message;
}
}
Need to know how to link this with the session timeout, from where i need to write the logic of the same. Thank You.

If you are looking to throw your custom exception when the is raised you can do it like this.
try {
DataTable dt = q.ExecuteQuery(); //This throws a timeout.
} catch(SessiontTimeoutException ste) {
throw new CustomException("Session has timed out");
} catch(Exception e) {
//Show unexpected exception has occured
}
Not too sure if this is what you are trying to do.
Update:
To Find out if SqlException is a TimeoutException please see this StackOverFlow Post.

You might want to write this as
public CustomException() : base("Invalid Query") { }
this way the exception message gets passed correctly, for the other constructor
public CustomException(String message) : base(message) { }
then you don't need the private string message field.

SqlException class exposes the property Errors which is a collection of SqlError objects. You can query the Number property of each error object which corresponds to an entry in the master.dbo.sysmessages table.

I recommend you use Inner Exception to get user friendly exception message with also the system error message. If getting MyException, you'll see your exception message and the system exception message at MyException.ToString().
Additionally, if you are concerned for coding Exception, you can use the Code Snippet Feature of VS. Just type 'Exception' and press TAB key twice, then VS will create Exception class as the following code.
try
{
DataTable dt = q.ExecuteQuery(); //This throws a timeout.
}
catch (SessiontTimeoutException ex)
{
throw new MyException("my friendly exception message", ex);
}
[Serializable]
public class MyException : Exception
{
public MyException() { }
public MyException(string message) : base(message) { }
public MyException(string message, Exception inner) : base(message, inner) { }
protected MyException(
System.Runtime.Serialization.SerializationInfo info,
System.Runtime.Serialization.StreamingContext context)
: base(info, context) { }
}

Related

custom exception for null parameters in c#

I'm trying to create custom exceptions for a Web-API program, if the name, code or whatever is null, it should send me a custom message saying x input is empty or null error, I'm not sure how to finish it so I'd appreciate some help.
public Product CreateProduct(Product p)
{
if (p.Name.Trim() == "")
{
throw new InvalidProductDataException("El producto no tiene nombre");
}
return p;
}
I'm assuming CreateProduct is an action method on a Controller class, and what you are actually trying to do is return errors to a client that is calling your API. Therefor, the easiest way to return errors to an HTTP client is by using the IActionResult return type instead of returning your actual type. This will give you control over the HTTP status code.
class ProductController : Controller {
public IActionResult CreateProduct(Product p)
{
if (String.IsNullOrWhitespace(p.Name))
{
return BadRequest("El producto no tiene nombre");
}
// Perform create?
return Ok(p);
}
}
For more information on controller action return types see: https://learn.microsoft.com/en-us/aspnet/core/web-api/action-return-types?view=aspnetcore-5.0
Any kind of exception thrown from a controller action is going to result in an opaque HTTP 500 response sent to the API client, which probably isn't what you want for this kind of error.
An alternative is to introduce Middleware that will capture certain types of exception and convert them to HTTP responses.
Let's define a custom exception named LoginException that will be used to throw an error exception in login processes.
public class LoginException : System.Exception
{
//todo
}
Now let's make the necessary constructor definitions for use in the application.
public class LoginException : System.Exception
{
public LoginException()
: base()
{ }
public LoginException(String message)
: base(message)
{ }
public LoginException(String message, Exception innerException)
: base(message, innerException)
{ }
protected LoginException(SerializationInfo info, StreamingContext context)
: base(info, context)
{ }
}
As seen above, we have defined the constructors of LoginException and made the constructor redirects for the System.Exception class, so we made the LoginException class ready for use.
void Login(string userName, string password)
{
try
{
if (userName != "canert" && password != "qwerty123")
throw new LoginException("Invalid login operation");
}
catch (LoginException loginException)
{
Response.Write(loginException.Message);
}
}
If you want to throw a custom type of exception called InvalidProductDataException then you need to declare a class with that name and it needs to be a subclass of System.Exception:
public class InvalidProductDataException : System.Exception {
public InvalidProductDataException(String message) : base(message) {
}
// This constructor overload is necessary to allow for your Exception to be deserialized. This is a best practice when implementing custom Exception types.
protected InvalidProductDataException(SerializationInfo info, StreamingContext context) :
base(info, context) {
// If you exception contained custom properties, you would want to deserialize them here
}
}
For more information on creating custom Exception classes see: https://learn.microsoft.com/en-us/dotnet/standard/exceptions/how-to-create-user-defined-exceptions
Note: It is not necessary to create a custom Exception class just to be able to specify the message that you want. For example you could simply throw new Exception("your message"). However it does make sense to create a custom Exception class if you want to be able to catch that specific exception elsewhere in your code.

How to log exceptions with structured arguments in .NET Core

I can't find a consistent way to log exceptions in my .NET Core microservice.
Informational messages logging guidelines are simple (Microsoft.Extension.Logging is used):
_logger.LogInformation($"Reading file {path}..."); // bad
_logger.LogInformation("Reading file {Path}...", path); // good
The benefit of the second variant is structured information: by using a clever log event router (like Serilog with RenderedCompactJsonFormatter) the path is written as separate property of the log event.
Things are going worse with errors logging. The requirements are obvious:
Errors are implemented as exceptions.
An error is logged in the catch block where it is handled.
Each error is logged in a structured form.
So, I'd expect the error reporting to look like
throw new MyException("Failed to read file {Path}", path);
and error logging - like
catch(MyException e)
{
_logger.LogError(e, "Processing error");
}
LogError method here logs the complete error description, but it is not structured: the path is not added as a property.
I tried to make MyException hold the message template and the arguments, but there are 2 problems with this approach:
How to render the exception message based on a template with named arguments?
An argument may be disposed when an exception is processed in a catch block.
Please tell me how you deal with this.
Exceptions in .NET don't support structured parameters like that. Since you are using custom exceptions, you could add this functionality to your own exception class.
For example:
public class MyException : Exception
{
public object[] Props { get; }
public MyException()
{
}
public MyException(string message)
: base(message)
{
}
// Add custom "props" parameter to your exception class
public MyException(string message, params object[] props)
: base(message)
{
Props = props;
}
public MyException(string message, Exception inner)
: base(message, inner)
{
}
}
Now in your code you could do something like this:
try
{
var file = "image.png";
var path = "./my/path/";
throw new MyException("Failed to read file '{file}' in path '{path}'", file, path);
}
catch (MyException e)
{
_logger.LogError(e, e.Message, e.Props);
}
If you look at your logs (I'm using InvisionLog here), then you should see that it is structured.
I think this is the only way to catch your exceptions and log them in a structured manner.

HttpError is ignored when creating an error response in a custom ExceptionFilterAttribute (if the exception is throwed in another attribute)

I have received the assignment to make our C# Webapi return always error responses with the following format:
{
"error": {
"code": 15,
"message": "My custom error message"
}
}
Because of that I registered my own ExceptionFilterAttribute:
public class CustomExceptionFilterAttribute : ExceptionFilterAttribute
{
class CustomError
{
public int code { get; set; }
public String message { get; set; }
}
public override void OnException(HttpActionExecutedContext context)
{
if (context.Exception is BaseException)
{
BaseException exception = (BaseException)context.Exception;
HttpError error = new HttpError();
CustomError customError = new CustomError
{
code=exception.CustomError.code,
message=exception.CustomError.message
};
error.Add("error", customError);
context.Response = context.Request.CreateErrorResponse(HttpStatusCode.InternalServerError, error);
}
else
{
context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
}
}
This is working very well when the exception was throwed in a controller. But if the exception was throwed in an attribute (AuthorizeAttribute or EnableQueryAttribute), althoug my custom ExceptionFilter is called and the same code is executed, the response generated ignores the given HttpError and the response has the following body:
{
"error": {
"code": "",
"message": ""
}
}
I'm not very skilled in c#, I'm pretty sure that I'm doing something wrong, but I don't know what :S
Thanks in advance.
Edit 1:
I'm applying the Attribute that throws the exception at each method where the attribute is needed. For example I have an Odata Controller for an entity called "event":
[CustomAuthentication]
[CustomEnableQueryAttribute(PageSize = 20)]
public IQueryable<Event> Get()
{
(...)
return result;
}
As said, if the exception is throwed in the body of the controller, then my CustomExceptionFilter is invoked, and the custom response is created correctly.
But if the exception is thrown in the CustomAuthenticationAttribute or in the CustomEnableQueryAttribute, then altough my CustomExceptionFilter is invoked and the very same code is executed, the body response is wrong (see example).
Filter are mean for only controller but for global errors you need to use Global Error Filter in WebAPI.
to handle error thrown from attribute you need to Create Global Error Hnandler : https://learn.microsoft.com/en-us/aspnet/web-api/overview/error-handling/exception-handling
class OopsExceptionHandler : ExceptionHandler
{
public override void HandleCore(ExceptionHandlerContext context)
{
context.Result = new TextPlainErrorResult//you have to create this class
{
Request = context.ExceptionContext.Request,
Content = "Oops! Sorry! Something went wrong." +
"Please contact support#contoso.com so we can try to fix it."
};
}
}
there are a number of cases that exception filters can't handle. For example:
Exceptions thrown from controller constructors.
Exceptions thrown from message handlers.
Exceptions thrown during routing.
Exceptions thrown during response content serialization .

Handle exceptions / HTTP status code based on exception types

I'm trying to throw some exception, catch it in a HandleException attribute and return it properly to the client.
Here is an example:
[HandleException(Type = typeof(UserNotFoundException), Status = HttpStatusCode.NotFound)]
[HandleException(Type = typeof(LoginFailedException), Status = HttpStatusCode.Unauthorized)]
public UserProfile Login(UserCredentials userCred)
In my Login() function I either throw a UserNotFoundException or LoginFailedException.
My HandleExceptionAttribute looks like this:
public class HandleExceptionAttribute : ExceptionFilterAttribute
{
public Type Type { get; set; }
public HttpStatusCode Status { get; set; }
public override void OnException(HttpActionExecutedContext context)
{
var ex = context.Exception;
ResponseHelper.CreateException(Status, ex.Message);
}
}
What I want is to be able to handle what kind of exceptions is going to be thrown and handle it properly in an attribute, where I specify the HttpStatusCode.
The problem, with this code, is that the top-most attribute is always called. So even if the exception is a LoginFailedException I always get UserNotFoundException and 404 code returned to the client.
How can I achieve this?
Just off the top of my head, it looks like you're going to need to do some filtering in your OnException method, so that you verify that the exception you got matches the exception you intended that instance of the attribute to handle.
public override void OnException(HttpActionExecutedContext context)
{
var ex = context.Exception;
if(typeof(ex) == Type)
ResponseHelper.CreateException(Status, ex.Message);
}

Need to determine if ELMAH is logging an unhandled exception or one raised by ErrorSignal.Raise()

I am using the Elmah Logged event in my Global.asax file to transfer users to a feedback form when an unhandled exception occurs.
Sometimes I log other handled exceptions. For example:
ErrorSignal.FromCurrentContext().Raise(new System.ApplicationException("Program code not found: " + Student.MostRecentApplication.ProgramCode));
// more code that should execute after logging this exception
The problem I am having is that the Logged event gets fired for both unhandled and these handled, raised exceptions. Is there a way to determine, in the Logged event handler, whether the exception was raised via ErrorSignal class or was simply unhandled? Are there other Elmah events that I can take advantage of?
Tired of trying to find the "right" way to do this, so I ended up creating my own exception type:
public class HandledElmahException : Exception
{
public HandledElmahException() : base() { }
public HandledElmahException(string message) : base(message) { }
public HandledElmahException(string message, Exception innerException) : base(message, innerException) { }
}
Then, in the ErrorLog.Logged event handler I just check to see if the exception is of type HandledElmahException.
void ErrorLog_Logged(object sender, ErrorLoggedEventArgs args)
{
if (args.Entry.Error.Exception is HandledElmahException)
return;
// my code to transfer to custom error page to collect feedback...
}
So, if I don't want to take them to the ErrorPage, when an exception is logged, I use an instance of my special HandledElmahException class, which can be derived from.
ErrorSignal.FromCurrentContext().Raise(new HandledElmahException("Program code not found: " + Student.MostRecentApplication.ProgramCode));

Categories

Resources