stopcode.net

Dave Knipper Was Here

Autostart Automapper within a WCF Service Application

Chances are you know what Automapper is, but if not, here's the description from their site:

"AutoMapper is a simple little library built to solve a deceptively complex problem - getting rid of code that mapped one object to another. This type of code is rather dreary and boring to write, so why not invent a tool to do it for us?"

Well, they did invent tool.

Whenever you use the tool to map entities, it must be initialized. To initialize it, you must call code similar to this: This issue is that you don't want to call this map creator everytime you are about to perform a mapping between entities. Usually this is fairly straightforward, you just call map creator somewhere where your application starts. It's a little trickier in a WCF application. We want this only called once upon first service method call on a fresh application pool refresh. Here's how:

1. Setup your entities. You probably have them setup already, but here's an example anyway: 2. Setup your service behavior. This is where the magic takes place the initializes the automapper. 3. Setup your service. You'll see the a class decoration on the service class. This is basically how the service knows how to acheive the goal we are striving for upon construction. That's it!

Comments (2) -

  • JRB

    5/12/2016 3:05:45 AM |

    Hi Dave,

    A good explanation in three steps how to implement [AutomapServiceBehavior] on a WCF-Service. In my case it's definitively working, since it's now complaining for the fist time over automapping errors

    Thanks for this post.

  • Marcelo Oliveira

    3/23/2017 11:52:07 AM |

    Hi Dave,

    I have implemented this approach but the behavior is not called. It is simply ignored.

    What am I doing wrong ?

    A piece of my codes are below:

    Behavior:
    =======

    using System;
    using System.Collections.ObjectModel;
    using System.ServiceModel;
    using System.ServiceModel.Channels;
    using System.ServiceModel.Description;

    namespace NSC.Service.AutoMapper
    {
        public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
        {
            public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
            {
                AutomapServiceConfig.InitializeMappings();
            }

            public void ApplyDispatchBehavior(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
            }

            public void Validate(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase)
            {
            }
        }
    }

    Automapper:
    ===========

    sing System.Collections.Generic;
    using AutoMapper;
    using NSC.Service.Contracts;
    using NSC.Transport.DTOs;

    namespace NSC.Service.AutoMapper
    {
        public class AutomapServiceConfig
        {
            /// <summary>
            /// Mapeamento de classes internas do serviço com as classes que são acessadas externamente
            /// </summary>
            public static void InitializeMappings()
            {
                Mapper.Initialize(cfg =>
                {
                    cfg.CreateMap<CargaTotalPorNumeroContract, NSC_CargaTotalPorNumeroDTO>().ReverseMap();
                    cfg.CreateMap<ClienteContract, NSC_ClientesDTO>().ReverseMap();
                    cfg.CreateMap<DataSorteioContract, NSC_DataSorteioDTO>().ReverseMap();
                    cfg.CreateMap<HistoricoRequisicaoContract, NSC_HistoricoRequisicoesDTO>().ReverseMap();
                    cfg.CreateMap<LogContract, NSC_LogDTO>().ReverseMap();
                    cfg.CreateMap<ModalidadeContract, NSC_ModalidadesDTO>().ReverseMap();
                    cfg.CreateMap<PlanoContract, NSC_PlanosDTO>()
                        .ForMember(dest => dest.NSC_Clientes, opt => opt.Ignore())
                        .ForMember(dest => dest.NSC_Processos, opt => opt.Ignore());
                    cfg.CreateMap<NSC_PlanosDTO, PlanoContract>()
                        .ForMember(dest => dest.Cliente, opt => opt.Ignore())
                        .ForMember(dest => dest.Processo, opt => opt.Ignore());
                    cfg.CreateMap<ProcessoContract, NSC_ProcessosDTO>()
                        .ForMember(dest => dest.NSC_TipoStatusProcesso, opt => opt.Ignore())
                        .ForMember(dest => dest.NSC_Modalidades, opt => opt.Ignore());
                    cfg.CreateMap<NSC_ProcessosDTO, ProcessoContract>()
                        .ForMember(dest => dest.TipoStatusProcesso, opt => opt.Ignore())
                        .ForMember(dest => dest.Modalidade, opt => opt.Ignore());
                    cfg.CreateMap<ProcessoMultiplicadorContract, NSC_ProcessosMultiplicadoresDTO>()
                        .ForMember(dest => dest.NSC_Processos, opt => opt.Ignore());
                    cfg.CreateMap<NSC_ProcessosMultiplicadoresDTO, ProcessoMultiplicadorContract>()
                        .ForMember(dest => dest.Processo, opt => opt.Ignore());
                    cfg.CreateMap<ProcessoParamSorteioContract, NSC_ProcessosParamSorteioDTO>()
                        .ForMember(dest => dest.NSC_DataSorteio, opt => opt.Ignore())
                        .ForMember(dest => dest.NSC_Processos, opt => opt.Ignore())
                        .ForMember(dest => dest.NSC_TipoApuracaoSorteio, opt => opt.Ignore())
                        .ForMember(dest => dest.NSC_TipoSorteio, opt => opt.Ignore());
                    cfg.CreateMap<NSC_ProcessosParamSorteioDTO, ProcessoParamSorteioContract>()
                        .ForMember(dest => dest.DataSorteio, opt => opt.Ignore())
                        .ForMember(dest => dest.Processo, opt => opt.Ignore())
                        .ForMember(dest => dest.TipoApuracaoSorteio, opt => opt.Ignore())
                        .ForMember(dest => dest.TipoSorteio, opt => opt.Ignore());
                    cfg.CreateMap<ProcessoProvisaoContract, NSC_ProcessosProvisoesDTO>()
                        .ForMember(dest => dest.NSC_Processos, opt => opt.Ignore());
                    cfg.CreateMap<NSC_ProcessosProvisoesDTO, ProcessoProvisaoContract>()
                        .ForMember(dest => dest.Processo, opt => opt.Ignore());
                    cfg.CreateMap<SerieDistribuicaoContract, NSC_SerieDistribuicoesDTO>()
                        .ForMember(dest => dest.NSC_Planos, opt => opt.Ignore());
                    cfg.CreateMap<NSC_SerieDistribuicoesDTO, SerieDistribuicaoContract>()
                        .ForMember(dest => dest.Plano, opt => opt.Ignore());
                    cfg.CreateMap<SerieContract, NSC_SeriesDTO>()
                        .ForMember(dest => dest.NSC_SerieDistribuicoes, opt => opt.Ignore());
                    cfg.CreateMap<NSC_SeriesDTO, SerieContract>()
                        .ForMember(dest => dest.SerieDistribuicao, opt => opt.Ignore());
                    cfg.CreateMap<TipoApuracaoSorteioContract, NSC_TipoApuracaoSorteioDTO>().ReverseMap();
                    cfg.CreateMap<TipoSorteioContract, NSC_TipoSorteioDTO>().ReverseMap();
                    cfg.CreateMap<TipoStatusProcessoContract, NSC_TipoStatusProcessoDTO>().ReverseMap();
                    cfg.CreateMap<TituloContract, NSC_TitulosDTO>()
                        .ForMember(dest => dest.NSC_Series, opt => opt.Ignore());
                    cfg.CreateMap<NSC_TitulosDTO, TituloContract>()
                        .ForMember(dest => dest.Serie, opt => opt.Ignore());

                    cfg.CreateMap<ICollection<CargaTotalPorNumeroContract>, IList<NSC_CargaTotalPorNumeroDTO>>();
                    cfg.CreateMap<ICollection<ClienteContract>, IList<NSC_ClientesDTO>>();
                    cfg.CreateMap<ICollection<DataSorteioContract>, IList<NSC_DataSorteioDTO>>();
                    cfg.CreateMap<ICollection<HistoricoRequisicaoContract>, IList<NSC_HistoricoRequisicoesDTO>>();
                    cfg.CreateMap<ICollection<LogContract>, IList<NSC_LogDTO>>();
                    cfg.CreateMap<ICollection<ModalidadeContract>, IList<NSC_ModalidadesDTO>>();
                    cfg.CreateMap<ICollection<PlanoContract>, IList<NSC_PlanosDTO>>();
                    cfg.CreateMap<ICollection<ProcessoContract>, IList<NSC_ProcessosDTO>>();
                    cfg.CreateMap<ICollection<ProcessoMultiplicadorContract>, IList<NSC_ProcessosMultiplicadoresDTO>>();
                    cfg.CreateMap<ICollection<ProcessoParamSorteioContract>, IList<NSC_ProcessosParamSorteioDTO>>();
                    cfg.CreateMap<ICollection<ProcessoProvisaoContract>, IList<NSC_ProcessosProvisoesDTO>>();
                    cfg.CreateMap<ICollection<SerieDistribuicaoContract>, IList<NSC_SerieDistribuicoesDTO>>();
                    cfg.CreateMap<ICollection<SerieContract>, IList<NSC_SeriesDTO>>();
                    cfg.CreateMap<ICollection<TipoApuracaoSorteioContract>, IList<NSC_TipoApuracaoSorteioDTO>>();
                    cfg.CreateMap<ICollection<TipoSorteioContract>, IList<NSC_TipoSorteioDTO>>();
                    cfg.CreateMap<ICollection<TipoStatusProcessoContract>, IList<NSC_TipoStatusProcessoDTO>>();
                    cfg.CreateMap<ICollection<TituloContract>, IList<NSC_TitulosDTO>>();

                    cfg.CreateMap<IList<NSC_CargaTotalPorNumeroDTO>, ICollection<CargaTotalPorNumeroContract>>();
                    cfg.CreateMap<IList<NSC_ClientesDTO>, ICollection<ClienteContract>>();
                    cfg.CreateMap<IList<NSC_DataSorteioDTO>, ICollection<DataSorteioContract>>();
                    cfg.CreateMap<IList<NSC_HistoricoRequisicoesDTO>, ICollection<HistoricoRequisicaoContract>>();
                    cfg.CreateMap<IList<NSC_LogDTO>, ICollection<LogContract>>();
                    cfg.CreateMap<IList<NSC_ModalidadesDTO>, ICollection<ModalidadeContract>>();
                    cfg.CreateMap<IList<NSC_PlanosDTO>, ICollection<PlanoContract>>();
                    cfg.CreateMap<IList<NSC_ProcessosDTO>, ICollection<ProcessoContract>>();
                    cfg.CreateMap<IList<NSC_ProcessosMultiplicadoresDTO>, ICollection<ProcessoMultiplicadorContract>>();
                    cfg.CreateMap<IList<NSC_ProcessosParamSorteioDTO>, ICollection<ProcessoParamSorteioContract>>();
                    cfg.CreateMap<IList<NSC_ProcessosProvisoesDTO>, ICollection<ProcessoProvisaoContract>>();
                    cfg.CreateMap<IList<NSC_SerieDistribuicoesDTO>, ICollection<SerieDistribuicaoContract>>();
                    cfg.CreateMap<IList<NSC_SeriesDTO>, ICollection<SerieContract>>();
                    cfg.CreateMap<IList<NSC_TipoApuracaoSorteioDTO>, ICollection<TipoApuracaoSorteioContract>>();
                    cfg.CreateMap<IList<NSC_TipoSorteioDTO>, ICollection<TipoSorteioContract>>();
                    cfg.CreateMap<IList<NSC_TipoStatusProcessoDTO>, ICollection<TipoStatusProcessoContract>>();
                    cfg.CreateMap<IList<NSC_TitulosDTO>, ICollection<TituloContract>>();
                });
            }
        }
    }

    One kind of Interface:
    =================

    using System.Collections.Generic;
    using System.ServiceModel;
    using NSC.Service.Contracts;
    using NSC.Service.Faults;

    namespace NSC.Service.Interfaces
    {
        [ServiceContract]
        public interface ICargaTotalPorNumeroService
        {
            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            int Add(CargaTotalPorNumeroContract ctr);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            CargaTotalPorNumeroContract GetById(int id);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            IList<CargaTotalPorNumeroContract> GetAll();

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            IList<CargaTotalPorNumeroContract> GetAllAsNoTracking();

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            IList<CargaTotalPorNumeroContract> GetTake(int numRows);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            IList<CargaTotalPorNumeroContract> GetTakeAsNoTracking(int numRows);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            bool Update(CargaTotalPorNumeroContract ctr);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            bool Remove(CargaTotalPorNumeroContract ctr);

            [OperationContract]
            [FaultContract(typeof(CargaTotalPorNumeroFault))]
            bool RemoveById(int id);
        }
    }

    One kind of Class:
    ===============
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.ServiceModel;
    using AutoMapper;
    using AutoMapper.QueryableExtensions;
    using NSC.Business.Classes;
    using NSC.Service.AutoMapper;
    using NSC.Service.Base;
    using NSC.Service.Contracts;
    using NSC.Service.Faults;
    using NSC.Service.Interfaces;
    using NSC.Transport.DTOs;

    namespace NSC.Service.Services
    {
        [AutomapServiceBehavior]
        public class CargaTotalPorNumeroService : ServiceBase, ICargaTotalPorNumeroService
        {
            private readonly CargaTotalPorNumeroBO _bo = new CargaTotalPorNumeroBO();
            private readonly string _nome = "CargarTotalPorNumeroService";

            public int Add(CargaTotalPorNumeroContract ctr)
            {
                try
                {
                    NSC_CargaTotalPorNumeroDTO dto = Mapper.Map<NSC_CargaTotalPorNumeroDTO>(ctr);

                    return _bo.Add(dto);
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " Add Exception");
                }
            }

            public CargaTotalPorNumeroContract GetById(int id)
            {
                try
                {
                    NSC_CargaTotalPorNumeroDTO dto = _bo.GetById(id);

                    return Mapper.Map<CargaTotalPorNumeroContract>(dto);
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " GetById Exception");
                }
            }

            public IList<CargaTotalPorNumeroContract> GetAll()
            {
                try
                {
                    IQueryable<NSC_CargaTotalPorNumeroDTO> listaDTO = _bo.GetAll();

                    List<CargaTotalPorNumeroContract> lista = listaDTO.ProjectTo<CargaTotalPorNumeroContract>().ToList();

                    return lista;
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " GetAll Exception");
                }
            }

            public IList<CargaTotalPorNumeroContract> GetAllAsNoTracking()
            {
                try
                {
                    IQueryable<NSC_CargaTotalPorNumeroDTO> listaDTO = _bo.GetAll();

                    List<CargaTotalPorNumeroContract> lista = listaDTO.ProjectTo<CargaTotalPorNumeroContract>().ToList();

                    return lista;
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " GetAllAsNoTracking Exception");
                }
            }

            public IList<CargaTotalPorNumeroContract> GetTake(int numRows)
            {
                try
                {
                    IQueryable<NSC_CargaTotalPorNumeroDTO> lista = _bo.GetTake(numRows);

                    List<CargaTotalPorNumeroContract> listaServico = lista.ProjectTo<CargaTotalPorNumeroContract>().ToList();

                    return listaServico;
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " GetById Exception");
                }
            }

            public IList<CargaTotalPorNumeroContract> GetTakeAsNoTracking(int numRows)
            {
                try
                {
                    IQueryable<NSC_CargaTotalPorNumeroDTO> lista = _bo.GetTakeAsNoTracking(numRows);

                    List<CargaTotalPorNumeroContract> listaServico = lista.ProjectTo<CargaTotalPorNumeroContract>().ToList();

                    return listaServico;
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " GetTakeAsNoTracking Exception");
                }
            }

            public bool Update(CargaTotalPorNumeroContract ctr)
            {
                try
                {
                    NSC_CargaTotalPorNumeroDTO dto = Mapper.Map<NSC_CargaTotalPorNumeroDTO>(ctr);

                    return _bo.Update(dto);
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " RemoveById Exception");
                }
            }

            public bool Remove(CargaTotalPorNumeroContract ctr)
            {
                try
                {
                    NSC_CargaTotalPorNumeroDTO dto = Mapper.Map<NSC_CargaTotalPorNumeroDTO>(ctr);

                    return _bo.Remove(dto);
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " Remove Exception");
                }
            }

            public bool RemoveById(int id)
            {
                try
                {
                    return _bo.RemoveById(id);
                }
                catch (Exception ex)
                {
                    log.Error(ex.Message, ex);
                    throw new FaultException<CargaTotalPorNumeroFault>(new CargaTotalPorNumeroFault(ex.Message), _nome + " RemoveById Exception");
                }
            }
        }
    }

    I suppose have made exactly as your example. But Nothing happens, and I get a "Missing Mapping error" every time I execute any method os my service that I need to make a class mapping.

    I need to make something in the app.config os my service ?

    Thanks.

Loading