Asp.net mvc 5 使用“窥视”和“邮寄”时引发异常
我刚开始在我的MVC5项目中使用Gliesh,当我使用Postal发送电子邮件而不禁用Gliesh时遇到了一个问题。我已经能够将它缩小到两个软件包的一个问题——如果没有打开“一瞥”cookie,就不会发生这种情况 在《小提琴手》中,我检查了两者之间的差异。当它抛出异常时,cookie是Asp.net mvc 5 使用“窥视”和“邮寄”时引发异常,asp.net-mvc-5,glimpse,postal,Asp.net Mvc 5,Glimpse,Postal,我刚开始在我的MVC5项目中使用Gliesh,当我使用Postal发送电子邮件而不禁用Gliesh时遇到了一个问题。我已经能够将它缩小到两个软件包的一个问题——如果没有打开“一瞥”cookie,就不会发生这种情况 在《小提琴手》中,我检查了两者之间的差异。当它抛出异常时,cookie是 glimpsePolicy=On 当它工作时(一瞥关闭),有两块饼干 glimpseId=FBar; glimpsePolicy= 我得到的例外是 System.ArgumentNullException:
glimpsePolicy=On
当它工作时(一瞥关闭),有两块饼干
glimpseId=FBar; glimpsePolicy=
我得到的例外是
System.ArgumentNullException: Value cannot be null.
Parameter name: controllerContext
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
at Castle.Proxies.Invocations.ValueProviderFactory_GetValueProvider.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Core.Extensibility.ExecutionTimer.Time(Action action)
at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.ValueProviderFactoryProxy.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
at System.Web.Mvc.ControllerBase.get_ValueProvider()
at Glimpse.Mvc.Message.ActionMessageExtension.AsActionMessage[T](T message, ControllerBase controller)
at Glimpse.Mvc.AlternateType.ViewEngine.FindViews.PostImplementation(IAlternateMethodContext context, TimerResult timerResult)
at Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.IViewEngineProxy.FindView(ControllerContext controllerContext, String viewName, String masterName, Boolean useCache)
at System.Web.Mvc.ViewEngineCollection.<>c__DisplayClass6.<FindView>b__4(IViewEngine e)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 lookup, Boolean trackSearchedPaths)
at System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator, Func`2 locator)
at Postal.EmailViewRenderer.Render(Email email, String viewName)
at Postal.EmailService.Send(Email email)
at System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1[T0](CallSite site, T0 arg0)
at System.Web.Mvc.ActionMethodDispatcher.<>c__DisplayClass1.<WrapVoidAction>b__0(ControllerBase controller, Object[] parameters)
at System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext, IDictionary`2 parameters)
at System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext, ActionDescriptor actionDescriptor, IDictionary`2 parameters)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__36(IAsyncResult asyncResult, ActionInvocation innerInvokeState)
at System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult asyncResult)
at Castle.Proxies.Invocations.AsyncControllerActionInvoker_EndInvokeActionMethod.InvokeMethodOnTarget()
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Glimpse.Mvc.AlternateType.AsyncActionInvoker.EndInvokeActionMethod.NewImplementation(IAlternateMethodContext context)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at Castle.Proxies.AsyncControllerActionInvokerProxy.EndInvokeActionMethod(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass30.<BeginInvokeActionMethodWithFilters>b__2f(IAsyncResult asyncResult)
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<>c__DisplayClass28.<BeginInvokeAction>b__19()
at System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult)
失败的原因是,Postal库在将电子邮件视图呈现为Postal的
EmailViewRenderer
类中的反编译CreateControllerContext
方法时创建了自己的HttpContext
实例,显示:
private ControllerContext CreateControllerContext()
{
HttpContextWrapper httpContextWrapper = new HttpContextWrapper(new HttpContext(new HttpRequest("", this.UrlRoot(), ""), new HttpResponse(TextWriter.Null)));
RouteData routeData = new RouteData();
routeData.Values["controller"] = (object) this.EmailViewDirectoryName;
return new ControllerContext(new RequestContext((HttpContextBase) httpContextWrapper, routeData), (ControllerBase) new EmailViewRenderer.StubController());
}
这意味着Spile在BeginRequest
上所做的设置被完全删除,而钩子仍然在拦截MVC相关调用
我们有一个问题,我解释了为什么这不起作用
更新:
我在上文中提到,之前也曾报道过类似的问题,但在我试图找到更合适的解决方案时,在这一点上,这种情况似乎略有不同,因为另一个类似的问题实际上使用新创建的上下文执行控制器,从而在特定于一瞥的代码中产生NullReferenceException
,而在这里,我们在特定于MVC的代码中得到NullReferenceException
,尽管是由一瞥触发的
System.ArgumentNullException:值不能为null
参数名称:controllerContext位于System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext ControllerContext) 我们在这里得到的例外是因为
StubController
实例(内联创建)上的ControllerContext
属性为null,这通常在执行控制器时设置(这里不是这种情况)
因此,我在下面提出的解决方法仍然适用,但如果稍微修改上面的CreateControllerContext()
的代码,就可以避免:
private ControllerContext CreateControllerContext()
{
HttpContextWrapper httpContextWrapper = new HttpContextWrapper(new HttpContext(new HttpRequest("", this.UrlRoot(), ""), new HttpResponse(TextWriter.Null)));
RouteData routeData = new RouteData();
routeData.Values["controller"] = (object) this.EmailViewDirectoryName;
// MODIFIED
var stubController = new EmailViewRenderer.StubController();
var controllerContext = new ControllerContext(new RequestContext(httpContextWrapper, routeData), stubController);
stubController.ControllerContext = controllerContext;
return controllerContext;
}
我已经在网站上为此创建了一个问题
更新结束
我认为目前最好的解决方案是在打电话到邮局时禁用窥视功能,然后再恢复正常的窥视行为。在即将发布的某个版本中,我们可能会以这种或那种方式将其包含到Spile核心库中,因为在请求处理逻辑的特定部分禁用Spile似乎并不少见,但现在下面的代码片段可能会对您有所帮助(注意,它使用的是一瞥内部密钥,但不保证在即将发布的版本中存在该密钥)
然后可以在控制器操作方法中使用,如下所示:
public void TestEmailExt()
{
using (new GlimpseSuppressionScope(System.Web.HttpContext.Current))
{
var confirmationToken = "ConfirmationToken";
var Phone1 = "**********";
dynamic email = new Email("RegEmail");
email.To = "**@gmail.com";
email.UserName = "UserName";
email.ConfirmationToken = confirmationToken;
email.Phone = Extensions.Right(Phone1, 4);
if (email.To.Contains("@mydomain"))
email.From = INTERNAL_EMAIL_FROM;
else
email.From = EXTERNAL_EMAIL_FROM;
email.Send();
}
}
public class GlimpseSuppressionScope : IDisposable
{
private const string GlimpseRequestRuntimePermissionsKey = "__GlimpseRequestRuntimePermissions";
private readonly HttpContext currentHttpContext;
private readonly RuntimePolicy? currentRuntimePolicy;
private bool disposed;
public GlimpseSuppressionScope(HttpContext currentHttpContext)
{
if (currentHttpContext == null)
{
throw new ArgumentNullException("currentHttpContext");
}
this.currentHttpContext = currentHttpContext;
this.currentRuntimePolicy = this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] as RuntimePolicy?;
this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] = RuntimePolicy.Off;
}
~GlimpseSuppressionScope()
{
this.Dispose(false);
}
public void Dispose()
{
this.Dispose(true);
GC.SuppressFinalize(this);
}
private void Dispose(bool disposing)
{
if (!this.disposed)
{
if (disposing)
{
if (this.currentHttpContext != null)
{
this.currentHttpContext.Items.Remove(GlimpseRequestRuntimePermissionsKey);
if (this.currentRuntimePolicy.HasValue)
{
this.currentHttpContext.Items[GlimpseRequestRuntimePermissionsKey] = this.currentRuntimePolicy.Value;
}
}
}
this.disposed = true;
}
}
}
public void TestEmailExt()
{
using (new GlimpseSuppressionScope(System.Web.HttpContext.Current))
{
var confirmationToken = "ConfirmationToken";
var Phone1 = "**********";
dynamic email = new Email("RegEmail");
email.To = "**@gmail.com";
email.UserName = "UserName";
email.ConfirmationToken = confirmationToken;
email.Phone = Extensions.Right(Phone1, 4);
if (email.To.Contains("@mydomain"))
email.From = INTERNAL_EMAIL_FROM;
else
email.From = EXTERNAL_EMAIL_FROM;
email.Send();
}
}