Permalink
Browse files

Issue 41: fix problem with Web API running in medium trust from the GAC

Fix a bug where WebAPI would cause an error for action methods returning Task<T> when running in Medium trust from the GAC.
Instead of using Expression tree compilation, use Delegate.CreateDelegate which does not have the same access violation problem.
  • Loading branch information...
1 parent e43ac2e commit f95cdef399c6b6b0c040d1b460bd23c79a8f867d @marcind marcind committed Apr 10, 2012
Showing with 21 additions and 8 deletions.
  1. +21 −8 src/System.Web.Http/Controllers/ReflectedHttpActionDescriptor.cs
@@ -9,6 +9,7 @@
using System.Net;
using System.Net.Http;
using System.Reflection;
+using System.Runtime.CompilerServices;
using System.Threading.Tasks;
using System.Web.Http.Filters;
using System.Web.Http.Internal;
@@ -315,11 +316,22 @@ public Task<object> Execute(object instance, object[] arguments)
}
// Method called via reflection.
- private static Task<object> Convert<T>(Task<T> task)
+ private static Task<object> Convert<T>(object taskAsObject)
{
+ Task<T> task = (Task<T>)taskAsObject;
return task.Then(r => (object)r);
}
+ // Do not inline or optimize this method to avoid stack-related reflection demand issues when
+ // running from the GAC in medium trust
+ [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.NoOptimization)]
+ private static Func<object, Task<object>> CompileGenericTaskConversionDelegate(Type taskValueType)
+ {
+ Contract.Assert(taskValueType != null);
+
+ return (Func<object, Task<object>>)Delegate.CreateDelegate(typeof(Func<object, Task<object>>), _convertOfTMethod.MakeGenericMethod(taskValueType));
+ }
+
private static Func<object, object[], Task<object>> GetExecutor(MethodInfo methodInfo)
{
// Parameters to executor
@@ -377,13 +389,14 @@ private static Task<object> Convert<T>(Task<T> task)
// for: public Task<T> Action()
// constructs: return (Task<object>)Convert<T>(((Task<T>)instance).method((T0) param[0], ...))
Type taskValueType = TypeHelper.GetTaskInnerTypeOrNull(methodCall.Type);
- MethodInfo convertMethod = _convertOfTMethod.MakeGenericMethod(taskValueType);
- Expression<Func<object, object[], Task<object>>> conversionLambda =
- Expression.Lambda<Func<object, object[], Task<object>>>(
- Expression.Convert(Expression.Call(convertMethod, methodCall), typeof(Task<object>)),
- instanceParameter,
- parametersParameter);
- return conversionLambda.Compile();
+ var compiledConversion = CompileGenericTaskConversionDelegate(taskValueType);
+
+ return (instance, methodParameters) =>
+ {
+ object callResult = compiled(instance, methodParameters);
+ Task<object> convertedResult = compiledConversion(callResult);
+ return convertedResult;
+ };
}
else
{

0 comments on commit f95cdef

Please sign in to comment.