BusinessRuleException is not working in UI project - c#

I'm working on 3 layer windows application in C#. We have custom exception to capture businessrule exceptions. this is getting captured in Data access layer and business layer. But it is not falling in businessrule exception in UI project.
[Serializable]
public class BusinessRuleException : ApplicationException
{
public BusinessRuleException():base(){}
public BusinessRuleException(string message):base(message){}
public BusinessRuleException(string message, Exception exception):base(message,exception){}
public BusinessRuleException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context):base(info,context){}
}
In Data access layer, below catch block is getting captured.
catch (BusinessRuleException ex)
{
throw ex;
}
In UI, below catch block is not working. it is going to System.Exception catch block
catch(BusinessRuleException ex)
{
m_strErrorMessage = ex.Message;
}
catch(Exception ex)
{
m_strErrorMessage = ex.Message;
}

Related

How do i catch or throw an exception in asp.net core?

I'm kind of not sure as to where to catch an application and any other unexpected exception, but i do want to show on the front end which exception occurred either an application or any other exception.
If i just 'throw' from service manager then it will be catched in the controller, but what if there was an exception in the service manager and the controller?
This also seems verboose.
This is my service manager where I'm calling an API.
public async Task<int> CreateCategory(CategoryViewModel model)
{
logger.LogInformation("In {service}, Creating {CategoryModel}", nameof(CategoryServiceManager), model.ToString());
try
{
model.Guard(model.ToString());
int categoryId = await apiClient.PostAsync<int, CategoryViewModel>("Category", model);
return categoryId;
}
// Guard wil throw
catch (ApplicationException ex)
{
logger.LogError("Exception thrown for {model}: {Message}, {Stacktrace}", model.ToString(),ex.Message, ex.StackTrace);
throw new ApplicationException($"Exception thrown in service when creating category: {ex.Message}");
}
catch (Exception ex)
{
logger.LogError("Unexpected error thrown in service when creating a category : {Message}, {Stacktrace}", ex.Message, ex.StackTrace);
throw new Exception("Unexpected error thrown in service when creating a category");
}
}
This is the Guard extension used in the service manager.
public static class GuardExtensions
{
public static void Guard(this string input, string inputName)
{
if (string.IsNullOrEmpty(input))
{
throw new ApplicationException($"{inputName} must be provided");
}
}
public static void Guard(this object input, string inputType)
{
if (input == null)
{
throw new ApplicationException($"{inputType} must be provided");
}
}
}
This is the controller where I'm using the the service manager.
public async Task<IActionResult> Create(CategoryViewModel model)
{
logger.LogInformation("In {controller}, Creating {CategoryViewModel}", nameof(CategoryController), model.ToString());
try
{
if (ModelState.IsValid)
{
int createdCategoryId = await categoryService.CreateCategory(model);
List<CategoryPictureViewModel> categoryPictureViewModels = new List<CategoryPictureViewModel>();
foreach (int picId in TransformTypes.SplitStringIntoListOfInt(model.uploadedImageIds))
{
categoryPictureViewModels.Add(new CategoryPictureViewModel
{
CategoryId = createdCategoryId,
PictureId = picId
});
//model.CategoryPictures.ToList().Add(new CategoryPictureViewModel
//{
// CategoryId = createdCategoryId,
// PictureId = item
//});
}
int res = await categoryPictureService.CreateCategoryPictureAsync(categoryPictureViewModels);
return RedirectToAction(nameof(Index));
}
}
catch (ApplicationException ex)
{
logger.LogError("In {controller}, Creating category: {Message}, {Stacktrace}", nameof(CategoryController), ex.Message, ex.StackTrace);
throw new ApplicationException($"Exception thrown controller when creating category: {ex.Message}");
}
catch (Exception ex)
{
logger.LogError("Unexpected error in {controller} when creating category: {Message}, {Stacktrace}", nameof(CategoryController), ex.Message, ex.StackTrace);
throw new Exception($"Unexpected error in controller when creating category: {ex.Message}");
}
return StatusCode(StatusCodes.Status422UnprocessableEntity);
}
You can handle your exception by Action filter or using a custom exception handling middleware.
It depends on your scenario. but Having a custom exception middleware or exception filter to handle your exception can work and it's better for sake of separation of concern.
using Middleware :
Microsoft
ExceptionFilter:
StackOverflow

Application specific exception wrapping "MongoDuplicateKeyException" not catch'ed

Out of need have created application exception which wraps a MongoDuplicateKeyException and throwing that exception like below
Public class AppException : Exception
{
// all constructor implementation
public int ErrorCode { get; set; }
public string AppMessage { get; set; }
}
In method catching and throwing exception
public async Task<Response> Method1(parameter ...)
{
try
{
//some insert/update operation to DB
return <instance of Response>;
}
catch(MongoduplicateKeyException ex)
{
var exception = new AppException(ex.Message, ex)
{
ErrorCode = 22,
AppMessage = "some message",
};
throw exception;
}
}
Method that calls Method1() above
try
{
//some other operation
var response = await Method1();
}
catch(AppException ex)
{
SomeOtherLoggingMethod(ex, other parameter);
}
catch(Exception ex)
{
SomeMethod(ex, other parameter);
}
Surprisingly the catch(AppException ex) catch block never gets catched even though am throwing an AppException from Method1(). It always catch the generic catch block catch(Exception ex).
After debugging, found that in catch(Exception ex) catch block the exception type ex.GetType() is actually a WriteConcernException type (MongoduplicateKeyException : WriteConcernException).
So essentially that specific catch block not hitting cause the exception type is not AppException rather WriteConcernException But
Not sure why is it so? am I missing something obvious here? Please suggest.
You found the answer while debugging. The catch(AppException ex) block is not executed because public async Task<Response> Method1 does not throw an AppException it throws a WriteConcernException.
The API shows a WriteConcernException is the superclass of DuplicateKeyException so the catch block in Method1 is not hit and the exception bubbles up to the 2nd catch block in the caller.
So if you update your code to catch the appropriate exception it should work as you intend.
public async Task<Response> Method1(parameter ...)
{
try
{
//some insert/update operation to DB
return <instance of Response>;
}
catch (MongoServerException mse)
...

How to log the "path taken" by the code and its exceptions

I have a requirement of compose the log message through the path taken by a code in a user click. Let me give an example:
Imagine the classical example: A user clicks in a button in a View, that calls code from the Business Layer that call code from Data Access Layer, that returns data to the Business, that return to a View.
I want to compose my log message through these layers. The caller method (in a View) that started the whole process will receive the full message. Here are some code sample just to help me explain what i am trying to achieve.
public void ViewMethod()
{
try
{
BussinessMethod();
}
catch (Exception ex)
{
Logger.Enqueue("exception occured");
Logger.Print();
}
}
public void BussinessMethod()
{
try
{
DataAcessMethod();
}
catch (Exception ex)
{
Logger.Enqueue("exception occured in the bussiness method")
}
}
public void DataAcessMethod()
{
try
{
// some code that executes an SQL command
// Log the SQL Command 1
// Log the SQL Command 2 and do on...
}
catch (Exception ex)
{
Logger.Enqueue("Error occurred, sqls executed are ...", sqlExecuted);
}
}
EDIT: The reason i am needing it is that i need to log all the SQL's executed in the whole process. If an error occurs in any point of the whole process, the user cant be warned, i need to store as much as possible information becouse the support technician will need it later.
My question is if there is any design pattern to develop it or passing a Logger reference across the "layers" are acceptable?
I would do something like this
public class Context
{
[ThreadStatic]
private static LogStore _store;
public static Log(....)
{
.....
}
}
public void ViewMethod()
{
var response = BussinessMethod();
if (response.Status = ResponseStatus.Success)
// do something with response.Data
else
// show message?
}
public BusinessMethodResponse BussinessMethod()
{
var response = new BusinessMethodResponse() {Status = ResponseStatus.Failure};
SomeData data;
try
{
data = DataAcessMethod();
}
catch (Exception ex)
{
Context.Log(....);
response.Message = "Data retrieval failed";
return response;
}
try
{
// massage the data here
response.Status = ResponseStatus.Success;
response.Data = myMassagedData;
}
catch (Exception ex)
{
Context.Log(....);
response.Message = "Something failed";
}
return response;
}
public void DataAcessMethod()
{
// some code that executes an SQL command
}
What this do? Now you can call your business objects from MVC, WPF, WinForms, Web Forms, etc...

Handle StackOverflowException in ASP.NET MVC 4

I'm trying to do something with my application before a StackOverflowException occurs in ASP.NET MVC 4 C#. I'm aware that when a StackOverflowException occurs, the application is killed by the OS (in this case it kills IIS). My question is, is there a way to catch that exception to make a log before it crashes? I tried using HandleProcesCorruptedStateExceptions but it doesn't work. Here's a sample code of what should be achieved.
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
public ActionResult StackOverflow()
{
try
{
Self("test");
return View();
}
catch (System.StackOverflowException ex)
{
//log
Console.WriteLine(ex.ToString());
// try to do something to prevent application from crashing
throw;
}
}
[HandleProcessCorruptedStateExceptions]
[SecurityCritical]
private string Self(string value)
{
try
{
return Self(value);
}
catch (System.StackOverflowException ex)
{
// log
Console.WriteLine(ex.ToString());
// try to do something to prevent application from crashing
throw;
}
}

how can i handle WCF Services when database result is very great?

I use code below:
private class WcfProxy<TService> :
ClientBase<TService> where TService : class, IContract
{
public TService WcfChannel
{
get
{
return Channel;
}
}
}
protected TResult ExecuteCommand<TResult>(Func<TContract, TResult> command)
where TResult : IDtoResponseEnvelop
{
var proxy = new WcfProxy<TContract>();
try
{
var result = command.Invoke(proxy.WcfChannel);
proxy.Close();
return result;
}
catch (CommunicationException ex)
{
proxy.Abort();
throw new BusinessException(BusinessExceptionEnum.Operational, Properties.Resources.Exception.WcfAdapterBase_CommunicationException_TransportInEnamDataIsInvalid, ex);
}
catch (TimeoutException ex)
{
proxy.Abort();
throw new BusinessException(BusinessExceptionEnum.Operational, Properties.Resources.Exception.WcfAdapterBase_TimeoutException, ex);
}
catch (Exception)
{
proxy.Abort();
throw;
}
}
When the query returns high amount of result
i encounter with this message:
The communication object cannot be used for communication because it is in the Faulted state
does exist a way or trick that i observe the result of database query successfully
or a way that i divide the result or get part of result?
Probably youneed to enlatge maxReceivedMessageSize, or one of other parameters of binding.
You can also enable wcf trace and review it with svcTraceViewer.exe
You get this error:
The communication object cannot be used for communication because it
is in the Faulted state.
because you throw an error and it is not handled and gets thrown in the iis pool.
Check this link out: http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/fc60cd6d-1df9-47ff-90a8-dd8d5de1f080/ also this is not caused by the large ammount of data: WCF Cannot be used for communication because it is in the Faulted state

Categories

Resources