WCF Which messages to return after catching an exception? - wpf

I am using a wcf service and I know how to catch all the exceptions I need...
But I dont know which messages should I return?
My code:
try
{
currentPosition = await locator.GetGeopositionAsync();
}
catch (FaultException<MessageError> ex)
{
MessageBox.Show(...?);
}
catch (EndpointNotFoundException ex)
{
MessageBox.Show(...?);
}
catch (CommunicationException ex)
{
...
}
catch (Exception ex)
{
...
}
I can return ex.Message but I dont want the client to know all the details, I want to show a short and helpful message.
What should I do?

I have always handled this situation in a similar way to the way that #Tim suggested in his comment. I need as much information to be saved so that I can debug the problem at a later date, but as you said, we don't want to show the end user the developer Exception messages.
Therefore the solution that I use is simply to store the information that comes from the Exception in the database and to provide the user with 'user-friendly' error messages. Make sure that you also add code to record any inner Exceptions as well if they exist. Now to address the question as to what to put in these messages... it really depends on your situation, but I generally follow this procedure.
First, I work out (either from forward thinking or from test results) which are the most likely errors to occur... off the top of my head, I'm talking about errors like 'no network access', or 'invalid user security', etc.
When I have a number of possible errors, I will attempt to catch the exact errors with a number of catch statements as you have. Inside the handlers, I check for certain Exception messages and return pre-written user friendly messages for each. Finally, I add one last generic message to display for all unforeseen error situations.

Related

Try/Catch does not work on conversion error, while importing data from excel in X++

I am trying to import data from excel to my journal, but if there is a conversion error, it just blocks my journal. I want to make try/catch exception, but it does not work.
My code looks like this:
try
{
[My insert code]
}
catch (Exception::Error)
{
throw error("error here");
}
Error looks like this:
Error executing code: Wrong type of argument for conversion function.
And first suggestion probably will be "Fix the conversion code", but it wouldnt resolve my problem...
Does anyone know why my catch block does not see that error?
I tried to find exception for conversion errors, but there is like 0 information about it on internet.
Try without this (Exception::Error) because it is probably that your code does not give an Error exception.
try
{
[My insert code]
}
catch
{
throw error("error here");
}
There are only two possible reasons why your catch does not work:
The conversion code does not throw an Error exception.
It might throw a CILError or something else.
You have a ttsBegin / ttsCommit outside of your try / catch.
Exceptions inside a transaction cannot be caught (for good reasons).

Strange behavior with try-catch on Dynamics Ax 2012

I'm trying without success to figure out what I'm doing wrong trying to handle one exception in my code, hopefully someone can help me.
I'm reading an external database from within Ax to integrate some customers. So I loop through a series of records using a ResultSet object. at a given point I have some code that looks like this:
while (resultSet.next())
{
//some logic (...)
ttsbegin;
//This is a custom table that stores to where I want to integrate the given customer
while select integrationCompany
where integrationCompany.CRMCompany == customerInfo.parmCRMDataAreaId()
{
changeCompany(integrationCompany.ERPCompany)
{
try
{
customerInfo.createCustomer();
//.. some more logic
}
catch
{
// My catch Block, that should update the source database to set
// the processing status to "error"
ttsAbort;
}
}
}
ttsCommit;
}
And inside the customerInfo.createCustomer() method I'm explicitly throwing some exceptions (throw Exception::Error) if some requirements aren't met.
The problem is that the catch block isn't reached - the program stops without getting back to the main routine.
Does it has something to do with the transaction opening/aborting/commiting or is something else?
AX (X++) is strange here (if you are used .NET/Java like try/catch scenario).
If you have try inside the transaction, then fist catch cathes the excation (which is Enum and not sort of exception object).
From the MSDN: Exceptions Inside Transactions:
When an exception is thrown inside a ttsBegin - ttsCommit transaction block, no catch statement inside that transaction block can process the exception. Instead, the innermost catch statements that are outside the transaction block are the first catch statements to be tested.

Display a message if user is unauthorised to run a stored procedure

I am new to stored procedures and am just curious how things are done. What I would like to know is how to display a message if a user tries to execute a procedure that he has no rights on ?
From what I can fathom, SQL Server itself takes care of the message. I tried this way (inside a stored procedure) :
BEGIN
try
DELETE from MYTABLE
END TRY
BEGIN CATCH
SELECT ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
and it makes no difference weather I write this or not. The error is the same. Didnt figure out how to write your own message though ...
If a user tries to execute a stored procedure or user-defined function (UDF) that they have not been granted permissions to, either explicitly or implicitly through one or more role memberships, then SQL Server will handle the exception and error message. You cannot set a message within that code as by definition the user is not allowed to execute it to get any error message or error handling that would be inside of it.
If you want a custom message, you need to catch the SQL Exception from the app side (there should be an error code that you can test for indicating "Permission Denied") and then just return your custom message.
There is fix message or say default message display when you try to access unauthorized object.
There is so many security feature comes, like user, role, schema etc. If anything mismatch, you get the error "Could not find stored procedure 'guest.get_procedureName'."
suppose I was created a procedure with default schema(dbo) the name procedure1.
exec dbo.procedure1 para1value,'para2value', null,para4value etc.
exec guest.procedure1 para1value,'para2value', null,para4value etc.
Now if everything fine, first one give me data to sql side and C# side.
But the second will give me the above error.
Nothing to handle in the sqlserver side for this type of security, As above your code, try catch is same work as C#, but ideally, it only need when you explicitly want the message from sql return to show directly to ui i.e. custom logic error message, while you run the sp or when mismatch the data etc.
For the c# point of view, you can get this message in catch, so you can do like.
public method
{
try
{
.....
}
catch(Exception ex)
{
if (ex.Message.Contains("Could not find"))
//give any your custom message or throw ex
}
}
try
DoTheThing();
except
on E:Exception
ShowMessage("Something Went Wrong! : " + E.Message);
end;
This shows a custom message (of sorts) and it also gives you a means to examine the contents of the error via 'E'.
You can also handle more specific exceptions
except
on E:ESomeSpecificException
// ----
end;
--
As others have pointed out - there is no point in trying to catch the error inside the stored proc - the user doesnt have access to it ... by definition

WCF service in WPF self host application crash when I throw a fault exception (async methods)

I have a service hosted in a WPF application with an async method with the Begin/end methods, and when I catch an exception in the service, I want to throw a faultException to warn to the client.
However, when I try to throw the faultException, the host application crash, shutdown suddenly.
In my repository, I catch the UpdateException, then, I create a custom exception, UniqueKeyException, that is throw to the caller. The caller is an auxiliar method that is called in the Begin method.
This auxiliar method, catch the UniqyeKeyException and only do a "throw", that is capture in the try/catch block of my end method. Here there is something that I don't understand, why in the end mehod this exception is catched in the block of AgregateException instead of the UniqueKeyException.
Well, anyway, in the catch block of the end method, in the AgregateException block, I check if the innerException is UniqueKeyException, if it is true, I create an object UniqueKeyArgs (a custom class with the information to send to the client), create a FaultException and finally do the throw FaultException. It is in this step, the throw, where the host application crash.
I think that I have all configure correctly, because my custom class UniqueKeyArgs is decorate as Datacontract and its properties as DataMember, in the app.config of my host application I configure the behavior to include exception details and in the contract I decorate it with faultContract.
Why the application crash?
My code is the following:
REPOSITORY
public List<Usuers> updateUsers(List<Users> paramUsers)
{
....
catch(UpdateException ex)
{
SqlException innerEx = (SqlException)ex.InnerException;
//Code 2627 is Unique Key exception from SQL Server.
if (innerEx != null && innerEx.Number == 2627)
{
//I create the conditions of searching
ConditionsUsers conditions = new conditions();
conditions.UserName = (Users)ex.StateEntries[0].Entity).userName;
//Search for the existing user
Users myUser = getUser(conditions);
string message = "the user " + conditions.userName + " exists.";
throw new UniqueKeyException(message, myUser);
}
throw;
}
SERVICE IMPLEMENTATION
//This is my auxiliar method, called in the Begin method.
private submitUpdates()
{
....
catch(UniqueKeyException ex)
{
//The code enter here
throw;
}
}
public IAsyncResult BeginUpdateUsers(List<users> paramUsers, AsyncCallback callback, object state)
{
Task<List<Users>> myTask= Task<List<Users>>.Factory.StartNew(p => sumbmitUpdates(paramUsers), state);
return myTask.ContinueWith(res => callback(myTask));
}
public List<Users> EndUpdateusers(IAsyncResult result)
{
try
{
return ((Task<List<Users>>)result).Result;
}
//Why agregateException and not is catched in the UniqueKeyException ???
catch(AgregateException ex)
{
if (innerExceptions[0] is UsuariosValorUnicoException)
{
//I assign manually the data to debug, to discard other problems.
Users myUser = new Users();
myUser.UserName = "Jhon";
myUser.Password = "pass123";
UniqueKeyArgs myArgs = new UniqueUserArgs("unique key error", myUser);
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs);
//Crash here, in the throw myException
throw myException;
}
}
throw;
}
MY CONTRACT
[FaultContract(typeof(UniqueKeyArgs))]
IAsyncResult BeginUpdateUsers(List<Users> paramUser, AsyncCallback callback, object state);
List<Users> EndUpdateUsers(IAsyncResult result);
Crash when I throw myException in the End method.
I see in this post that the solution is catch the exception in the host application too, not only in the service object. However, this solution uses Application.ThreadException, that belong to System.Windows.Forms namespace, and I am using a WPF application.
How could I send the exception to the client from a service hosted in a WPF application?
Thanks.
EDIT1: well, I am use a try/catch block in the line where I throw the exception and I see that the error is that I have not indicated a reason, so when I create my FaultException I do:
FaultException<UniqueKeyArgs> myException = new FaultException<UniqueKeyArgs>(myArgs, new FaultReason("DummyReason");
In this case, the exception message is "DummyReason", the message that I set in the FaultReason, so it says me nothing. The FaultException is not throw, and throw the generic exception to the client.
In this case the host application does not shutdown, but close the connection with the client and I have to reconnect.
It seems that the problem is the creaton of the FaultException, but I don't see the problem.
#Roeal suggests that perhaps is only possible to use faultException with synch methods, but in this link I can see an example in which is used with async methods. I have seen others examples, is not the unique.
Thanks.
EDIT2: I solve my problem. My problem is that in the FaultException, T is an object that have a property that was a self tracking entity, and this is a problem, if I am not wrong, I only can use basic types as properties of the exception.
Then, in the exception, I have implmemented ISerialize. It's needed to be able to send the information to the client, without this, the client receives an exception.Detail with null properties.
Did you also declare the synchronous operation in your service contract? In that case, maybe this helps:
If fault contracts are defined on the service operation contract, the FaultContract attribute should be applied only on the synchronous operations.
-- Juval Lowy, "Programming WCF Services 3rd Edition" (p456)
I solve my problem. My problem is that in the FaultException, T is an object that have a property that was a self tracking entity, and this is a problem, if I am not wrong, I only can use basic types as properties of the exception.
Then, in the exception, I have implmemented ISerialize. It's needed to be able to send the information to the client, without this, the client receives an exception.Detail with null properties.

Try Catch block in Siebel

I have a script which sends a set of records into a file. I'm using Try - Catch block to handle the exceptions. In the catch block I have a code where it has the pointer to next record. But this is not executing . Basically I wan to skip the bad record n move to next record.
while(currentrecord)
{
try
{
writerecord event
}
catch
{
currentrecord = next record
}
}
In most languages (unless you're using something very strange), If 'writerecord event' doesn't throw an exception, the catch block will not be called.
Don't you mean :
while(currentrecord) {
try { writerecord event }
catch { log error }
finally { currentrecord = next record}
}
Are you trying to loop through some records that are returned by a query? Do something like this:
var yourBusObject = TheApplication().GetBusObject("Your Business Object Name");
var yourBusComp = yourBusObject.GetBusComp("Your Business Component Name");
// activate fields that you need to access or update here
yourBusComp.ClearToQuery();
// set search specs here
yourBusComp.ExecuteQuery(ForwardOnly);
if (yourBusComp.FirstRecord()) {
do {
try {
// update the fields here
yourBusComp.WriteRecord();
} catch (e) {
// undo any changes so we can go to the next record
// If you don't do this I believe NextRecord() will implicitly save and trigger the exception again.
yourBusComp.UndoRecord();
// maybe log the error here, or just ignore it
}
} while (yourBusComp.NextRecord());
}
You can use try-finally structure so that whatever inside the finally block will always be executed, regardless of whether the code throws an exception or not. It's often used to clean up resources such as closing files or connections. Without a catch clause, any thrown exception in your try block will abort execution, jump to your finally block and run that code.
Agree that 'finally' might be the best bet here - but do we know what the exception actually is ? - can you output it in your catch loop, so that :
A) you can prove an exception is being thrown (rather than say a 'null' being returned or something)
B) Make sure the exception you get isn't something that could prevent 'nextrecord' working as well...[not sure what the 'finally' would achieve in the case - presumably the exception would have to bubble up to calling code?
So you're trying to move onto the next record if you failed to commit this one. Robert Muller had it right. To explain...
If the WriteRecord fails, then the business component will still be positioned on the dirty record. Attempting to move to the next record will make the buscomp try to write it again--because of a feature called "implicit saving".
Solution: You'll have to undo the record (UndoRecord) to abandon your failing field changes before moving onto the next one.

Resources