Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there any way to disable AutoMapper's exception wrapping?

I have a repository that will throw an EntityNotFoundException when its GetSingle<T>(int id) method cannot find the requested entity in the database. When I use this with AutoMapper and an exception occurs, I get something like this instead:

AutoMapperMappingException: Trying to map CategoryDTO to Category... --->

AutoMapperMappingException: Trying to map System.Int32 to CategoryType... --->

AutoMapper.MappingException: Trying to map System.Int32 to CategoryType... --->

EntityNotFoundException: entity of type CategoryType with ID 5 was not found in the database

My custom exception is 4 levels down. This makes it hard to use try-catch blocks because now I have to do something like this:

try
{
    // do the mapping
}
catch (AutoMapperMappingException e)
{
    // get the inner-most exception
    while (e.InnerException != null)
    {
        e = e.InnerException;
    }

    // check to see if it's an EntityNotFoundException
    if (e.GetType() == typeof (EntityNotFoundException))
    {
        var notFound = e as EntityNotFoundException;
        // do something specific here, like inform the user
    }
    else
    {
        // do something more generic
    }

What I'd like to be able to do is just this:

try
{
    // do the mapping
}
catch (EntityNotFoundException e)
{
    // do something specific here, like inform the user
}
catch (Exception e)
{
    // do something more generic
}

Is there any way of disabling AutoMapper's exception wrapping behavior so that I get the straight-up exceptions that are being thrown?

Answer

I ended up creating a thin wrapper around AutoMapper that will catch the AutoMapperMappingException, find the inner-most exception, and throw that:

public class AutoMapperWrapper
{
    public TB Map<TA, TB>(TA source, TB destination)
    {
        // try to do the mapping
        try
        {
            return Mapper.Map(source, destination);
        }
        // catch AutoMapper's exception
        catch (Exception e)
        {
            // find the first InnerException that's not wrapped
            while (e is AutoMapperMappingException)
            {
                e = e.InnerException;
            }

            // if the inner exception is null, throw the original exception
            if (e == null)
            {
                throw;
            }
            // otherwise, throw the inner exception
            else
            {
                throw e;
            }
        }
    }
}

The downside of this method though is that sometimes the entire exception tree is useful to look at to see which property or entity mapping AutoMapper failed on, but this code will only give you the inner-most exception, which is sometimes not very helpful by itself, like InvalidCastException: "could not convert string to int", but won't tell you which property it was.

like image 382
Daniel T. Avatar asked Nov 02 '10 03:11

Daniel T.


2 Answers

I thing it would be bad design to conditionally wrap exception so I guess the only thing to do is to drill down into inner exception and find the first none automapperexception.

like image 194
VdesmedT Avatar answered Nov 15 '22 01:11

VdesmedT


I've implemented AutoMapperMappingException unwrapping in my NArms.AutoMapper library (see issue). It main purpose is to reduce code amount by providing MapTo<>() extension method which can be used instead of Mapper.Map(). You can get it via NuGet.

Obviously, source code is available at GitHub.

like image 35
Eskat0n Avatar answered Nov 15 '22 00:11

Eskat0n