Генерация отчетов Excel на стороне сервера Silverlight на основе запроса к базе данных - PullRequest
2 голосов
/ 11 февраля 2010

Я нахожусь в процессе создания приложения для интрасети с использованием Silverlight 3. На одной странице мне нужно создать отчет в формате Excel. Пользователи могут выбрать несколько параметров через пользовательский интерфейс и нажать кнопку «Отправить», затем Silverlight сгенерирует отчет Excel и отобразит окно, позволяющее пользователям сохранить сгенерированный отчет.

Есть ли способ реализовать это простым и понятным способом?

Ниже приведены шаги, которые я мог бы придумать, но все еще не совсем ясно, как решить эту проблему.

  1. Пользователь выбирает несколько комбинированных списков и выбирает список
  2. Пользователь нажимает кнопку отправки
  3. btnSubmit_Click (обработчик события нажатия кнопки «Отправить») вызовет вызов службы WCF «takeQueryParamsAsync»
  4. Служба WCF на стороне сервера создает динамический SQL-запрос, выполняет запрос и извлекает данные
  5. Клиент Silverlight получает уведомление о завершении выборки данных, вызывая функцию обратного вызова «takeQueryParamsAsync_Completed»

Теперь, как клиент Silverlight запрашивает генерацию отчета с сервера и как он выдаст сгенерированный отчет пользователю? Нужно ли вызывать другую службу wcf в функции обратного вызова takeQueryParamsAsync_Completed, чтобы запросить файл отчета из полученных данных? Если так, как служба wcf запомнит, что это тот же клиент, который запрашивал выборку данных из БД с этими конкретными параметрами запроса? Должен ли я поддерживать состояние между сервисом wcf и silverlight? Есть ли более простое решение?

генерирование отчетов на стороне клиента не является опцией (поскольку генерируемый файл Excel должен содержать диаграммы Excel). Это действительно так сложно? или я просто слишком усложняю себя, не зная, как это реализовать?

Любые указатели или примеры кода будут отличными. Спасибо.

Я уверен, что для этого должно быть элегантное решение.

Ответы [ 2 ]

1 голос
/ 11 февраля 2010

Если у вас есть ASP.NET, вы можете создать обработчик HTTP, который можно вызывать с помощью HTML-моста в Silverlight, который будет принимать параметры вашего отчета в строке запроса. Затем сгенерируйте отчет и отправьте его обратно клиенту.

string printUrl = string.Format("createxlsreport.ashx?param1={0}", param1);
HtmlPage.Window.Navigate(new Uri(printUrl, UriKind.Relative), "_blank", "toolbar=yes,location=no,status=no,menubar=no,resizable=yes");

Отправить файл обратно клиенту:

private void SendFileToClient(byte[] file, string fileName)
{
    HttpResponse Response = HttpContext.Current.Response;
    Response.Clear();
    Response.AddHeader("Content-Disposition", string.Format("attachment; filename={0}", fileName));
    // Add a HTTP header to the output stream that contains the 
    // content length(File Size). This lets the browser know how much data is being transfered
    Response.AddHeader("Content-Length", file.Length.ToString());
    // Set the HTTP MIME type of the output stream
    Response.ContentType = "application/vnd.ms-excel";
    // Write the data out to the client.
    Response.BinaryWrite(file);
    Response.End();
}
1 голос
/ 11 февраля 2010

Хорошо, у меня есть несколько идей по этому поводу:

Собираетесь ли вы использовать Silverlight SaveDialog для загрузки файла? Прежде всего, и я думаю, что вы это знаете, это единственный способ сохранения файлов на компьютер пользователя с помощью Silverlight 3. Если вы собираетесь использовать этот метод, вам понадобится управляемое пользователем событие для сохранения файла (т. Е. Нажатие кнопки).

Так что да, вам придется пойти на этот дополнительный вызов, но не внутри кода takeQueryParamsAsync_Completed. Что вы можете сделать, так это активировать кнопку или что-то еще, что сообщит пользователю, что отчет сгенерирован, и заставит его нажать кнопку download. Есть и другие варианты, хотя недавно я реализовал опцию загрузки, в которой использовалось перенаправление URL-адреса на URL-адрес файла на сервере, и это позволило мне обойти весь вопрос (Нет имени файла по умолчанию, не могу просто открыть файл, но имеет сначала сохранить его на жесткий диск и т. д.).

Что касается вопроса с государством. Это действительно зависит от того, где вы храните сгенерированный отчет. Вы храните его на жестком диске, в базе данных или храните в памяти? Это влияет на то, как вы можете вызвать файл. Один из простых способов сделать это - вернуть клиенту ключ, который он передает обратно на сервер в виде ключа, связывающего файл. Таким образом, вам не нужно поддерживать состояние между службой WCF и Silverlight.

EDIT Что ж, на стороне Wcf Service вам потребуется дополнительная услуга. Мой выглядит примерно как

<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 / {имя файла}», тогда ваш Uri будет выглядеть что-то вроде http://localhost/FileService.svc/GetFile/NewReport.xls

Теперь все, что вы делаете, это переходите по этому URL с помощью чего-то вроде HtmlPage.Window.Navigate(page, "_self");. Это позволит вам загрузить файл и остаться на той же странице Silverlight, что и вы.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...