views:

231

answers:

1

I am trying to use AutoMapper with web application running on IIS 7. The intended use it so map domain types defined in an external dll to view models defined in the IIS application. This works fine except when the external dll is singed. Then I get the following error:

AutoMapper.AutoMapperMappingException was unhandled by user code
  Message="Trying to map TestLibrary.Source to WebApplication1.Destination.\nUsing mapping configuration for TestLibrary.Source to WebApplication1.Destination\nException of type 'AutoMapper.AutoMapperMappingException' was thrown."
  Source="AutoMapper"
  StackTrace:
       at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
       at AutoMapper.MappingEngine.Map(Object source, Type sourceType, Type destinationType)
       at AutoMapper.MappingEngine.Map[TSource,TDestination](TSource source)
       at AutoMapper.Mapper.Map[TSource,TDestination](TSource source)
       at WebApplication1._Default.Page_Load(Object sender, EventArgs e)
       at System.Web.Util.CalliHelper.EventArgFunctionCaller(IntPtr fp, Object o, Object t, EventArgs e)
       at System.Web.Util.CalliEventHandlerDelegateProxy.Callback(Object sender, EventArgs e)
       at System.Web.UI.Control.OnLoad(EventArgs e)
       at System.Web.UI.Control.LoadRecursive()
       at System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
  InnerException: AutoMapper.AutoMapperMappingException
       Message="Trying to map TestLibrary.Source to System.Object.\nUsing mapping configuration for TestLibrary.Source to WebApplication1.Destination\nDestination property: Value\nException of type 'AutoMapper.AutoMapperMappingException' was thrown."
       Source="AutoMapper"
       StackTrace:
            at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.MapPropertyValue(ResolutionContext context, IMappingEngineRunner mapper, Object mappedObject, PropertyMap propertyMap)
            at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.Map(ResolutionContext context, IMappingEngineRunner mapper)
            at AutoMapper.Mappers.TypeMapMapper.Map(ResolutionContext context, IMappingEngineRunner mapper)
            at AutoMapper.MappingEngine.AutoMapper.IMappingEngineRunner.Map(ResolutionContext context)
       InnerException: System.Security.SecurityException
            Message="Request failed."
            Source="Anonymously Hosted DynamicMethods Assembly"
            StackTrace:
                 at lambda_method(ExecutionScope , Object )
                 at AutoMapper.Internal.PropertyGetter.GetValue(Object source)
                 at AutoMapper.Internal.MemberGetter.Resolve(ResolutionResult source)
                 at AutoMapper.PropertyMap.ResolveValue(Object input)
                 at AutoMapper.Mappers.TypeMapObjectMapperRegistry.PropertyMapMappingStrategy.MapPropertyValue(ResolutionContext context, IMappingEngineRunner mapper, Object mappedObject, PropertyMap propertyMap)
            InnerException:

Steps to Reproduce the problem:

1) Create a new web application using Visual Studio 2008 on a machine with IIS 7 installed. (We are using windows 7).

2) Download the AutoMapper.dll from http://www.codeplex.com/AutoMapper. (We are using version 0.4.x.x) and add a reference to this Dll to your web application.

3) Place the following code in the code behind for the default page:

using System;
using AutoMapper;
using TestLibrary;

namespace WebApplication1
{
    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            Mapper.CreateMap<Source, Destination>();
            Mapper.AssertConfigurationIsValid();

            var source = new Source {Value = "Automapper works!" };
            var destination = Mapper.Map<Source, Destination>(source);

            Response.Clear();
            Response.ContentType="text/plain";
            Response.Write(destination.Value);
            Response.End();
        }
    }

    public class Destination
    {
        public object Value { get; set; }
    }

4) Create a new Class Library named "TestLibrary" and rename the Class1.cs file to Source.cs and put the following code it in:

namespace TestLibrary
{
    public class Source
    {
        public object Value { get; set; }
    }
}

5) Add a reference to this library to your web application.

6) Run the solution and you should see the "Automapper works!" output.

7) To make it fail, you must do two things.
i) Configure the website to run under IIS instead of the Visual Studio development server. ii) Sign the TestLibrary assembly. After that, running the solution should produce the error reported above.

Does anyone have any idea how to get around this? We have checked and the application is running with full trust accourding the the IIS management console.

+2  A: 

So this exception comes from creating a lambda expression programmatically and then compiling it. Can you try doing the same thing, just in the Default.aspx.cs? One way to do this would be to create a lambda expression in code:

Expression> expr = () => 5;

then do:

var func = expr.Compile();

it's a line just like that that's failing for you.

If this works, I'd then next put this code in that signed assembly, and access it from the web application.

Jimmy Bogard
Sorry, that was supposed to be a comment :P
Jimmy Bogard
Jimmy, I tried the code that you suggested including invoking the compiled function and it works fine. I even put the code in a signed assembly and called that from the web application. Again, no issues. However, the automapper call still fails. MORE INTERESTINGLY, not having access to my main machine over the holidays, I did some tests on IIS 7 on a server 2008 VM that I had sitting around and automapper is working fine there. I concur that this is a CAS issue with IIS 7.
Kenneth Baltrinic
MORE INFO: I figured out by trial and error that if I put the AllowPartiallyTrustedCallers attribute on the TestLibrary assembly the problem goes away. I am not 100% satisfied with this solution because apparently other people (Including myself in Server 2008) don't need to do this to get the same code to work. So it is still not clear to me what is really going on here.
Kenneth Baltrinic
And they said IIS7 was supposed to simplify things :P. We've run several deployments, both in hosted and non-hosted scenarios, and not run into this issue. At least, not after we added that AllowPartiallyTrustedCallers attribute. I wish I could help more!
Jimmy Bogard
AllowPartiallyTrustedCallers worked for me too, thanks for the hint.
Igor Brejc
This saga continues. In upgrading the application in question to .Net Framework 4.0 from 3.5, I found that the use of the AllowPartiallyTrustedCallers attribute caused about half of our 2K+ unit tests to fail. Shawn Farkas of Microsoft explains why here: http://social.msdn.microsoft.com/Forums/en-US/netfxgeneralprerelease/thread/825ccf02-a505-40ee-ac95-44a4918c6ee5 Fortunately, in 4.0 the weird issue seems to be resolved and I no longer need the attribute.
Kenneth Baltrinic