سؤال

Note: I have also asked this question on the AutoMapper mailing list

My MVC application essentially has two levels of mapping (simplified for this question):

RepositoryObject <-> Entity <-> ViewModel

We have created two profiles, each handling the configuration for the appropriate mapping level.

The "RepositoryObjects" are eventually serialised to XML and used in REST web services. The problem we found was that an empty collection in the RepositoryObject would serialise down to an empty element in the XML, and this would cause an issue as the web service is either expecting no element, or an element containing data.

We were able to resolve this using the AllowNullCollections configuration setting. This will (of course) create a null collection rather than an empty collection, which then serialises fine.

However I'm not entirely comfortable having this as a global setting as because as Jimmy has pointed out, its not really best practice. I'm happy to have it in the RepositoryObject <-> Entity mapping because the RepositoryObjects are auto-generated (so are ugly anyway) and its very low-level in the application. But I'd prefer to not "corrupt" the Entity <-> ViewModel mapping if possible.

So, is it possible to configure this setting per profile?

Thanks.

Update

I have created test code here: https://gist.github.com/4069909

Copied here for reference:

ProfileClasses.cs

namespace NullCollectionIssue
{
    using System.Collections.Generic;

    public class SourceProfileOne
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class DestProfileOne
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class SourceProfileTwo
    {
        public ICollection<string> Stuff { get; set; }
    }

    public class DestProfileTwo
    {
        public ICollection<string> Stuff { get; set; }
    }
}

AutoMapperConfigurator.cs

namespace NullCollectionIssue
{
    using AutoMapper;

    public class ProfileOne : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "ProfileOne";
            }
        }

        protected override void Configure()
        {
            AllowNullCollections = true;
            Mapper.CreateMap<SourceProfileOne, DestProfileOne>();
        }
    }

    public class ProfileTwo : Profile
    {
        public override string ProfileName
        {
            get
            {
                return "ProfileTwo";
            }
        }

        protected override void Configure()
        {
            Mapper.CreateMap<SourceProfileTwo, DestProfileTwo>();
        }
    }

    public static class AutoMapperConfigurator
    {
        public static void Configure()
        {
            Mapper.Initialize(x =>
            {
                x.AddProfile<ProfileOne>();
                x.AddProfile<ProfileTwo>();
            });
        }
    }
}

MappingTests.cs

namespace NullCollectionIssue
{
    using AutoMapper;

    using NUnit.Framework;

    [TestFixture]
    public class MappingTests
    {
        [Test]
        public void AutoMapper_Configuration_IsValid()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();
        }

        [Test]
        public void AutoMapper_ProfileOne_AllowsNullCollections()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();

            var source = new SourceProfileOne { Stuff = null };
            var dest = Mapper.Map<SourceProfileOne, DestProfileOne>(source);

            Assert.That(dest, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Null);
        }

        [Test]
        public void AutoMapper_ProfileTwo_DoesntAllowNullCollections()
        {
            AutoMapperConfigurator.Configure();
            Mapper.AssertConfigurationIsValid();

            var source = new SourceProfileTwo { Stuff = null };
            var dest = Mapper.Map<SourceProfileTwo, DestProfileTwo>(source);

            Assert.That(dest, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Not.Null);
            Assert.That(dest.Stuff, Is.Empty);
        }
    }
}

The tests AutoMapper_Configuration_IsValid and AutoMapper_ProfileTwo_DoesntAllowNullCollections pass, but the test AutoMapper_ProfileOne_AllowsNullCollections fails because dest.Stuff is not null.

هل كانت مفيدة؟

المحلول

You are getting this behaviour because you are calling the static Mapper.Map in your configure method:

protected override void Configure()
{
    Mapper.CreateMap<SourceProfileTwo, DestProfileTwo>();
}

should instead be

protected override void Configure()
{
    CreateMap<SourceProfileTwo, DestProfileTwo>();//leading Mapper. removed
}

نصائح أخرى

Looking at the source code of the initial commit of this functionality, it appears that this is a profile property - look at Profile.cs.

So, I guess, it should work per profile. I did not try it though.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top