Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Jerode 44 posts 159 karma points
    Dec 16, 2014 @ 02:39
    Jerode
    0

    Automapper in 7 failing on backoffice

    I upgraded Umbraco from 6.1.4 to 7.2.0 and once I connected it to my logic layer I encounter an issue with Automapper.

    Received an error from the server

    Server call failed for getting current user

    Missing type map configuration or unsupported mapping. Mapping types: User -> UserDetail Umbraco.Core.Models.Membership.User -> Umbraco.Web.Models.ContentEditing.UserDetail Destination path: UserDetail Source value: Umbraco.Core.Models.Membership.User

    EXCEPTION DETAILS:
    AutoMapper.AutoMapperMappingException: Missing type map configuration or unsupported mapping. Mapping types: User -> UserDetail Umbraco.Core.Models.Membership.User -> Umbraco.Web.Models.ContentEditing.UserDetail Destination path: UserDetail Source value: Umbraco.Core.Models.Membership.User
    STACKTRACE:
    at Umbraco.Web.Editors.AuthenticationController.GetCurrentUser()
       at lambda_method(Closure , Object , Object[] )
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass13.<GetExecutor>b__c(Object instance, Object[] methodParameters)
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.<>c__DisplayClass5.<ExecuteAsync>b__4()
       at System.Threading.Tasks.TaskHelpers.RunSynchronously[TResult](Func`1 func, CancellationToken cancellationToken)

    I already register Automapper for my models and I suspect that my initialization of the mapper is short circuiting the Umbraco implementation of it.

    What needs to be done to use my own mappings in addition to the Umbraco ones?

  • Jerode 44 posts 159 karma points
    Dec 16, 2014 @ 15:27
    Jerode
    0

    I have confirmed that removing my call when initializing Automapper indeed allows the backoffice to function. Here is an example of the call:

    On application startup:

    Mapper.Initialize(x => x.AddProfile<RegisterAutoMapper>());

    This will call an Automapper class that will setup all my mappings.

    public sealed class RegisterAutoMapper : Profile
    {
        protected override void Configure()
        {
            PopulateAutoMapper();
        }
    
        private static void PopulateAutoMapper()
        {
            SocialNetwork.Map();
    
            Mapper.AssertConfigurationIsValid();
        }
    }
    

    Here is an example of the map call for SocialNetwork.

    internal static void Map()
    {
        Mapper.CreateMap<Avatar, SocialNetwork>()
            .ForMember(d => d.AvatarName, option => option.MapFrom(o => o.Name))
            .IgnoreAllNonExisting();
    
        Mapper.CreateMap<SocialNetwork, Avatar>()
            .ForMember(d => d.Name, option => option.MapFrom(o => o.AvatarName))
            .ForMember(d => d.IsActive, option => option.UseValue(true))
            .IgnoreAllNonExisting();
    }
  • Jerode 44 posts 159 karma points
    Dec 16, 2014 @ 16:35
    Jerode
    0

    It looks like Umbraco.Core.CoreBootManager is responsible initialzing the models that are required for the back office. Currently researching if I can inherit MapperConfiguration and see if Umbraco will pick them up and work correctly.

  • Jerode 44 posts 159 karma points
    Dec 16, 2014 @ 20:48
    Jerode
    100

    The issue was one of three things.

    Startup was changed to because adding a profile seemed to clash with something.

    RegisterAutoMapper.PopulateAutoMapper();

    Took away inheriting profile since I was no longer using the initialize add profile any longer. Also had to remove the following:

    Mapper.AssertConfigurationIsValid();

    The AssertConfiguartionIsValid caused issues no matter what.

    Working modifications to original post below

    public static class RegisterAutoMapper
    {
        public static void PopulateAutoMapper()
        {
            SocialNetwork.Map();
        }
    }

     

    internal static void Map()
    {
        Mapper.CreateMap()
            .ForMember(d => d.AvatarName, option => option.MapFrom(o => o.Name))
            .IgnoreAllNonExisting();
    
        Mapper.CreateMap()
            .ForMember(d => d.Name, option => option.MapFrom(o => o.AvatarName))
            .ForMember(d => d.IsActive, option => option.UseValue(true))
            .IgnoreAllNonExisting();
    }

    This no longer appears to be an issue for me.

  • Kenny Burns 173 posts 305 karma points
    Feb 09, 2015 @ 11:22
    Kenny Burns
    0

    * Bump

    Hey,

    I too am having this issue - is there a way I can use my own mappings with the Umbraco ones? Code similar to below - I have a feeling its doing something funny on ApplicationStarted. Anyone have any ideas?

    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, ApplicationContext applicationContext)        {           
    MappingConfiguration.Configure();  
    }

     

    public static class MappingConfiguration{
            public static void Configure(){
                Mapper.Initialize(m =>{
                    m.AddProfile<MyProfile>();
                });
            }
        }

    Thanks

  • Kenny Burns 173 posts 305 karma points
    Feb 09, 2015 @ 12:41
    Kenny Burns
    7

    Hey, 

    So after further investigation, we found you shouldn't use Mapper.Initialize as this bins anything that has gone before it - we went down the path of the way Umbraco set their mappings up.

    In each mapping profile, we implemented the IMapperConfiguration interface, then in the ConfigureMappings we create our map like so:

    public void ConfigureMappings(IConfiguration config, ApplicationContext applicationContext)
    {
          config.CreateMap<PaymentAttempt, AuthRequestBlock>().ConvertUsing<AuthRequestBlockTypeConverter>();   
    }

    Hope that helps someone! :)

    K

  • David Peck 687 posts 1863 karma points c-trib
    May 01, 2018 @ 13:09
    David Peck
    1

    Or MapperConfiguration if you prefer the abstract class route to the interface. That is an IMapperConfiguration anyway.

    https://github.com/umbraco/Umbraco-CMS/blob/7ee510ed386495120666a78c61497f58ff05de8f/src/Umbraco.Core/Models/Mapping/MapperConfiguration.cs

  • Dimitri Troncquo 4 posts 26 karma points
    Jul 17, 2018 @ 10:16
    Dimitri Troncquo
    0

    Running into a similar issue here.

    So just to summarize: I need to ditch all profiles, and hook up the mapping through IMapperConfigurations instead?

    That kind of sucks, because I want all my assemblies to be responsible for registering their own mappings, without them knowing anything about Umbraco. That's kind of the idea about mapping profiles in the first place, isn't it?

    Anyways, I'll figure something out.

    EDIT

    Seems like I was a bit to fast in drawing conclussions there. I was actually able to fix it pretty easily by inherriting MapperConfiguration and moving my original code to load the profiles to ConfigureMappings(IConfiguration config, ApplicationContext applicationContext).

    So that means I can still use my original Profiles and leave each assembly in charge of it's own mappings.

    On a side note

    In newer versions of AutoMapper (sadly unsupported by Umbraco 7) AutoMapper.IConfiguration has a nifty method AddProfiles(IEnumerable<Assembly> assembliesToScan), which basically loads all profiles from the assemblies you pass in. I pulled the code from the Automapper code base and added it, with some minor changes, as an extension method. Might be of use, so here it goes:

    internal static class IConfigurationExtensions
        {
            //from automapper v7 (https://github.com/AutoMapper/AutoMapper)
            public static void AddProfiles(this IConfiguration me, IEnumerable<Assembly> assembliesToScan)
            {
                var allTypes = assembliesToScan.Where(a => !a.IsDynamic).SelectMany(a => a.DefinedTypes).ToArray();
    
                var profiles =
                    allTypes
                        .Where(t => typeof(Profile).GetTypeInfo().IsAssignableFrom(t))
                        .Where(t => !t.IsAbstract)
                        .Select(t => t.AsType());
    
                foreach (var profile in profiles)
                {
                    me.AddProfile((Profile)Activator.CreateInstance(profile));
                }
            }
        }
    
Please Sign in or register to post replies

Write your reply to:

Draft