Hello,
I am developing window form application by using CSLA 4.5.501.0 with visual studio 2013 and dot net 4.0. I can successfully fetch data from remote dataportal.
The following is static factory method from BusinessBase class.
public static async Task<PurchaseHeader> GetPurchaseVoucher(string prefix, long serial)
{
VoucherNoCriteria criteria = new VoucherNoCriteria()
{
Prefix = prefix,
Serial = serial
};
PurchaseHeader purchase = await DataPortal.FetchAsync<PurchaseHeader>(criteria);
purchase.MarkOld();
return purchase;
}
----------------------------------------------------------------------------------
private async void SearchPurchase(VoucherNo vno) {
try
{
this.Cursor = Cursors.WaitCursor;
if (vno != null)
{
this.ultraStatusBar1.Text = string.Format("Loading purchase voucher ({0}-{1}).", vno.Prefix, vno.Serial);
this.purchase = await PurchaseHeader.GetPurchaseVoucher(vno.Prefix, vno.Serial);
BindData();
commandToolBar1.SetSavedState();
this.ultraStatusBar1.Text = string.Format("Done loading purchase voucher ({0}-{1}).", vno.Prefix, vno.Serial);
}
}
catch (Csla.DataPortalException ex) {
if (ex.BusinessException is RecordNotFoundException)
{
UltraMessageBoxManager.Show("Purchase voucher cannot found.", "Purchase", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (ex.BusinessException != null)
{
UltraMessageBoxManager.Show("Fail to load purchase voucher\n" + ex.BusinessException.Message, "Purchase", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
this.ultraStatusBar1.Text = "Ready";
}
catch (Exception ex)
{
UltraMessageBoxManager.Show("Fail to load purchase voucher\n" + ex.Message, "Purchase", MessageBoxButtons.OK, MessageBoxIcon.Error);
this.ultraStatusBar1.Text = "Ready";
}
finally {
this.Cursor = Cursors.Default;
}
}
But if awaiting async dataportal call throw exception, catch block is unable to catch exception and TargetInvocationException is throw at Application.Run() method in Program.cs.
How can I handle exception in this case.
Hi,
When you use async methods that return a Task you must catch System.AggregateException that may contain several exceptions. One of these exception will be a Csla.DataPortalException.
See this article: https://msdn.microsoft.com/en-us/library/dd537614(v=vs.110).aspx
As you suggested, I changed my code.
private async void SearchPurchase(VoucherNo vno) {
try
{
this.Cursor = Cursors.WaitCursor;
if (vno != null)
{
Program.MainForm.ShowLoading(string.Format("Loading purchase voucher ({0}-{1}).", vno.Prefix, vno.Serial));
this.purchase = await PurchaseHeader.GetPurchaseVoucherAsync(vno.Prefix, vno.Serial);
BindData();
commandToolBar1.SetSavedState();
Program.MainForm.HideLoading(string.Format("Done loading purchase voucher ({0}-{1}).", vno.Prefix, vno.Serial));
}
}
catch (AggregateException ex)
{
ex.Handle(x => { HandleException("Failed to load purchase voucher", x); return true; });
}
catch (Csla.DataPortalException ex)
{
if (ex.BusinessException is RecordNotFoundException)
{
Program.MainForm.HideLoading("Ready");
UltraMessageBoxManager.Show("Purchase voucher cannot found.", "Purchase", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
else if (ex.BusinessException != null)
{
HandleException("Fail to load purchase voucher",ex);
}
}
catch (Exception ex)
{
UltraMessageBoxManager.Show("Fail to load purchase voucher\n" + ex.Message, "Purchase", MessageBoxButtons.OK, MessageBoxIcon.Error);
Program.MainForm.HideLoading("Ready");
}
finally {
this.Cursor = Cursors.Default;
}
}
Here I found two interesting things.
1.If exception is thrown by server side code (in my case, I throw my custom exception 'RecordNotFoundException'), it pass to the client and I can successfully catch the exception (by DataPortalException catch block not by AggregateException catch block) that return from server as expected.
2.If exception is throw by client code (in my case, I unplugged network cable from my computer to throw exception), the exception cannot be catch as expected and throw at Application.Run() method in Program.cs.
As workaround, I catch this kind of user unable to handle exception by using Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException) and
attach event handler
Application.ThreadException += Application_ThreadException.
But it is not perfect. Because I cannot perform required action if communication is failed.
Thanks
Chit Swe
Copyright (c) Marimer LLC