C# ASP.NET-LocalReport.Render()-模拟的令牌无效
我正在尝试在ASP.NET MVC web应用程序中使用本地reporting services生成PDF报告 问题是,当对C# ASP.NET-LocalReport.Render()-模拟的令牌无效,c#,asp.net,asp.net-mvc,multithreading,reporting-services,C#,Asp.net,Asp.net Mvc,Multithreading,Reporting Services,我正在尝试在ASP.NET MVC web应用程序中使用本地reporting services生成PDF报告 问题是,当对Render()方法的调用在单独的任务中完成时,我得到一个异常: Microsoft.ReportingServices.ReportProcessing.ReportProcessingException: 未能加载表达式宿主程序集。详细信息:的令牌无效 模拟-它不能被复制 如果对Render()的调用被同一线程中的用户请求(通过控制器->类库)命中,则不会引发异常 我现
Render()
方法的调用在单独的任务中完成时,我得到一个异常:
Microsoft.ReportingServices.ReportProcessing.ReportProcessingException:
未能加载表达式宿主程序集。详细信息:的令牌无效
模拟-它不能被复制
如果对Render()
的调用被同一线程中的用户请求(通过控制器->类库)命中,则不会引发异常
我现在没有选择了。到目前为止我尝试过的事情:
我已尝试使用
块将任务包装到中
// 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
...
}
我检查了,但我看不出这对我有什么帮助,因为我目前正在本地主机中调试
我检查了,但它建议删除任务并在同一线程中进行报告,这是我无法做到的
提前感谢您的时间。在我去工作解决方案的路上,我首先开始修补alwaysFlowImpersonationPolicy
配置标志,该标志似乎用于处理ASP.NET请求生命周期中线程之间传递模拟令牌的问题,虽然有一些,但它是一条死胡同
这里的问题是身份,以及LocalReport.Render
使用沙盒应用程序域编译和执行表达式的事实
如果我们可以阻止报表引擎创建沙盒应用程序域,那么它的代码将在与调用代码相同的域和执行上下文中执行,从而避免引发内部异常的额外令牌传播。检查LocalReport
类的找到了ExecuteReportInCurrentAppDomain
方法,该方法承诺:
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
* ... */
}
我测试了它,它确实有效!但也有一个缺点:该方法在.NET4.0及更高版本中已被弃用。有必要添加两个传统配置开关以使其正常工作:
<configuration>
<system.web>
<trust legacyCasModel="true" />
</system.web>
<runtime>
<legacyCasPolicy enabled="true" />
<NetFx40_LegacySecurityPolicy enabled="true"/>
</runtime>
</configuration>
如果未添加这些属性,则调用executeReportUrrentAppDomain会引发异常。我现在正在生产中使用此代码;我知道,在未来的.NET版本中,这可能会中断—也许在此之前,报表引擎也会得到改进。当然,不建议添加这些旧的CAS支持内容,因为它可能会影响应用程序的其他部分,例如,它将阻止运行时使用GAC提供的NGEN映像
尝试在任务上下文中植入请求标识与在Aspnet.config文件中一样毫无意义
总的来说,这种方法还存在许多其他问题,例如,没有任何机制可以防止主机进程终止工作线程和后台任务。
其他几篇文章都在讨论这些额外的复杂问题,无论如何,最可靠的解决方案仍然是让服务进程独立于IIS运行,并使用消息队列、命名管道或类似的方式为其分配后台任务。从.NET framework 4.5.2版开始,您可以使用HostingEnvironment.QueueBackgroundWorkItem
既然有这么多反对这一点的建议,我们为什么还要坚持呢?在我看来,只有一个很好的理由:每当我们想要一个请求快速返回时,我们不在乎结果是否被丢弃。我不知道OP的用户故事,但我的允许:我们在页面导航上触发SCORM电子学习包的请求,我们需要避免任何延迟。如果用户在使用异步提交的报告之前离开,工作线程也可以提前终止任务。您是否解决了此保留任务?@San很遗憾,我记不起确切的解决方案,已经有一段时间了,同时我换了公司。如果你想让我整理一下,我可以删除这个问题。我刚才也遇到了同样的问题,并且认为在任务
代码中,标识不再是应用程序池标识,而是NT-AUTHORITY\SYSTEM
。如果我找到了解决方案,我会发布一个答案。谢谢你花时间回答这个问题!很抱歉,我不记得我是怎么做到的,很长一段时间后我就离开了.NET。我很高兴找到了一条出路。:)