使用掠影和邮政时抛出异常 [英] Exception thrown when using Glimpse and Postal

查看:244
本文介绍了使用掠影和邮政时抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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

  glimpsePolicy =开

在它的工作(一瞥是关闭)有两种饼干

  glimpseId = FBAR; glimpsePolicy =

我得到的例外是

  System.ArgumentNullException:值不能为空。
参数名:controllerContext
   在System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)
   在Castle.Proxies.Invocations.ValueProviderFactory_GetValueProvider.InvokeMethodOnTarget()
   在Castle.DynamicProxy.AbstractInvocation.Proceed()
   在Glimpse.Core.Extensibility.ExecutionTimer.Time(动作动作)
   在Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext上下文)
   在Castle.DynamicProxy.AbstractInvocation.Proceed()
   在Castle.Proxies.ValueProviderFactoryProxy.GetValueProvider(ControllerContext controllerContext)
   在System.Web.Mvc.ValueProviderFactoryCollection.GetValueProvider(ControllerContext controllerContext)
   在System.Web.Mvc.ControllerBase.get_ValueProvider()
   在Glimpse.Mvc.Message.ActionMessageExtension.AsActionMessage [T](T消息,ControllerBase控制器)
   在Glimpse.Mvc.AlternateType.ViewEngine.FindViews.PostImplementation(IAlternateMethodContext背景下,TimerResult timerResult)
   在Glimpse.Core.Extensibility.AlternateMethod.NewImplementation(IAlternateMethodContext上下文)
   在Castle.DynamicProxy.AbstractInvocation.Proceed()
   在Castle.Proxies.IViewEngineProxy.FindView(ControllerContext controllerContext,字符串的viewName,字符串masterName,布尔useCache将)
   在System.Web.Mvc.ViewEngineCollection<方式>&c__DisplayClass6 LT; FindView> b__4(IViewEngine E)
   在System.Web.Mvc.ViewEngineCollection.Find(Func`2查找,布尔trackSearchedPaths)
   在System.Web.Mvc.ViewEngineCollection.Find(Func`2 cacheLocator,Func`2定位器)
   在Postal.EmailViewRenderer.Render(电子邮件电子邮件,字符串的viewName)
   在Postal.EmailService.Send(邮箱电子邮件)
   在System.Dynamic.UpdateDelegates.UpdateAndExecuteVoid1 [T0](调用点现场,T0为arg0)
   在System.Web.Mvc.ActionMethodDispatcher.<>c__DisplayClass1.<WrapVoidAction>b__0(ControllerBase控制器,对象[]参数)
   在System.Web.Mvc.ReflectedActionDescriptor.Execute(ControllerContext controllerContext,IDictionary`2参数)
   在System.Web.Mvc.ControllerActionInvoker.InvokeActionMethod(ControllerContext controllerContext,ActionDescriptor actionDescriptor,IDictionary`2参数)
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.<BeginInvokeSynchronousActionMethod>b__36(IAsyncResult asyncResult,ActionInvocation innerInvokeState)
   在System.Web.Mvc.Async.AsyncResultWrapper.WrappedAsyncResult`2.CallEndDelegate(IAsyncResult的asyncResult)
   在Castle.Proxies.Invocations.AsyncControllerActionInvoker_EndInvokeActionMethod.InvokeMethodOnTarget()
   在Castle.DynamicProxy.AbstractInvocation.Proceed()
   在Glimpse.Mvc.AlternateType.AsyncActionInvoker.EndInvokeActionMethod.NewImplementation(IAlternateMethodContext上下文)
   在Castle.DynamicProxy.AbstractInvocation.Proceed()
   在Castle.Proxies.AsyncControllerActionInvokerProxy.EndInvokeActionMethod(IAsyncResult的asyncResult)
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3c()
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.AsyncInvocationWithFilters.<>c__DisplayClass45.<InvokeActionMethodFilterAsynchronouslyRecursive>b__3e()
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass30.<BeginInvokeActionMethodWithFilters>b__2f(IAsyncResult asyncResult)
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<>c__DisplayClass28.<BeginInvokeAction>b__19()
   在System.Web.Mvc.Async.AsyncControllerActionInvoker.<>c__DisplayClass1e.<BeginInvokeAction>b__1b(IAsyncResult asyncResult)

我创建了一个快速的行动来测试它。控制器code是:

 公共无效TestEmailExt()
    {
    VAR confirmationToken =ConfirmationToken;
    VAR电话1 =**********;
    动态电子邮件=新的电子邮件(RegEmail);
    email.To =**@gmail.com;
    email.UserName =用户名;
    email.ConfirmationToken = confirmationToken;
    email.Phone = Extensions.Right(电话1,4);
    如果(email.To.Contains(@ mydomain的))
        email.From = INTERNAL_EMAIL_FROM;
    其他
        email.From = EXTERNAL_EMAIL_FROM;
    email.Send();
    }


解决方案

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

 私人ControllerContext CreateControllerContext()
{
  HttpContextWrapper httpContextWrapper =新HttpContextWrapper(新HttpContext的(新的Htt prequest(,this.UrlRoot(),),新的Htt presponse(TextWriter.Null)));
  的RouteData的RouteData =新的RouteData();
  routeData.Values​​ [控制器] =(目标)this.EmailViewDirectoryName;
  返回新ControllerContext(新的RequestContext((HttpContextBase)httpContextWrapper,的RouteData),(ControllerBase)新EmailViewRenderer.StubController());
}

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

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

更新:

我上面说了类似的问题已经报previously提及,但同时,我试图找到一个更合适的解决方案,它似乎是这种情况下是在这方面略有不同,其他类似的问题,实际执行控制器与新创建的背景下产生了的NullReferenceException 中管窥特定code,而在这里我们得到了一个的NullReferenceException 内MVC具体code,尽管通过一瞥触发。


  

    

System.ArgumentNullException:值不能为空


    
    

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


  

和我们在这里得到的异常是因为在 StubController 实例(创建内嵌)的 ControllerContext 属性为null时,执行控制器(这不是这里的情况)时,这通常被设置

所以,我提出以下仍然适用,但可避免的解决办法,如果的code中的 CreateControllerContext()上面略作修改:

 私人ControllerContext CreateControllerContext()
{
  HttpContextWrapper httpContextWrapper =新HttpContextWrapper(新HttpContext的(新的Htt prequest(,this.UrlRoot(),),新的Htt presponse(TextWriter.Null)));
  的RouteData的RouteData =新的RouteData();
  routeData.Values​​ [控制器] =(目标)this.EmailViewDirectoryName;
  //改进
  VAR stubController =新EmailViewRenderer.StubController();
  VAR controllerContext =新ControllerContext(新的RequestContext(httpContextWrapper,的RouteData),stubController);
  stubController.ControllerContext = controllerContext;
  返回controllerContext;
}

我在邮政问题跟踪

UPDATE OF END

我认为最好的解决方案,现在,是禁用窥,同时调用到邮政,之后再次恢复正常一瞥行为。因为它似乎请求处理逻辑的特定部分中禁用窥似乎并没有是少见,但是现在下面的代码片段,我们可能包括这样一种方式或其他进入掠影核心库在即将到来的版本之一可以帮助你(小心它利用它不能保证有在即将发布的一个掠影内部键)

 公共类GlimpseSup pressionScope:IDisposable接口
{
    私人常量字符串GlimpseRequestRuntimePermissionsKey =__GlimpseRequestRuntimePermissions;
    私人只读的HttpContext currentHttpContext;
    私人只读RuntimePolicy? currentRuntimePolicy;
    私人BOOL处置;    公共GlimpseSup pressionScope(HttpContext的currentHttpContext)
    {
        如果(currentHttpContext == NULL)
        {
            抛出新的ArgumentNullException(currentHttpContext);
        }        this.currentHttpContext = currentHttpContext;
        this.currentRuntimePolicy = this.currentHttpContext.Items [GlimpseRequestRuntimePermissionsKey]作为RuntimePolicy ?;
        this.currentHttpContext.Items [GlimpseRequestRuntimePermissionsKey] = RuntimePolicy.Off;
    }    〜GlimpseSup pressionScope()
    {
        this.Dispose(假);
    }    公共无效的Dispose()
    {
        this.Dispose(真);
        GC.Sup pressFinalize(本);
    }    私人无效的Dispose(BOOL处置)
    {
        如果(!this.disposed)
        {
            如果(处置)
            {
                如果(this.currentHttpContext!= NULL)
                {
                    this.currentHttpContext.Items.Remove(GlimpseRequestRuntimePermissionsKey);
                    如果(this.currentRuntimePolicy.HasValue)
                    {
                        this.currentHttpContext.Items [GlimpseRequestRuntimePermissionsKey] = this.currentRuntimePolicy.Value;
                    }
                }
            }            this.disposed = TRUE;
        }
    }
}

然后你就可以在你的控制器操作方法使用,如下所示:

 公共无效TestEmailExt()
{
    使用(新GlimpseSup pressionScope(System.Web.HttpContext.Current))
    {
        VAR confirmationToken =ConfirmationToken;
        VAR电话1 =**********;
        动态电子邮件=新的电子邮件(RegEmail);
        email.To =**@gmail.com;
        email.UserName =用户名;
        email.ConfirmationToken = confirmationToken;
        email.Phone = Extensions.Right(电话1,4);
        如果(email.To.Contains(@ mydomain的))
            email.From = INTERNAL_EMAIL_FROM;
        其他
            email.From = EXTERNAL_EMAIL_FROM;
        email.Send();
    }
}

I'm just starting to use Glimpse with my MVC5 project and have run into an issue when I use Postal to send an email without disabling Glimpse. I've been able to narrow it down to an issue with both packages - it doesn't occur if the Glimpse cookie has not been turned on.

In Fiddler, I checked the difference between the two. When it threw the exception, the cookie was

glimpsePolicy=On

when it worked (Glimpse was off) there were two cookies

glimpseId=FBar; glimpsePolicy=

The exception I get is

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)

I created a quick action to test it. The controller code is:

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

解决方案

The reason this fails is because the Postal library creates its own HttpContext instance while rendering the email view as the decompiled CreateControllerContext method inside Postal's EmailViewRenderer class shows:

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

This means that the setup that Glimpse does at BeginRequest is completely removed, while the hooks are still in place to intercept MVC related calls.

We've had a similar issue where I gave a similar response to why this is not working.

UPDATE :

I mentioned above that a similar issue had been reported previously, but while I was trying to find a more appropriate solution, it seemed that this case is slightly different in that respect that the other similar issue actually executes a controller with the freshly created context resulting in a NullReferenceException in Glimpse specific code, while here we get a NullReferenceException inside MVC specific code, albeit triggered by Glimpse.

System.ArgumentNullException: Value cannot be null.

Parameter name: controllerContext
at System.Web.Mvc.ChildActionValueProviderFactory.GetValueProvider(ControllerContext controllerContext)

And the exception we get here is because the ControllerContext property on the StubController instance (created inline) is null, which would normally be set when executing the controller (which is not the case here).

So the workaround that I proposed below still applies, but can be avoided if the code of the CreateControllerContext() above is slightly modified:

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

I've created an issue for this on the Postal issue tracker

END OF UPDATE

I think the best solution, for now, is to disable Glimpse while calling into Postal and restore normal Glimpse behavior back again afterwards. We might include this one way or the other into the Glimpse Core library in one of the upcoming releases as it seems that disabling Glimpse during a specific part of the request processing logic doesn't seem to be that uncommon, but for now the following snippet might help you (beware it makes use of a Glimpse internal key which is not guaranteed to be there in an upcoming release)

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

which you can then use in your controller action method as shown below:

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

这篇关于使用掠影和邮政时抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆