好的,我对此有一些想法:
您打算使用 Silverlight SaveDialog 下载文件吗?首先,我想你知道这一点,这是使用 Silverlight 3 将文件保存到用户计算机的唯一方法。
如果您打算使用该方法,那么您需要一个用户驱动的事件来保存文件(即单击按钮)。
所以是的,您将不得不进行那个额外的调用,但不能从 takeQueryParamsAsync_Completed 代码内部进行。您可以做的是激活一个按钮或其他东西,这将通知用户报告已生成并让他们单击download 按钮。不过还有其他选项,我最近实现了一个下载选项,该选项利用 URL 重定向到服务器上的文件 URL,这使我能够解决整个问题(没有默认文件名选项,不能只打开文件,但有先将其保存到 HDD 等)。
关于状态的问题。这实际上取决于您存储生成的报告的位置。您是将其存储在硬盘驱动器中、数据库中还是保存在内存中?这会影响您如何调用文件。一种简单的方法是向客户端返回一个密钥,它作为链接到文件的密钥传递回服务器。这样您就不必维护 WCF 服务和 Silverlight 之间的状态。
编辑
那么,在 Wcf 服务方面,您将需要额外的服务。
我的看起来像
<service behaviorConfiguration="NewBehavior" name="ALMWCFHost.FileProvider.FileService">
<endpoint address="" behaviorConfiguration="NewBehavior1" binding="webHttpBinding"
bindingConfiguration="" name="File" contract="ALMWCFHost.FileProvider.IFileService" />
<host>
<baseAddresses>
<add baseAddress="http://localhost:8021/Files/" />
</baseAddresses>
</host>
</service>
您还必须创建一个新的端点行为
<endpointBehaviors>
<behavior name="NewBehavior1">
<webHttp />
</behavior></endpointBehaviors>
这将创建一个 webHttp 服务。
现在您将创建一些端点:
[OperationContract, WebGet(UriTemplate = "GetFile/{filename}")]
Stream GetFile(string filename);
[OperationContract, WebGet]
Stream GetYCFile(string date, string type, string format);
[OperationContract, WebGet(UriTemplate = "GetFiles/Files.zip?filenames={querystring}")]
Stream GetFiles(string querystring);
您通过地址传递的任何查询字符串都将被解析为变量。
然后在 silverlight 客户端我简单地创建了一个自定义 URI(在您的情况下,假设文件名为“NewReport.xls”)指向调用“GetFile/{filename}”,然后您的 Uri 将看起来类似http://localhost/FileService.svc/GetFile/NewReport.xls
现在您只需使用HtmlPage.Window.Navigate(page, "_self"); 之类的内容导航到该 URL。这将允许您下载该文件,并且仍然停留在与您相同的 Silverlight 页面上。