I personally find vague error messages a pain. In my new practice project I am trying to add additional validation to the user input. However, ASP.NET MembershipCreateStatus has Members; e.g. InvalidEmail that takes care of some of these areas when the CreateUser Method is used.
I can do an if statement or Regex on the submitted email before the input reaches the Membership.CreateUser Method. However, I am not sure where to start with this:
I know this question is a little subjective but I hate to find out later that there is a better way, and if you are just starting up, it can be a lifesaver.
Should I create an additional validation Method to check for very specific formatting errors in the email, in addition to the system checking. As you can see the error message does not say why it is invalid.
Also is it possible to create my own enum for example, email contains underscore, which I can attached to the MembershipCreateStatus? If so how?
Here is my sample code, abbreviated:
public string GetErrorMessage(MembershipCreateStatus status)
{
switch (status)
{
case MembershipCreateStatus.InvalidEmail:
return "The e-mail address provided is invalid.";
default:
return "Go to jail!!";
}
}
protected void btnSubmit_Click(object sender, EventArgs e)
{
try
{
Membership.CreateUser(txtUserName.Text, txtPassword.Text, txtEmail.Text);
}
catch (MembershipCreateUserException ex)
{
ltrStatusMsg.Text = GetErrorMessage(ex.StatusCode);
}
catch (HttpException ex)
{
ltrStatusMsg.Text = ex.Message;
}
}
Thanks my friends.
There are lots of ways to skin a cat. Certainly you can do your own validation before calling Membership.CreateUser. Your validation method could throw a MembershipCreateUserException and reuse one of the existing status codes, or throw a different exception. The exception you throw could be a custom exception, or you could reuse an existing exception type such as ValidationException.
try
{
ValidateUser(txtUserName.Text, txtPassword.Text, txtEmail.Text);
Membership.CreateUser(txtUserName.Text, txtPassword.Text, txtEmail.Text);
}
catch (MembershipCreateUserException ex)
{
ltrStatusMsg.Text = GetErrorMessage(ex.StatusCode);
}
catch (ValidationException ex)
{
ltrStatusMsg.Text = ex.Message;
}
catch (Exception ex)
{
// log exception ...
ltrStatusMsg.Text = "An unexpected error occurred while creating the user";
}
...
private void ValidateUser(...)
{
if (... not valid ...) throw new ValidationException("some suitable message");
}
In my CustomMembershipProvider I don't use the CreateUser method, I have a CreateUser method as part of my User business object code with an output parameter (Custom Enum) with the various invalid (or valid) result.
Related
I have a function to check whether an email entered is valid:
bool IsValidEmail(string email)
{
try
{
var addr = new System.Net.Mail.MailAddress(email);
return addr.Address == email;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.Message);
return false;
}
}
Even though it's within a try/catch I still get an exception when an invalid email is entered stating:
'The specified string is not in the form required for an e-mail address.'
I have used this function in other applications and it works fine. Not sure what's going on with it now.
Edit: Solution was my Exception settings, my VS was ignoring the try/catch
catch (Exception ex)
can't catch all the exceptions. Only managed ones.
You can use catch without type:
catch
{
return false;
}
Not sure if it is a good point. You can't handle something like Environment.FailFast call inside a constructor of MailAddress
Anyway, it looks like your problem is not there.
Please, add a stack trace of your exception if you want more help.
I have a code segment that is responsible for orchestrating the execution of a few modules and it is very sensitive to errors - I want to make sure I log and alert about every exception that occurs.
Right now I have something like this:
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
}
catch (Exception ex)
{
string errorMessage = string.Format("Module A failed doing it's thing. Specific exception: {0}", ex.Message);
// Log exception, send alerts, etc.
}
try
{
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
string errorMessage = string.Format("Module B failed doing it's thing. Specific exception: {0}", ex.Message);
// Log exception, send alerts, etc.
}
// etc for other modules.
It looks to me that the multiple try-catch is making this segment less readable. Is it indeed the right thing to do?
Yes, it's the right thing.
But you should have the performance in in mind, maybe it's better to put all method calls in one try/catch and add stack trace and error information in the exception in the methiod itself.
public void ModuleA.DoSomethingA()
{
throw new Exception("Error in module A");
}
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
// get information about exception in the error message
}
You did well.
This way, you can process the error after each module. If you want to run it all and then do error handling, consider this alternative:
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch(ModuleAException ex)
{
// handle specific error
}
catch(ModuleBException ex)
{
// handle other specific error
}
catch (Exception ex)
{
// handle all other errors, do logging, etc.
}
i think that depends on the approach that you want to follow.
It seems like you error messsages are different for each module that raises exception so i guess the approach that you followed is right.
you could have put the whole thing in a big try - catch block then in that case you will not know which module caused the exception as a generic excpetion gets printed.
try
{
ModuleAResult aResult = ModuleA.DoSomethingA();
ModuleBResult bResult = ModuleB.DoSomethingB();
}
catch (Exception ex)
{
string errorMessage = string.Format("Either Module A or B failed", ex.Message);
// Log exception, send alerts, etc.
}
So if you want your exception handling to not be cleaner use the above code.
Otherwise what you followed is absolutely fine.
I am trying to figure out how to return exceptions and errors up to the controller level from my repository and be able to return custom errors to the client when they call my web service.
I have the following example from my BookRepository class:
public BookViewModel GetBookById(Guid id)
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
obviously my function would be a little more complicated than this, but if i called this method on a id that did not exist i would get an exception. How can I have my exceptions and custom errors bubble up to my controller and then displayed nicely in the client response
Even a web service should follow the same patterns as any other code, with respect to exception handling. Those best practices include not using custom exceptions unless the caller is going to make a programmatic choice based on the exception type. So,
public BookViewModel GetBookById(Guid id)
{
try
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
catch (SpecificExceptionType1 ex)
{
Log.Write(ex);
throw new Exception("Some nicer message for the users to read", ex);
}
catch (SpecificExceptionType2 ex)
{
Log.Write(ex);
throw new Exception("Some nicer message for the users to read", ex);
}
catch (Exception ex)
{
Log.Write(ex);
throw; // No new exception since we have no clue what went wrong
}
}
what edmastermind29 mentioned is one common way to do it. i would usually the same way.
but sometimes developers like to catch the exception before the controller and return a result message based on enumerated value for example , so the controller would have no try catch blocks for that call, it will only need to check the status message.
you can use out parameter to check status and display messages for users accordingly.
this is how ASP.NET Membership provider is implemented.
check the method create user in Membership provider for example:
http://msdn.microsoft.com/en-us/library/system.web.security.membershipprovider.createuser(v=vs.100).aspx
Place a try-catch around methods, LINQ queries, etc. that may fail given a circumstance (null value, empty value, invalid value, etc.). From there, you can catch the exception, and throw a custom exception tailored to what you are looking for. See below.
public BookViewModel GetBookById(Guid id)
{
try
{
var Book = _Books.Collection.Find(Query.EQ("_id", id)).Single();
return Book;
}
catch (Exception e)
{
Log.Write(e)
status = "Some Custom Message";
}
catch (DoesNotExistException dne)
{
Log.Write(dne)
status = "Some Custom Message about DNE";
}
}
I have a line:
string[] cPathDirectories = Directory.GetDirectories(Properties.Settings.Default.customerFolderDirectory);
that will throw the error "Path is not of legal form" if the user didn't specify a search path (this setting is saved as String.Empty at this point). I would like throw this error to say, "Hey you idiot, go into the application settings and specify a valid path" instead. Is there a way to do this instead of:
...catch (SystemException ex)
{
if(ex.Message == "Path is not of legal form.")
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
No, you need to check what the type of the exception is and catch that explicitly. Testing for strings in exception messages is a bad idea because they might change from one version of the framework to another. I'm pretty sure Microsoft doesn't guarantee that a message will never change.
In this case, looking at the docs you might be getting either a ArgumentNullException or ArgumentException, so you need to test for that in your try/catch block:
try {
DoSomething();
}
catch (ArgumentNullException) {
// Insult the user
}
catch (ArgumentException) {
// Insult the user more
}
catch (Exception) {
// Something else
}
Which exception you need here, I have no idea. You need to determine that and structure your SEH block accordingly. But always try to catch exceptions, not their properties.
Note the last catch is highly recommended; it ensures that if something else happens you won't get an unhandled exception.
you might check for an argument exception
...catch (SystemException ex)
{
if(ex is ArgumentException)
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
That's an ArgumentException:
catch (ArgumentException) {
MessageBox.Show("Please enter a path in settings");
} catch (Exception ex) {
MessageBox.Show("An error occurred.\r\n" + ex.Message);
}
A couple ways to go about it.
First, just check the setting first before you make the GetDirectories() call:
if(string.IsNullOrEmpty(Properties.Settings.Default.customerFolderDirectory))
{
MessageBox.Show("Fix your settings!");
}
else
{
string[] cPathDirectories = Directory.GetDirectories(Properties.Settings.Default.customerFolderDirectory);
}
Or catch a more specific exception:
catch (ArgumentException ex)
{
MessageBox.Show("Hey you idiot, go into the application settings and specify a valid path","Error");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
I'd probably go with the former, since then you don't run into a penalty (albeit minor) for exception throwing and can do any other validation you want such as checking whether the path exists, etc.
If you prefer the latter, though, you can find the list of exceptions Directory.GetDirectories() throws here, so you can tailor your messages appropriately.
P.S. I also wouldn't call your users idiots, but that's between you and your god. :)
Yes, you can again throw exception from catch block, example:
catch (SystemException ex)
{
if(ex.Message == "Path is not of legal form.")
{
throw new Exception("Hey you idiot, go into the application settings and specify a valid path", ex);
}
else
{
MessageBox.Show(ex.Message,"Error");
}
}
Modifying to make it clear:
I have a question on exception logging and graceful exit. This is in continuation with previous question. The code looks like:
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
if (status != "-1")
{
status = objA.Method1();
}
}
catch (Exception Ex)
{
//Log Exception EX
}
Inside the Method1:
public string Method1()
{
string status = "0";
try
{
//Code
return "0";
}
catch (Exception Ex)
{
//Log Exception with details
return "-1"
}
}
I log the Exception in the calling method and return only a status to the caller.
Should I return the Exception to the calling method or is only a status sufficient. With a status of "-1", I know there was an Exception in the called method and details of that Exception were logged in a log file.
I think it is OK to do it like that if you have a lot of status codes, otherwise you could also just throw an exception and catch it in the method higher up.
Also maybe reconsider your return type. Looks like you could be using integers, think you are opening yourself up to errors using strings.
Don't use the status return value, it is not adding anything that is useful to you.
consider,
var a = new ClassA()
try
{
a.Mehtod1();
}
catch
{
try
{
a.Method1();
}
catch (Exception ex)
{
//Log without details;
}
}
class ClassA
{
void Method1()
{
try
{
//Code
}
catch (Exception ex)
{
//Log with details
throw;
}
}
}
This code achieves the same functionality but leaves the return code of the functions for something useful and non exceptional.
More generally, I suggest that you should have one catch all handler at the top level of your application that deals with logging, or at most one per public entry point. Other handlers should deal with specific exception types that they can actually "handle" (do something about.)
It all depends on the purpose and implementation of the code; sometimes it is better to allow exceptions to pass back to the caller - they should be used in exceptional cases.
If you do intend on using return codes, however, I would be more inclined to use enum's (though, again, it depends what the purpose of the code is). That way, it is easy for the caller to check against an available selection of return codes. Also, a comment on using integers or strings as error codes - it may not be very descriptive for a caller to know what the issue was. In this case, throwing an Exception or a specific type (containing the error message), or returning a pre-defined enum with a descriptive name, would be more meaningful to the caller.
From these short code snippets which does nothing it is very difficult to say what is best practice.
In general it is best to push exceptions to where they are handled best. If you are writing a framework for interfacing with some webservice the users of your framework will most likely not care about network exceptions etc. - they want return codes or, even better some framework specific exceptions that you include/code.
Hm - in your situation I'd rather do the following, but it really depends on the situation:
public string Method1()
{
string status = "0";
//Code - Exception may be thrown
return "0";
}
string status = "0";
ClassA ObjA = new ClassA();
try
{
status = objA.Method1();
}
Catch(Exception Ex)
{
//Log Exception EX
status = "-1;
}
EDIT
Sometimes it's hard to define values that indicate whether an error occurred in the method. You should keep Nullable types in mind. If you can find a suitable return value that indicates errors, it may also be ok to log the error within the method that caused the error and just react to the return value as you suggested.
By the way: In your code you're calling Method1 twice if the first call succeeded. I guess that is because it is a quick sample...
class MyException : Exception
{
public readonly int status;
public MyException(int status, string msg):base(msg)
{
this.status = status;
}
}
public string Method1()
{
throw new MyException(-1,"msg");
return "0";
}
SomeCode()
{
try
{
Method1();
}catch(MyException ex)
{
ex.status //here you get the status
}
}