I have a piece of try catch code:
try 
{
    ...
}
catch(Exception ex) 
{
    ModelState.AddModelError(
        \"duplicateInvoiceNumberOrganisation\", \"The com         
        To get name of the exception you can use
    catch (Exception exc){
       if (exc.GetType().FullName == "Your_Exception") 
       {
          // The same can be user for InnerExceptions
          // exc.InnerException.GetType().FullName
       }
   }
                                                                        Replace System.Threading.ThreadAbortException with your exception.
try
{
    //assume ThreadAbortException occurs here
}
catch (Exception ex)
{
    if (ex.GetType().IsAssignableFrom(typeof(System.Threading.ThreadAbortException)))
    {
         //what you want to do when ThreadAbortException occurs         
    }
    else
    {
         //do when other exceptions occur
    }
}
                                                                        You can take a look at the SQLException class -- and check for the contents of the exception's message if it contains what you now see in your inner exception..Something like this:
try
{
    //your code here
}
catch (SQLException ex)
{
    if (ex.Message.Contains("Cannot insert duplicate key in obj...."))
    {
        //your code here
    }
}
                                                                        before your current catch add the following:
catch(DbUpdateException ex)
{
  if(ex.InnerException is UpdateException)
  {
    // do what you want with ex.InnerException...
  }
}
From C# 6, you can do the following:
catch(DbUpdateException ex) when (ex.InnerException is UpdateException)
{
    // do what you want with ex.InnerException...
}
                                                                        Not enough rep to comment. In response to @conterio question (in @Davide Piras answer):
is there a catch "when not" syntax?
There is.
catch (Exception e) when (!(e is ArgumentException)) { }