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;
}
}
Related
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)
...
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;
}
I am trying to unit test my code to see if I try to view an account's details without a sessionKey, it will throw an exception. The unit test will go and execute the statement in the try-catch and despite knowing an exception will occur, it lists the test as successful even though Assert should be false. Assert is reached in similar functions, but not always. What would be the cause of the problem?
Original Function
/// <summary>
/// Displays the account details to the user
/// </summary>
/// <returns>HttpResponseMessage deserialized into AccountResponses object</returns>
public async Task<AccountResponse> Details()
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("X-Session-Key", sessionKey);
try
{
HttpResponseMessage response = await client.GetAsync(_baseUrl + "/Account/Details");
response.EnsureSuccessStatusCode();
string details = await response.Content.ReadAsStringAsync();
AccountResponse temp = JsonConvert.DeserializeObject<AccountResponse>(details);
return temp
}
catch (HttpRequestException ex)
{
throw ex;
}
}
Working Live Unit Test Function
[TestCategory("Account/Logon")]
[TestMethod]
public void LogOnNegativeBadPasswordTest()
{
try
{
string sessionKey = dmWeb.Account.LogOn(new DMWeb_REST.AccountLogOn { Password = "test#pasasdfasfsword" }).GetAwaiter().GetResult().ToString();
}
catch (HttpRequestException ex)
{
Assert.IsTrue(ex.Message.Contains("400"));
}
}
Not Working Live Unit Test Function
[TestCategory("Account/Details")]
[TestMethod]
public void DisplayDetailsNegativeNoSessionKeyTest()
{
try
{
string details = dmWeb.Account.Details().GetAwaiter().GetResult().ToString();
}
catch (HttpRequestException ex)
{
Assert.IsTrue(ex.Message.Contains("401"));
}
}
The test will be treated as successful as long as no errors are thrown. If no error is being caught in the catch block, this almost definitely means that no error was thrown by the code you're testing.
So place an Assert.Fail() after the statement that's supposed to throw an error:
public void TestMethod()
{
try
{
string details = ThingIAmTesting();
// shouldn't get here
Assert.Fail();
}
catch (Exception ex)
{
Assert.IsTrue(ex.Message.Contains("401");
}
}
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...
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