首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >ASP.NET - LocalReport.Render() -无效的模拟令牌

ASP.NET - LocalReport.Render() -无效的模拟令牌
EN

Stack Overflow用户
提问于 2016-11-11 10:03:51
回答 1查看 742关注 0票数 2

我试图在ASP.NET MVC web应用程序中使用本地报告服务生成PDF报告。

问题是,当对Render()方法的调用在一个单独的Task中完成时,我会得到一个异常:

Microsoft.ReportingServices.ReportProcessing.ReportProcessingException:未能加载表达式宿主程序集。详细信息:模拟令牌无效-它不能被复制。

如果对Render()的调用在同一个线程中被用户请求(通过控制器->类库)命中,则不会引发异常。

我现在没有选择了。到目前为止我尝试过的事情:

我尝试过将任务包装在一个using块中。

代码语言:javascript
复制
// Doesn't work even with (true) or ()
IntPtr currentUser = WindowsIdentity.GetCurrent(false).Token;
Task.Run(() =>
{
    using (WindowsIdentity.Impersonate(currentUser))
    {
        ProcessStart();
    }
});

public static void ProcessStart()
{
    LocalReport localReport = new LocalReport();

    ...
    getting data for the report
    ...

    // this statement throws the exception
    byte[] pdfStream = localReport.Render(formatString,
                       deviceInfo,
                       out mimetype,
                       out encoding,
                       out fileNameExtension,
                       out streams,
                       out warnings);

    ...
    saving bytestream to file
    ...
}

我检查了这个职位,但我看不出这对我有什么帮助,因为我目前只是在本地主机上调试。

我检查了这个答案,但是它建议删除该任务,并在同一个线程中执行报告,这是我做不到的。

提前谢谢你的时间。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-06-29 17:05:18

在我使用工作解决方案的过程中,我首先开始修改alwaysFlowImpersonationPolicy配置标志,它似乎存在以处理ASP.NET请求生命周期中线程之间传递模拟令牌的问题,有一些有用的文件,但它是死胡同。

这里的问题是身份问题,以及LocalReport.Render使用沙箱应用程序域编译和执行表达式的事实。

如果我们能够阻止报表引擎创建沙箱应用程序域,那么它的代码将在与调用代码相同的域中和执行上下文中执行,从而避免引发内部异常的附加令牌传播。检查文档中的LocalReport类会发现ExecuteReportInCurrentAppDomain方法,并承诺这样做:

代码语言:javascript
复制
public static void ProcessStart()
{
    var localReport = new LocalReport();

    /* ...
     * getting data for the report
     * ... */

    /* prepare to do all rendering in the same appdomain */
    localReport.ExecuteReportInCurrentAppDomain(Assembly.GetExecutingAssembly().Evidence);
    /* now this fails no more */
    byte[] pdfStream = localReport.Render(
        formatString,
        deviceInfo,
        out mimetype,
        out encoding,
        out fileNameExtension,
        out streams,
        out warnings
    );

    /* ...
     * saving bytestream to file 
     * ... */
}

我测试过了,它真的能用!但是也有一个缺点:在.NET 4.0和更高版本中,这个方法已经被废弃了。有必要添加两个遗留配置开关以使其工作:

代码语言:javascript
复制
<configuration>
    <system.web>
        <trust legacyCasModel="true" />
    </system.web>
    <runtime>
         <legacyCasPolicy enabled="true" />    
         <NetFx40_LegacySecurityPolicy enabled="true"/>
    </runtime>
</configuration>

如果没有添加这些内容,调用ExecuteReportInCurrentAppDomain将引发异常。我现在正在生产中使用这段代码;我知道在.NET的未来版本中,这可能会中断--也许在此之前,报告引擎也会得到改进。当然,不建议添加这些遗留的CAS支持内容,它可能会对应用程序的其他部分产生影响,例如,它将阻止运行时使用来自GAC的NGEN映像。

尝试在任务上下文中放置请求标识与标志文件中的Aspnet.config一样毫无意义。

总的来说,这种方法还有许多其他问题,例如,没有阻止主机进程终止工作线程和后台任务的机制。因此和其他地方上的其他几篇文章处理了这些额外的复杂问题,无论如何,最健壮的解决方案仍然是让服务流程独立于IIS运行,并使用消息队列、命名管道或诸如此类的方式为其分配后台任务。从.NET框架版本4.5.2开始,您可以使用HostingEnvironment.QueueBackgroundWorkItem

既然有这么多反对的建议,我们为什么还要继续这样做呢?海事组织只有一个很好的理由:每当我们要求尽快返回时,我们都不在乎结果是否被丢弃。我不知道OP的用户故事,但我允许这样做:我们在页面导航上触发来自SCORM电子学习包的请求,我们需要避免这里的任何延迟。如果用户在使用异步交付的报表之前导航,工作线程也可以提前终止任务。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/40545540

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档