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

2

7

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.

Pilatus answered 2/11, 2010 at 3:32 Comment(4)
Can't you do the repository call first, catch your EntityNotFoundException and then, if the entity WAS found, do your mapping? Sounds like you might be trying to do too much in one step and it's causing you some pain.Beatification
That's one of the reasons why I'm using AutoMapper. What I provided was only an example. My actual entities contain a lot of relationships, sometimes 20 or more. You can imagine how much of a pain it'd be to do a check for each entity. AutoMapper is nice enough to automatically handle this for me, as long as I set up the mapping correctly.Pilatus
Any development about this topic ? I'm facing the same frustration :-)Integument
@VdesmedT: I modified my question to include what I ended up doing.Pilatus
I
1

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.

Integument answered 23/12, 2010 at 14:38 Comment(1)
I posted the solution I used at the end of my question. Basically, I created a very thin wrapper for AutoMapper that will catch the AutoMapperMappingException, find the inner-most exception, and throw that.Pilatus
A
1

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.

Asp answered 8/4, 2014 at 9:53 Comment(1)
Thank you! I found the code in here very usefulIsomorphism

© 2022 - 2024 — McMap. All rights reserved.