使用掠影和邮政时抛出异常(Exception thrown when using Glimpse a

2019-10-19 05:23发布

我刚开始使用掠影我MVC5项目,并已运行到一个问题,当我用邮政发送一封电子邮件,而无需禁用一瞥。 我已经能够与两个包范围缩小到一个问题 - 如果一瞥的cookie尚未开启它不会发生。

在提琴手,我查了两者之间的区别。 当它抛出异常,该cookie是

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)

我创建了一个快速的行动,以测试它。 控制器的代码是:

public void TestEmailExt()
    {
    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();
    }

Answer 1:

失败的原因是因为邮政库创建自己HttpContext而呈现的电子邮件视图作为反编译的实例CreateControllerContext方法内邮政的EmailViewRenderer类所示:

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());
}

这意味着,一瞥确实在设定BeginRequest完全去除,而挂钩仍然存在,拦截MVC相关的调用。

我们已经有一个类似的问题 ,我给了一个类似的反应 ,为什么这是行不通的。

更新:

我上面说了类似的问题,先前已经报道提及,但是当我试图找到一个更合适的解决方案,它似乎是这种情况下,在这方面是略有不同的是,其他类似的问题,实际执行,导致刚创建的上下文控制器在NullReferenceException中管窥特定的代码,而在这里我们得到NullReferenceException内MVC特定的代码,虽然通过一瞥触发。

System.ArgumentNullException:值不能为空。

参数名:controllerContext
在System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)

而我们这里得到的异常是由于ControllerContext对房地产StubController实例(创建内嵌)为空,执行控制器(这是不是这里的情况)时,这通常被设置。

所以,我提出以下解决方法仍然适用,但可避免,如果的代码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;
}

我所创建的一个问题这个邮政问题跟踪器

END OF UPDATE

我认为最好的办法,就目前而言,是一边打电话到邮政禁用一瞥,之后再次恢复正常一瞥行为。 因为它似乎是请求处理逻辑的特定部分期间禁止一瞥似乎并没有是少见,但是现在下面的代码片段,我们可能包括这一个或其他方式进入掠影核心库在即将到来的版本之一可以帮助你(小心它利用它不能保证在有即将发布的版本掠影内部键)

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();
    }
}


文章来源: Exception thrown when using Glimpse and Postal