I'm trying to show a Duplicate Record error message in an WebAPI service. I'm using .net5 and mysql. I cannot seem to find a way to pull the duplicateEntry message from the exception response. I'd like to key in on the ErrorCode field and use this to tailor a response to the user. I can see the Message property, but cannot figure out how to access the innerException.
{
try
{
module.Id = Guid.NewGuid();
await _moduleRepository.Add(module);
await _uow.CompleteAsync();
return true;
}
catch (DbUpdateException ex)
{
logger.LogWarning("Module - Add Error: " + ex.Message);
return false;
}
}
You may try to catch an Exception object which has a InnerException attribute. Also, you may also check DbEntityValidationException class.
Reference: link
Found something that worked. Made a helper function, but this is highly coupled to Mysql. Had to check the InnerException to see if it was of type MsyqlException.
{
public static string GetExceptionMessage(Exception ex)
{
var message = ex.Message;
var innerException = ex.InnerException;
if (innerException != null && (innerException.GetType() == typeof(MySqlException)))
{
var dbException = (MySqlException)innerException;
if(dbException.ErrorCode == MySqlErrorCode.DuplicateKeyEntry)
{
return ErrorMessages.RecordExists;
} else
{
return ErrorMessages.UnknownError;
}
}
return message;
}
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 1 year ago.
I have an SSIS package which calls a Data Flow Task as part of a loop which iterates different end-point addresses (out of scope).
The Data Flow Task has a source Script Component responsible for calling a REST API and creating a row for each result.
There are 3 output buffers;
1. actual data row
2. error row
3. monitoring
The monitoring buffer used for telemetry and is populated through an event (EventHander) that is fired every time the API makes a request.
During the first iteration of the ForEach int the Control Flow loop, everything runs as expected, all the buffers produce the correct rows.
However, during the next iterations, the monitoring buffer which is populated within the event throws;
System.NullReferenceException: Object reference not set to an instance of an object.
at Microsoft.SqlServer.Dts.Pipeline.ScriptComponentHost.HandleUserException(Exception e)
at Microsoft.SqlServer.Dts.Pipeline.ScriptComponentHost.PrimeOutput(Int32 outputs, Int32[] outputIDs, PipelineBuffer[] buffers)
at Microsoft.SqlServer.Dts.Pipeline.ManagedComponentHost.HostPrimeOutput(IDTSManagedComponentWrapper100 wrapper, Int32 outputs, Int32[] outputIDs, IDTSBuffer100[] buffers, IntPtr ppBufferWirePacket)
I don't understand why the MonitoringBuffer is not initialised in the proceeding iterations.
The exception occurs while calling MonitoringBuffer.AddRow();.
Here's the whole Script Component simplified for readability:
[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
private string ClientCode { get { return Variables.ErplyClientCode; } }
private string Username { get { return Variables.ErplyUsername; } }
private string Password { get { return Variables.ErplyPassword; } }
private bool IsTest { get { return Variables.IsTest; } }
private int ErplyRecordsPerPage { get { return Variables.ErplyRecordsPerPage; } }
private string ErplyDebugOutputPath { get { return Variables.ErplyDebugOutputPath; } }
private DateTime ChangeSince { get { return Variables.ChangeSince; } }
private int records { get; set; }
private int errors { get; set; }
private string rawFolder { get; set; }
public override void PreExecute()
{
base.PreExecute();
}
public override void PostExecute()
{
base.PostExecute();
}
public override void CreateNewOutputRows()
{
ErplyAPI.OnPreRequestEvent += new EventHandler<EAPIEvent>(ErplyAPI_OnPreRequestEvent);
var staff = ErplyAPI.getStaff(ClientCode, Username, Password, ChangeSince, ErplyRecordsPerPage, IsTest);
foreach (var p in staff.List)
{
try
{
if (!p.IsError)
{
EmployeeBuffer.AddRow();
EmployeeBuffer.employeeID = p.employeeID;
}
else
{
ErrorBuffer.AddRow();
ErrorBuffer.employeeID = p.employeeID;
ErrorBuffer.Error = p.Error.Message.Trim() + "\n" + p.Error.StackTrace;
errors++;
}
records++;
}
catch (Exception ex)
{
this.ComponentMetaData.FireWarning(0, "Script", ex.Message + "\n" + ex.StackTrace, string.Empty, 0);
}
}
EmployeeBuffer.SetEndOfRowset();
ErrorBuffer.SetEndOfRowset();
}
private void ErplyAPI_OnPreRequestEvent(object sender, EAPIEvent e)
{
var request = string.Empty;
var sessionKey = string.Empty;
bool fireAgain = true;
if (e == null)
{
ComponentMetaData.FireWarning(0, "SC_ERPLY_API", string.Format("EAPIEvent is NULL in ErplyAPI_OnPreRequestEvent. Amonit did not log the Erply request."), string.Empty, 0);
return;
}
if (e.eAPI == null)
{
ComponentMetaData.FireWarning(0, "SC_ERPLY_API", string.Format("EAPIEvent.eAPI is NULL in ErplyAPI_OnPreRequestEvent. Amonit did not log the Erply request."), string.Empty, 0);
return;
}
try
{
if (e.Parameters != null && e.Parameters.ContainsKey("request"))
request = e.Parameters["request"].ToString();
if (request != "verifyUser" && e.Parameters != null && e.Parameters.ContainsKey("sessionKey"))
sessionKey = e.Parameters["sessionKey"].ToString();
}
catch (Exception ex)
{
ComponentMetaData.FireWarning(0, "SC_ERPLY_API", string.Format("Error occurred assigning variables from EAPIEvent parameters in ErplyAPI_OnPreRequestEvent. {0} {1}", ex.Message, ex.StackTrace), string.Empty, 0);
}
try
{
MonitoringBuffer.AddRow(); // Exception occurs here
MonitoringBuffer.Request = ResizeString(request, 255);
MonitoringBuffer.SessionKey = ResizeString(sessionKey, 128);
}
catch (Exception ex)
{
var message = string.Format("Error occurred outputting Erply request in ErplyAPI_OnPreRequestEvent. {0} {1}", ex.Message, ex.StackTrace);
MonitoringBuffer.ErrorMessage = ResizeString(message, 8000);
ComponentMetaData.FireWarning(0, "SC_ERPLY_API", message, string.Empty, 0);
}
finally
{
MonitoringBuffer.EndOfRowset();
}
}
}
I sorted the problem out.
The exception was being raised when the variable dispenser was being accessed from the Event. For some reason the GetValueWithContext(ScriptComponent.EvaluatorContext) is being dropped during the second call. Why this happens is beyond me.
The solution is simple, assign the variables from the variables dispenser to a local property or variable in the OnPreExecute function.
It's also good practice to not call the variable dispenser in the CreateNewOutputRows as it cause variable locking.
I ran into this issue too, but my solution was a little different -- moving the variable assignments into PreExecute() didn't help.
Instead, what I'd done is that I wanted to parse three different files, and read each of them with a Script Component. Their columns were kinda similar, so I created one Data Flow task, made sure it worked, then copied it and modified each copy to reflect the differences in the files. Running each individual Data Flow task was successful, but when I tried to run two of them, one after the other in a loop, I got a NullReferenceException from HostPrimeOutput() after calling the OutputBuffer.AddRow() method in my Script Component.
It turns out that when I copied each Data Flow task, the Script Components all kept the same namespace, and I guess it doesn't like that. So, I created brand new Script Components, set up all the output columns again (ugh!), copied the body of the script over, and it's happy.
i have the following code that gets an error message.i want to pass it into a string before an exception is thrown,this is my code
ValidateError(authDeserialized, "Succeed", "error", "failed"); //the validateError is a function as indicated below
Model.Response= authResponse.Content;
protected static void ValidateError(dynamic response, string validStatus,string categoryMatch, string message)
{
if (response.result.status != validStatus)
{
try
{
var category = response.result.category;
if (category == categoryMatch)
message=ErrorCodes.MessageFor(code,description);
//so i get the message back fine here but now how do i pass it back to this line Model.Response= authResponse.Content; so that it can get saved?
}
catch (Exception) { }
throw new Exception(message ?? "Request was not successfull");
}
}
As you are already sending message to the ValidateError() method, pass that parameter as a out parameter, it will update value of message if you assign new value to it then it will update message and will be accessible to outside environment.
string failureMessage = "failed";
ValidateError(authDeserialized, "Succeed", "error", out failureMessage);
//^^^ This is what you have to change
//Now you can assign failureMessage to any other value
Model.Response= authResponse.Content;
protected static void ValidateError(dynamic response, string validStatus,string categoryMatch, out string message)
{ //^^^ This is what you have to change
if (response.result.status != validStatus)
{
try
{
var category = response.result.category;
if (category == categoryMatch)
message=ErrorCodes.MessageFor(code,description); //so i get the message back fine here but now how do i pass it back to this line Model.Response= authResponse.Content; so that it can get saved?
}
catch (Exception) { }
throw new Exception(message ?? "Request was not successfull");
}
}
In this way you can assign value to failure message before throwing an error.
Try out online
I am working on ASP.NET web application (C# Language). One of my task is to send email to 1000 to 2000 person at a time.
I got problems like some end users(Email Receivers) got duplication multiple copies of same email content.
This method will call one by one as per new email address got from list. Due to privacy I remove some part of this method.
[System.Web.Services.WebMethod]
public static CampMaster SendMailContinue(int CustId)
{
try
{
Customers Customer = null;
Customer = Customers.GetbyCustNextId(CustId,true).FirstOrDefault();
string sTemplate = "Here will be Template content.";
#region SendMail
if (IsValidEmail(Customer.Email))
{
if (Globals.SendMail(sTemplate, FromEmailAddress, FromName, ToEmail,EmailSubject))
{
//Sent Success
}
}
sTemplate = string.Empty;
return true;
#endregion
}
}
catch (System.Threading.ThreadAbortException)
{
return null;
}
catch (Exception ex)
{
return null;
}
//Client Side Code by Call WebMethod.
function SendMailContinue(CustId, true) {
PageMethods.SendMailContinue(CustId, true, OnGetSuccessSendMailContinue, OnGetFailureSendMailContinue);
return false;
}
I am working on outlook add-in where I need to set a custom header. I am using VS2010 for my development.
I am trying with the following code but it doesn't seems to be working.
private void AddUserProperty(Outlook.MailItem mail, string folderEmailId)
{
Outlook.PropertyAccessor mailPropertyAccessor = null;
try
{
if (string.IsNullOrEmpty(folderEmailId))
return;
mailPropertyAccessor = mail.PropertyAccessor;
mail.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-WorksiteFolderEmailId", folderEmailId);
mail.Save();
try
{
MessageBox.Show("Existing :" + mail.PropertyAccessor.GetProperty("http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-WorksiteFolderEmailId"));
}
catch (System.Exception ex)
{
MessageBox.Show(ex.Message);
}
}
catch (System.Exception ex)
{
Logger.Error(ex);
MessageBox.Show(ex.Message);
}
finally
{
if (mailPropertyAccessor != null)
Marshal.ReleaseComObject(mailPropertyAccessor);
}
}
After saving the mail item, I am trying to fetch the same item for verification, but it's throwing an exception saying the property not found.
I don't see a problem with your code, although getting a reference directly to the PropertyAccessor is unnecessary. Try:
string prop = "http://schemas.microsoft.com/mapi/string/{00020386-0000-0000-C000-000000000046}/X-WorksiteFolderEmailId";
mail.PropertyAccessor.SetProperty(prop, folderEmailId);
mail.Save();