An unhandled exception of type 'System.StackOverflowException' using AutoMapper with many to one Related Entities

2

After fixing this error: AutoMapper throws Missing Map when Map exists I received the error:

Cannot evaluate expression because the current thread is in a stack overflow state. Here is where I initially get the error (As you can see, it's the same line as the first error):

enter image description here

UPDATED: When I add the ignore statement to my CreateMap<>(); declaration:

CreateMap<Pages, PagesViewModel>()
            .ForMember(m => m.PageTypes, x => x.Ignore())
            .ForMember(m => m.SiteMap, x => x.Ignore())
            .ForMember(m => m.Row, x => x.Ignore())
            .ForMember(m => m.Tracks, x => x.Ignore());

I received this message: System.Reflection.TargetParameterCountException: Parameter count mismatch. So i removed the Ignore statement and the CreateMaps are as follow:

CreateMap<Pages, PagesViewModel>();

CreateMap<PagesViewModel, Pages>();

the error does one of the following (all three have happened and hard to reproduce a specific one):

  1. The first one is the application just keeps running and eventually times out.
  2. The program '[5256] iisexpress.exe' has exited with code -2147023895 (0x800703e9).
  3. moves on to another part of the code (my PagesViewModel)

(UPDATED):

private string PagesURL;
[Required]
[Display(Name = "Page URL")]
[DataType(DataType.Url)]
[StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long and no longer than {1} characters.", MinimumLength = 2)]
public string pagesURL
{
    get { return PagesURL; }
    set { PagesURL = HttpUtility.UrlEncode(value); }
}

When this third one comes up, I get the same error: Cannot evaluate expression because the current thread is in a stack overflow state.

I have tried separating out the code to see where and why it's doing this by trying the following:

List<Pages> getPages = db.Pages.ToList();
List<Pages> getPagesOrdered = getPages.OrderBy(o => o.pageOrder).ToList();
List<PagesViewModel> convertPages = new List<PagesViewModel>();
foreach (Pages item in getPages)
{
    PagesViewModel pagesViewModel = new PagesViewModel();

    pagesViewModel.pageDescription = item.pageDescription;
    //...loops through all other properties

    convertPages.Add(pagesViewModel);
}

It gets all Pages from the database context, orders it and declared the PagesViewModel fine BUT when it goes inside the for loop, it declares the pagesViewModel variable fine and then right after it, before it even jumps to the pagesViewModel.pageDescription = item.pageDescription; line the application crashed The program '[5176] iisexpress.exe' has exited with code 0 (0x0).

MrChief, in the answer I linked at the top, suggested it is how my models connect with each other that is causing this issue. For example, PagesViewModel connects to public virtual PageTypeViewModel PageTypes { get; set; } and PageTypesViewModel connects back to PagesViewModel public ICollection<PagesViewModel> Page { get; set; }

My model requires those be connected and it works fine without auto mapper (with the exception of me trying to set each variable manually which cause the application to crash). I'm stuck and would appreciate some insight.


UPDATE:

After going here: http://www.symbolsource.org/Public/Wiki/Using a co-worker of mine was able to get us the symbols for AutoMapper so we can trace into that source code. We added a trace breakpoint to output what was actually causing the issue. Here is what it output a few hundred times:

From "Pages"."PageTypes" to "PagesViewModel"."PageTypes"

So MrChief's prediction was correct. Now how to fix this, I don't know.

This is where the PageViewModel links to the PageTypes view model: public virtual PageTypeViewModel PageTypes { get; set; } and then in PageTypesViewModel is links to PageViewModel: public ICollection<PagesViewModel> Page { get; set; }

This is how EF6 generated my model. I went about this doing model first.

I might have forgotten to include some important information so let me know if there is anything missing. Thank you in advance for the help.

c#
asp.net-mvc
viewmodel
automapper
stack-overflow
asked on Stack Overflow Sep 26, 2014 by Termato • edited May 23, 2017 by Community

4 Answers

4

I just tried with MaxDepth() method in Automapper and got resolve "StackOverflowException" Exception given by Automapper.

 CreateMap<Pages, PagesViewModel>().MaxDepth(5);

just try with above code and get avoid the exception for a while.

answered on Stack Overflow Aug 8, 2016 by dush88c
3

While I'm not entirely sure why proxy creation causes issue but here's 2 workaround that I know of which doesn't require you to turn off proxy creation/lazy loading (at least not for global scope permanently):

Option A: If you want to use projection:

// disable proxy creation just for the duration of query

_context.Configuration.ProxyCreationEnabled = false;

// do the query, map, go crazy!

// enable proxy again. or if your context goes out of scope after this call, then you can ignore re-enabling.
_context.Configuration.ProxyCreationEnabled = true;

Option B: If you are not using projection

var entity = _context.Where(...);  // or whatever query

// detach entity
_context.Entry(entity).State = EntityState.Detached;    

// then call Map

Now reading thru your updates, there might be a third option:

Option C: Fix your models

  • EF doesn't generate View Models, so you should be able to change them to remove the circular reference.
  • Ignore should work. I'd say take another hard look as to why or where you're getting that error. I haven't seen it before and I have mapped properties like that before.

It'd help if you can post your complete model, view model and database call related code. Maybe one model, view model to keep it brief.

answered on Stack Overflow Sep 27, 2014 by Mrchief
3
CreateMap<AppUser, AppUserDTO>().PreserveReferences();

This One also worked for me.

answered on Stack Overflow Jan 2, 2017 by dush88c
1

I was able to not get a stackoverflow error by doing the following:

pageDisplay newPage = new pageDisplay();
db.Configuration.ProxyCreationEnabled = false;
newPage.Pages = AutoMapper.Mapper.Map<List<PagesViewModel>>(db.Pages.ToList()).ToPagedList(page ?? 1, 20);

Which I found here: http://social.msdn.microsoft.com/Forums/en-US/abde3073-60f6-4cfb-9050-92a32fe00bcc/dynamicproxy-to-poco?forum=adodotnetentityframework

BUT as stated in the article, turning off ProxyCreation turns off lazy loading, therefore I have to load each related entity separate.

This is a hacky solution, so if anyone finds a better way around this, please let me know. I would rather get all related entities instead of having to load them later. The problem is, it creates the stack overflow with AutoMapper.

answered on Stack Overflow Sep 26, 2014 by Termato

User contributions licensed under CC BY-SA 3.0