C# – Best Practices for Integrating AutoMapper with WCF Data Services and EF4

automappercentity-framework-4netwcf-data-services

We are exposing a domain model via WCF Data Services. The model originates from EF4, and requires some additional work to get it into the required form for being published via the web-service.

I'd like to handle this outside of EF4, to keep our EDMX focused on the model rather than it's usage. My idea is to create a customized "ServiceModel" which is specifically for the web-service and contains the service-specific concerns.

My question is in how to best wire-up automapper in the middle of WCF Data Services. I'm using WCF Data Services with a custom (reflection-based) provider for the ServiceModels. Where can I convert the OData query (for ServiceModels) into an EF4 query (for DomainModels), and map the results back to ServiceModels?

Best Answer

I use Automapper in my WCF Services to map from database entities to data contracts. For each service I create a static AutomapBootstrap class with a method to InitializeMap. Then for each service, I decorate the service with an AutomapServiceBehavior attribute.

I do not know if this will work for your scenario because WCF Data Services is a little different from vanilla WCF SOAP services and services using WCF WebBindings.

However, its worth a look.

This is the Service Behavior

[CoverageExclude(Reason.Framework)]
public sealed class AutomapServiceBehavior : Attribute, IServiceBehavior
{
    public AutomapServiceBehavior()
    {
    }

    #region IServiceBehavior Members

    public void AddBindingParameters(ServiceDescription serviceDescription, ServiceHostBase serviceHostBase, 
        Collection<ServiceEndpoint> endpoints, BindingParameterCollection bindingParameters)
    {
        AutomapBootstrap.InitializeMap();
    }

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

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

    #endregion
}

This is my mapper

public class AutomapBootstrap
{
    public static void InitializeMap()
    {
        Mapper.CreateMap<CreateBookmarkRequest, TagsToSaveRequest>()
            .ForMember(dest => dest.TagsToSave, opt => opt.MapFrom(src => src.BookmarkTags))
            .ForMember(dest => dest.SystemObjectId, opt => opt.UseValue((int)SystemObjectType.Bookmark))
            .ForMember(dest => dest.SystemObjectRecordId, opt => opt.Ignore());

    }
}

this is how I wire up my service to automap

[AutomapServiceBehavior]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
public class Clouds : ICloudService
{ 
    // service operation implementation details elided
}

Final note, my service is a vanilla WCF Service using the WebBinding and serving up data in a REST style fashion.

Related Topic