Создание отчета FastReport несколько источников данных, группировки
Делаю отчет в FastReport по аналогии со статьей в Академии.
https://academy.terrasoft.ru/documents/technic-sdk/7-16/primer-nastroyki-otcheta
Но мне для отчета нужны несколько источников данных и во многих несколько уровней группировки данных.
Источники данных.
{ "ProviderName": "MortgageConclusionDataProvider", "Schemas": { "MortgageConclusionData": { "GroupName": {"DataValueType": 1}, "Account": {"DataValueType": 1}, "PreparationDate": {"DataValueType": 7}, "ConclusionType": {"DataValueType": 1} }, "LevelSecurityData": { "MortgageConclusion": {"DataValueType": 0}, "SublimitTypes": {"DataValueType": 0}, "NameSublimitTypes": {"DataValueType": 1}, "Groupe": {"DataValueType": 1}, "TargetUse": {"DataValueType": 1}, "AmountLimit": {"DataValueType": 5} }, "LocalizableStrings": { "ReportTitle": {"DataValueType": 1}, ... } } }
В сервисе прописываю логику:
public Task<ReportDataDictionary> GetData(UserConnection userConnection, IReadOnlyDictionary<string, object> parameters) { var filter = ExtractFilterFromParameters(userConnection, _entitySchemaUId, parameters); var result = new ReportDataDictionary { // Заполнить колонки в отчете. ["MortgageConclusionData"] = GetMortgageConclusionData(userConnection, _entitySchemaUId, filter), ["LevelSecurityData"] = GetLevelSecurityData(userConnection, _entityLevelSecuritySchemaUId), ["LocalizableStrings"] = GetLocalizableStrings(userConnection) }; return Task.FromResult(result); }
И при формировании отчета ошибка
Error while sending request
response status: 500 (Internal Server Error)
request url: ...FastReportService/CreateReport
method: POST
request data: {"reportTemplateId":"a1c1f160-a7c2-56a0-edcb-1101dde5a74e","reportCaption":"Заключение","reportSchemaName":"MortgageConclusion","report...
Через Profiler запросы сформировались, данные есть.
Хотелось бы хоть один рабочий пример увидеть, где несколько источников и есть иерархия...
Спасибо!
Нравится
Судя по сообщению из логов, второе исключение происходит в схеме FastReportService, в функции:
[Obsolete("7.15.3")] [OperationContract] [WebGet(UriTemplate = "GetReportFile/{key}")] public Stream GetReportFile(string key) { var data = PopFromSessionData(key); string contentDisposition = "attachment; filename*=UTF-8''" + data.Key; var reportStream = new MemoryStream(data.Value); WebResponseProcessor.AssignFileResponseContent(HttpContextAccessor.GetInstance(), "application/pdf; charset=UTF-8", reportStream.Length, contentDisposition); return reportStream; } private KeyValuePair<string, byte[]> PopFromSessionData(string sessionKey) { var data = (KeyValuePair<string, byte[]>)UserConnection.SessionData[sessionKey]; UserConnection.SessionData.Remove(sessionKey); return data; }
То есть падает не внутри Вашего кода отчёта, а при попытке скачать с сервера файл отчёта, вместо него пусто. Отчёт перед этим уже должен был создаться в CreateReport, а в ней происходит первое исключение. Но в этой функции любые ошибки обрабатывает общий блок try:
[Obsolete("7.15.3")] [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] public string CreateReport(Guid reportTemplateId, string reportCaption, string reportSchemaName, string reportFilters) { try { var reportParameters = new Dictionary<string, object> { ["EsqFilters"] = new Dictionary<string, Filters> { [reportSchemaName] = JsonConvert.DeserializeObject<Filters>(reportFilters) } }; var reportBytes = InternalCreateReport(reportTemplateId, reportParameters); return PushToSessionData(new KeyValuePair<string, byte[]>($"{HttpUtility.UrlPathEncode(reportCaption)}.pdf", reportBytes)); } catch (Exception exception) { throw new WebFaultException<FastReportGenerationException>( new FastReportGenerationException(exception), HttpStatusCode.InternalServerError); } }
Получается, чтобы увидеть, где именно упало при генерации отчёта, нужно для теста убрать этот try, чтобы видеть дальнейший стек вызовов и настоящую ошибку.
А у Вас response status: 500 только на конкретном отчёте, который разрабатываете, на остальных нормально?
По поводу примеров, кроме описанного в академии, в системе есть ещё стандартные «Знаменательные события контакта» и «Полнота наполнения данными». В первом — несколько источников и схема ContactAnniversariesReportDataProvider, в ней интересующая Вас функция:
public Task<ReportDataDictionary> GetData(UserConnection userConnection, IReadOnlyDictionary<string, object> parameters) { var contactFilter = ExtractFilterFromParameters(userConnection, _contactEntitySchemaUId, parameters); var result = new ReportDataDictionary { ["Contact"] = GetContactData(userConnection, _contactEntitySchemaUId, contactFilter), ["ContactAnniversary"] = GetContactAnniversaryData(userConnection, _contactAnniversaryEntitySchemaUId, contactFilter), ["LocalizableStrings"] = GetLocalizableStrings(userConnection) }; return Task.FromResult(result); }
Но обратите внимание, выше в коде есть сами функции GetContactData и GetContactAnniversaryData, получающие из базы коллекцию данных с указанным фильтром.
Елена, ошибка 500 происходит на сервере, то есть в логах должна быть более подробная информация, где именно в коде она возникает.
Зверев Александр,
2020-08-05 18:06:11,849 [192] ERROR Terrasoft.Web.Common.ServiceModel.ErrorHandler ProvideFault - Internal Server Error System.ServiceModel.Web.WebFaultException`1[Terrasoft.Configuration.Reporting.FastReport.FastReportGenerationException]: Internal Server Error (Дополнительные сведения об ошибке — Terrasoft.Configuration.Reporting.FastReport.FastReportGenerationException: Error during report generation). 2020-08-05 18:06:11,864 [192] ERROR Terrasoft.WebApp.FileWebEventProvider RaiseInternal - Date: 05.08.2020 18:06:11 Date (UTC): 05.08.2020 15:06:11 Exception Message: Internal Server Error Exception Type: System.ServiceModel.Web.WebFaultException`1[Terrasoft.Configuration.Reporting.FastReport.FastReportGenerationException] Exception Source: Terrasoft.Configuration Exception Stack Trace: в Terrasoft.Configuration.Reporting.FastReport.FastReportService.CreateReport(Guid reportTemplateId, String reportCaption, String reportSchemaName, String reportFilters) в SyncInvokeCreateReport(Object , Object[] , Object[] ) в System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) в System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) SessionID: xxiqbf2pqlqi4uvge2vbjffb Request URL: /0/rest/FastReportService/CreateReport Request Path: /0/rest/FastReportService/CreateReport Request UrlReferrer: http://192.168.222.228:82/0/Nui/ViewModule.aspx Request Type: POST User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 User Host Address: 192.168.10.131 User: Supervisor Is Authenticated: True Authentication Type: Forms Is Secure Connection: False Application Version: 7.16.0.4449 Application Virtual Path: /0 Application Trust Level: Full Is Local: False Process ID: 3988 Process Name: w3wp.exe OS Version: Microsoft Windows NT 10.0.14393.0 Net Framework Version: 4.0.30319.42000 DBExecutor Type: MSSqlExecutor <--> 2020-08-05 18:06:11,880 [192] ERROR Terrasoft.Web.Common.ServiceModel.ErrorHandler HandleError - Internal Server Error System.ServiceModel.Web.WebFaultException`1[Terrasoft.Configuration.Reporting.FastReport.FastReportGenerationException]: Internal Server Error (Дополнительные сведения об ошибке — Terrasoft.Configuration.Reporting.FastReport.FastReportGenerationException: Error during report generation). 2020-08-05 18:06:11,974 [192] ERROR Terrasoft.Web.Common.ServiceModel.ErrorHandler ProvideFault - Ссылка на объект не указывает на экземпляр объекта. System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта. в Terrasoft.Configuration.Reporting.FastReport.FastReportService.PopFromSessionData(String sessionKey) в Terrasoft.Configuration.Reporting.FastReport.FastReportService.GetReportFile(String key) в SyncInvokeGetReportFile(Object , Object[] , Object[] ) в System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) в System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet) 2020-08-05 18:06:11,974 [192] ERROR Terrasoft.WebApp.FileWebEventProvider RaiseInternal - Date: 05.08.2020 18:06:11 Date (UTC): 05.08.2020 15:06:11 Exception Message: Ссылка на объект не указывает на экземпляр объекта. Exception Type: System.ServiceModel.FaultException`1[System.NullReferenceException] Exception Source: Exception Stack Trace: SessionID: xxiqbf2pqlqi4uvge2vbjffb Request URL: /0/rest/FastReportService/GetReportFile/undefined Request Path: /0/rest/FastReportService/GetReportFile/undefined Request Type: GET User Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36 User Host Address: 192.168.10.131 User: Supervisor Is Authenticated: True Authentication Type: Forms Is Secure Connection: False Application Version: 7.16.0.4449 Application Virtual Path: /0 Application Trust Level: Full Is Local: False Process ID: 3988 Process Name: w3wp.exe OS Version: Microsoft Windows NT 10.0.14393.0 Net Framework Version: 4.0.30319.42000 DBExecutor Type: MSSqlExecutor <--> 2020-08-05 18:06:11,989 [192] ERROR Terrasoft.Web.Common.ServiceModel.ErrorHandler HandleError - Ссылка на объект не указывает на экземпляр объекта. System.NullReferenceException: Ссылка на объект не указывает на экземпляр объекта. в Terrasoft.Configuration.Reporting.FastReport.FastReportService.PopFromSessionData(String sessionKey) в Terrasoft.Configuration.Reporting.FastReport.FastReportService.GetReportFile(String key) в SyncInvokeGetReportFile(Object , Object[] , Object[] ) в System.ServiceModel.Dispatcher.SyncMethodInvoker.Invoke(Object instance, Object[] inputs, Object[]& outputs) в System.ServiceModel.Dispatcher.DispatchOperationRuntime.InvokeBegin(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage5(MessageRpc& rpc) в System.ServiceModel.Dispatcher.ImmutableDispatchRuntime.ProcessMessage11(MessageRpc& rpc) в System.ServiceModel.Dispatcher.MessageRpc.Process(Boolean isOperationContextSet)
Судя по сообщению из логов, второе исключение происходит в схеме FastReportService, в функции:
[Obsolete("7.15.3")] [OperationContract] [WebGet(UriTemplate = "GetReportFile/{key}")] public Stream GetReportFile(string key) { var data = PopFromSessionData(key); string contentDisposition = "attachment; filename*=UTF-8''" + data.Key; var reportStream = new MemoryStream(data.Value); WebResponseProcessor.AssignFileResponseContent(HttpContextAccessor.GetInstance(), "application/pdf; charset=UTF-8", reportStream.Length, contentDisposition); return reportStream; } private KeyValuePair<string, byte[]> PopFromSessionData(string sessionKey) { var data = (KeyValuePair<string, byte[]>)UserConnection.SessionData[sessionKey]; UserConnection.SessionData.Remove(sessionKey); return data; }
То есть падает не внутри Вашего кода отчёта, а при попытке скачать с сервера файл отчёта, вместо него пусто. Отчёт перед этим уже должен был создаться в CreateReport, а в ней происходит первое исключение. Но в этой функции любые ошибки обрабатывает общий блок try:
[Obsolete("7.15.3")] [OperationContract] [WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, BodyStyle = WebMessageBodyStyle.Wrapped)] public string CreateReport(Guid reportTemplateId, string reportCaption, string reportSchemaName, string reportFilters) { try { var reportParameters = new Dictionary<string, object> { ["EsqFilters"] = new Dictionary<string, Filters> { [reportSchemaName] = JsonConvert.DeserializeObject<Filters>(reportFilters) } }; var reportBytes = InternalCreateReport(reportTemplateId, reportParameters); return PushToSessionData(new KeyValuePair<string, byte[]>($"{HttpUtility.UrlPathEncode(reportCaption)}.pdf", reportBytes)); } catch (Exception exception) { throw new WebFaultException<FastReportGenerationException>( new FastReportGenerationException(exception), HttpStatusCode.InternalServerError); } }
Получается, чтобы увидеть, где именно упало при генерации отчёта, нужно для теста убрать этот try, чтобы видеть дальнейший стек вызовов и настоящую ошибку.
А у Вас response status: 500 только на конкретном отчёте, который разрабатываете, на остальных нормально?
По поводу примеров, кроме описанного в академии, в системе есть ещё стандартные «Знаменательные события контакта» и «Полнота наполнения данными». В первом — несколько источников и схема ContactAnniversariesReportDataProvider, в ней интересующая Вас функция:
public Task<ReportDataDictionary> GetData(UserConnection userConnection, IReadOnlyDictionary<string, object> parameters) { var contactFilter = ExtractFilterFromParameters(userConnection, _contactEntitySchemaUId, parameters); var result = new ReportDataDictionary { ["Contact"] = GetContactData(userConnection, _contactEntitySchemaUId, contactFilter), ["ContactAnniversary"] = GetContactAnniversaryData(userConnection, _contactAnniversaryEntitySchemaUId, contactFilter), ["LocalizableStrings"] = GetLocalizableStrings(userConnection) }; return Task.FromResult(result); }
Но обратите внимание, выше в коде есть сами функции GetContactData и GetContactAnniversaryData, получающие из базы коллекцию данных с указанным фильтром.
Зверев Александр,
Спасибо за помощь,
«Знаменательные события контакта» нашла, сделала полностью по аналогии. Та же ошибка.
Ошибка исчезает, как только убираю второй источник данных(
Может быть дело в версии, отчет на 16.1 - наша 16.0...
Если дело в версии, зарегистрируйте тестовый сайт и проверьте такое же там.