TECHNOLOGIES
FORUMS
JOBS
BOOKS
EVENTS
INTERVIEWS
Live
MORE
LEARN
Training
CAREER
MEMBERS
VIDEOS
NEWS
BLOGS
Sign Up
Login
No unread comment.
View All Comments
No unread message.
View All Messages
No unread notification.
View All Notifications
Answers
Post
An Article
A Blog
A News
A Video
An EBook
An Interview Question
Ask Question
Forums
Monthly Leaders
Forum guidelines
First Last
NA
648
73.3k
An MVC custom error logger trying to call a web api using async
Oct 28 2020 12:56 PM
I have a custom error logger that I want to:
1. Write a text file to a folder.
2. Using a web api, it sends an alert email to a staff members to notify that an error was written to a folder.
3. At the, end show the appropiate error view.
#1 and #3 worked fine before I introduced into the 'OnException' method code to process the #2. To do so, I had to add 'async' to the method as I am calling a web api that has that feature.
Now when MVC detects a code bug, it goes to the custom error logger but fails as it does not like the 'async' on the method.
I get:
An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.
How do I solve this as I want to call the web api to send that alert email?
I have in the FilterConfig.cs - the ErrorLoggerAttribute points to a custom error logger.
filters.Add(
new
ErrorLoggerAttribute());
Here is the custom ErrorLoggerAttribute.cs:
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// An async override method.
// - Fired off on exception.
//++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public
async
override
void
OnException(ExceptionContext filterContext)
{
//#############################################################################################
// Write a text file to the ClientErrorLog folder.
// - It may append to the text file if it already exists.
//#############################################################################################
string
strLogText =
""
;
Exception ex = filterContext.Exception;
filterContext.ExceptionHandled =
true
;
var objClass = filterContext;
// Set the text.
strLogText +=
"Message ---\n{0}"
+ ex.Message;
// Check the error source.
if
(ex.Source ==
".Net SqlClient Data Provider"
)
{
strLogText += Environment.NewLine +
"SqlClient Error ---\n{0}"
+
"Check Sql Error"
;
}
else
if
(ex.Source ==
"System.Web.Mvc"
)
{
strLogText += Environment.NewLine +
".Net Error ---\n{0}"
+
"Check MVC Code For Error"
;
}
else
if
(filterContext.HttpContext.Request.IsAjaxRequest() ==
true
)
{
strLogText += Environment.NewLine +
".Net Error ---\n{0}"
+
"Check MVC Ajax Code For Error"
;
}
strLogText += Environment.NewLine +
"Source ---\n{0}"
+ ex.Source;
strLogText += Environment.NewLine +
"StackTrace ---\n{0}"
+ ex.StackTrace;
strLogText += Environment.NewLine +
"TargetSite ---\n{0}"
+ ex.TargetSite;
if
(ex.InnerException !=
null
)
{
// Error prone.
strLogText += Environment.NewLine +
"Inner Exception is {0}"
+ ex.InnerException;
}
if
(ex.HelpLink !=
null
)
{
// Error prone.
strLogText += Environment.NewLine +
"HelpLink ---\n{0}"
+ ex.HelpLink;
}
// The Textwriter for writing characters to a stream.
StreamWriter log;
// Set the date.
// - For instance: 27-October-2020
string
timestamp = DateTime.Now.ToString(
"d-MMMM-yyyy"
,
new
CultureInfo(
"en-GB"
));
// Read the web.config and get the error log path to write an 'error log' text file to.
string
error_folder = ConfigurationManager.AppSettings[
"ClientErrorLogPath"
].ToString();
// Check if the error folder exists.
if
(!System.IO.Directory.Exists(error_folder))
{
System.IO.Directory.CreateDirectory(error_folder);
}
// Check if the text file exists.
// - For instance, looks for: ClientErrorLog\Log_27-October-2020.txt
if
(!File.Exists(String.Format(@
"{0}\Log_{1}.txt"
, error_folder, timestamp)))
{
// Create the text file.
log =
new
StreamWriter(String.Format(@
"{0}\Log_{1}.txt"
, error_folder, timestamp));
}
else
{
// Set for an add(append) to the text file.
log = File.AppendText(String.Format(@
"{0}\Log_{1}.txt"
, error_folder, timestamp));
}
var controllerName = (
string
)filterContext.RouteData.Values[
"controller"
];
var actionName = (
string
)filterContext.RouteData.Values[
"action"
];
// Start writing to the 'error log' text file.
// - First, write the timestamp to the file.
log.WriteLine(Environment.NewLine + DateTime.Now);
log.WriteLine(
"------------------------------------------------------------------------------------------------"
);
log.WriteLine(
"Controller Name :- "
+ controllerName);
log.WriteLine(
"Action Method Name :- "
+ actionName);
log.WriteLine(
"------------------------------------------------------------------------------------------------"
);
// Write the filter context.
log.WriteLine(objClass);
// Write the text.
log.WriteLine(strLogText);
// Write an empty line.
log.WriteLine();
//#############################################################################################
// Using the web api, send a client error alert email to a staff member (an Admin) as to notify
// that an error was written to the ClientErrorLog folder.
//#############################################################################################
string
errorMessage =
""
;
string
exceptionMessage =
""
;
try
{
// Instantiate the ControlResult for getting data from the web api.
ControlResult controlResult =
new
ControlResult();
// -----------------------------------------------------------------------------------------------------------------------------------------------
// 1st: There is no 'user name' available here - can't reference the session variable.
// A 'user name' is needed so that the process functions properly - need to access the web api with a valid 'user name'.
// -----------------------------------------------------------------------------------------------------------------------------------------------
// Get the control control 'user name'.
// - It calls a model class to execute a method.
controlResult = await GetControl();
// Check if an error occurred in the web api.
if
(controlResult.ApiErrorMessage ==
null
)
{
// Got the control 'user name' in order to access the web api'.
try
{
// -----------------------------------------------------------------------------------------------------------------------------------------------
// 2nd: Send a client error alert email to a staff member (an Admin) as to notify that an error was written to the
// ClientErrorLog folder.
// -----------------------------------------------------------------------------------------------------------------------------------------------
// Instantiate the ClientErrorResult for getting data from the web api.
ClientErrorResult clientErrorResult =
new
ClientErrorResult();
// Instantiate the BLL_Client class so that the functions can be referenced.
BLL_ClientError bll_ClientError =
new
BLL_ClientError();
// Call the web api to process the error.
// - It calls a model class to execute a method.
clientErrorResult = await bll_ClientError.ProcessClientErrorNoLog(controlResult.UserName);
// Check if an error occurred in the web api.
if
(clientErrorResult.ApiErrorMessage !=
null
)
{
// Set the error message with the web api error message. The ReasonPhrase set in BLL_ClientError.
errorMessage = controlResult.ApiErrorMessage;
}
}
catch
(Exception ex3)
{
// Friendly user message.
errorMessage =
"Server error on sending a client error alert. Exception error: "
+ ex3.Message;
}
}
else
{
// Set the error message with the web api error message. The ReasonPhrase set in BLL_Control.
errorMessage = controlResult.ApiErrorMessage;
}
}
catch
(Exception ex1)
{
// Friendly user message.
exceptionMessage =
"Server error on getting. Exception error: "
+ ex1.Message;
try
{
// Instantiate the ClientErrorResult for getting data from the web api.
ClientErrorResult clientErrorResult =
new
ClientErrorResult();
// Call the web api to process the error.
// Note: the 'user name' being passed. Using 'Control' as a 'user name' is not available.
// - It calls a model class to execute a method.
clientErrorResult = await ProcessClientError(
"Control"
, ex1.Message,
"Server error on getting the control field. Method: OnException"
);
// Check if an error occurred in the web api.
if
(clientErrorResult.ApiErrorMessage ==
null
)
{
// All good. Just show the friendly user message set above.
// Pass data from the controller to the corresponding view.
errorMessage = exceptionMessage;
}
else
{
// Set the error message with the web api error message. The ReasonPhrase set in BLL_ClientError.
errorMessage = clientErrorResult.ApiErrorMessage;
}
}
catch
(Exception ex2)
{
// Pass data from the controller to the corresponding view.
errorMessage =
"Failure in ProcessClientError. Exception error: "
+ ex2.Message +
". Original error: "
+ exceptionMessage;
}
}
// Check if there was an error.
if
(errorMessage ==
""
)
{
// Close the stream.
log.Close();
// Cancel the current session.
filterContext.HttpContext.Session.Abandon();
// Set the action result.
filterContext.Result =
new
ViewResult()
{
// Set the name of the view to render - the Views/Shared/Error.cshtml.
ViewName =
"Error"
};
}
else
{
// Write the error to the text file.
// - It may append to the text file if it already exists.
// Write to the 'error log' text file.
// First, write the timestamp to the file.
log.WriteLine(Environment.NewLine + DateTime.Now);
// Set the text with a header statement.
strLogText =
"Attmpted to send a client error alert email to a staff member (an Admin) - but got an error. See it below."
;
// Write the text.
log.WriteLine(strLogText);
// Write an empty line.
log.WriteLine();
// Clear the previous.
strLogText =
""
;
// Set the text with the error message.
strLogText +=
"Message ---\n{0}"
+ errorMessage;
// Write the text.
log.WriteLine(strLogText);
// Write an empty line.
log.WriteLine();
// Close the stream.
log.Close();
// Cancel the current session.
filterContext.HttpContext.Session.Abandon();
// Set the action result.
filterContext.Result =
new
ViewResult()
{
// Set the name of the view to render - the Views/Shared/ErrorSendingError.cshtml.
ViewName =
"ErrorSendingError"
};
}
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// async Method.
// Returns a model.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public
async Task<ControlResult> GetControl()
{
BLL_Control bll_Control =
new
BLL_Control();
ControlResult controlResult =
new
ControlResult();
try
{
// Call the model class to get the control field.
controlResult = await bll_Control.GetControl();
}
catch
(Exception)
{
throw
;
}
return
controlResult;
}
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
// async Method.
// Returns a model.
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
public
async Task<ClientErrorResult> ProcessClientError(
string
userName,
string
errorMessage,
string
additionalInfo)
{
BLL_ClientError bll_ClientError =
new
BLL_ClientError();
ClientErrorResult clientErrorResult =
new
ClientErrorResult();
try
{
// Call the model class to process the client error.
clientErrorResult = await bll_ClientError.ProcessClientError(userName, errorMessage, additionalInfo);
}
catch
(Exception)
{
throw
;
}
return
clientErrorResult;
}
Reply
Answers (
2
)
Having trouble with using "DatePicker" in MVC5 application
Insert image and description into database table