Obtain a Report from a Web API Controller Endpoint(从 Web API 控制器端点获取报告 )
This topic demonstrates how to obtain a report through HTTP requests to the DevExpress Web API Service.
本主题演示如何通过对DevExpress Web API服务的HTTP请求获取报告。
The application must use the following technologies to enable such API requests:
应用程序必须使用以下技术来启用此类API请求:
DevExpress Reporting(DevExpress报告)
Creates report definitions.(创建报告定义。)
XPO | EF Core
These ORM tools enable storage for report definitions and bound data.
这些ORM工具支持存储报表定义和绑定数据。
XAF Reports Module(XAF报告模块)
Stores report definitions in a database with the help of specially designed classes: ReportDataV2 (XPO) / ReportDataV2 (EF Core).
借助专门设计的类将报表定义存储在数据库中:ReportDataV2(XPO)/ReportDataV2(EF Core)。
HTTP request parameters allow you to filter or sort data before the API Controller generates the final report document.
HTTP请求参数允许您在API控制器生成最终报告文档之前过滤或排序数据。
Note
This option of our Web API Service ships as part of the DevExpress Universal Subscription.
我们的Web API服务的此选项作为DevExpress通用订阅的一部分提供。
Report Controller Availability(报告控制器可用性)
The API described in this article only works if your project contains an MVC Controller that allows you to access reports – ReportController. You can use the following methods to enable this controller in your applications:
本文中描述的API仅在您的项目包含允许您访问报告的MVC控制器-ReportController时才有效。您可以使用以下方法在应用程序中启用此控制器:
Enable the Module in the Solution Wizard(在解决方案向导中启用模块)
If you create your Backend Web API project with the help of the Solution Wizard, a dedicated wizard screen allows you to enable the Reports module. For additional information, see Create a Standalone Web API Application.
如果您在解决方案向导的帮助下创建后端Web API项目,则专用向导屏幕允许您启用报告模块。有关其他信息,请参阅创建独立Web API应用程序。
Add the Reports Module to a Standalone Web API or XAF Blazor Application(将报告模块添加到独立的Web API或XAF Blazor应用程序)
1.Install the DevExpress.ExpressApp.ReportsV2.Blazor NuGet package.
安装DevExpress. ExpressApp.ReportsV2。Blazor NuGet包。
2.Register the Reports module and required services in Startup.cs. Use the Web API builder or XAF Application builder:
在Startup. cs中注册Reports模块和所需的服务。使用Web API构建器或XAF应用程序构建器:
File: MySolution.WebApi\Startup.cs (MySolution.Blazor.Server\Startup.cs)
C#
(Standalone WEB API Service) C# (XAF Application Builder) services.AddXafWebApi(builder => {
//...
builder.Modules
.AddReports(options => {
//...
})
//...
}, Configuration);
services.AddXaf(Configuration, builder => {
//...
builder.Modules
.AddReports(options => {
//...
})
//...
}
3.Add an API controller with endpoints to download reports to your existing Blazor application. An example of this controller can be found in our demo application that ships with the XAF installation (%PUBLIC%\Documents\DevExpress Demos 24.1\Components\XAF\MainDemo.NET.EFCore\CS\MainDemo.Blazor.Server\API\Reports\ReportController.cs by default).
添加带有端点的API控制器以将报告下载到现有的Blazor应用程序。可以在XAF安装附带的演示应用程序中找到此控制器的示例(默认为%PUBLIC%\Documents\DevExpress Demos 24.1\Components\XAF\MainDemo.NET。EFCore\CS\MainDemo. Blazor.Server\API\Reports\ReportController.cs)。
Report Controller API(报表控制器API)
The ReportController class includes the following methods:
ReportController类包括以下方法:
C#
[HttpGet("DownloadByKey({key})")]
public async Task<object> DownloadByKey(string key,
[FromQuery] ExportTarget fileType = ExportTarget.Pdf,
[FromQuery] string criteria = null) {
//...
}
[HttpGet("DownloadByName({displayName})")]
public async Task<object> DownloadByName(string displayName,
[FromQuery] ExportTarget fileType = ExportTarget.Pdf,
[FromQuery] string criteria = null) {
//...
}
Basic Usage Example(基本用法示例)
This example demonstrates how to obtain a report as a PDF file. The code in this example sends a request to the Report/DownloadByName endpoint with the displayName parameter.
此示例演示如何以PDF文件的形式获取报告。此示例中的代码使用displayName参数向Report/DownloadByName端点发送请求。
C#
HttpClient httpClient = new HttpClient();
// Set up client Uri.
httpClient.BaseAddress = new Uri("https://localhost:5001/");
// Argument for the DownloadByName method.
var displayName = "Employee List Report";
// Send request for a report PDF.
var response = await httpClient.GetAsync(
$"/api/Report/DownloadByName({displayName})"
);
// Parse the result from HttpResponseMessage.
var report = await response.Content.ReadAsStringAsync();
Configure the Request Locale(配置请求区域设置)
You can use the HttpRequestMessage API to configure the request locale:
您可以使用HttpRequestMessage API来配置请求区域设置:
C#
var customRequest = new HttpRequestMessage(HttpMethod.Get,
$"/api/Report/DownloadByName({displayName})");
customRequest.Headers.Add("Accept-Language", "en-US");
var response = await httpClient.SendAsync(customRequest);
For additional information, refer to the following article: Accept-Language header in HttpRequestHeaders.
有关其他信息,请参阅以下文章:HttpRequestHeaders中的Accept-Language标头。
Specify a Filter Condition(指定过滤器条件)
To specify a filter condition, use a query parameter named criteria. For example, the following URL instructs the report to only include records where “FirstName” equals “Aaron”:
要指定过滤条件,请使用名为条件的查询参数。例如,以下URL指示报告仅包含“FirstName”等于“Aaron”的记录:
/api/Report/DownloadByName(ReportName)?criteria=[FirstName] = 'Aaron'
Note
ReportController filters data on the server side.
ReportController在服务器端过滤数据。
The report itself can apply additional filter conditions to the data source. The criteria set by the report’s FilterString property take effect on the client side, after the data is loaded.
报表本身可以对数据源应用额外的过滤条件。报告的FilterString属性设置的条件在加载数据后在客户端生效。
Specify Sort Order(指定排序顺序)
You can use the sortProperty query parameter. For example, the following URL sorts records by FirstName in descending order:
您可以使用sortProperty查询参数。例如,以下URL按FirstName按降序对记录进行排序:
/api/Report/DownloadByName(ReportName)?sortProperty=[FirstName],Descending
Note
The sort order can be overriden by the report. A report band’s SortFields property takes priority if it conflicts with the specified sort order.
排序顺序可以被报表覆盖。如果报表带的SortFields属性与指定的排序顺序冲突,则该属性具有优先级。
Pass Report Parameters*(通过报告参数)
If your report uses Parameters, you can pass their values in the query. For example, the following URL sets parameters FirstName and Position to “Mary” and “Manager”, respectively:
如果您的报表使用参数,您可以在查询中传递它们的值。例如,以下URL将参数FirstName和Poplace分别设置为“Mary”和“Manager”:
/api/Report/DownloadByKey({key})?FirstName=Mary&Position=Manager
Report Controller Customization(报告控制器定制)
To use Web API Authentication, decorate the ReportController with AuthorizeAttribute.
要使用Web API身份验证,请使用AuthorizeAtual装饰ReportController。
Note that the ReportController uses a report export service: IReportExportService. This service loads a report and prepares it to be exported to the specified format.
请注意,ReportController使用报表导出服务:IReportExportService。该服务加载报表并准备将其导出为指定格式。
C#
using Microsoft.AspNetCore.Mvc;
using DevExpress.ExpressApp.ReportsV2;
public class ReportController : ControllerBase {
private readonly IReportExportService service;
// ...
}
You can modify the controller’s methods as required and even use IReportExportService to create custom endpoints.
您可以根据需要修改控制器的方法,甚至可以使用IReportExportService创建自定义端点。
The report export service includes helper methods that manage reports and their data sources. Note the SetupReport method that allows you to specify the following parameters before report export: a filter condition and an array of sort properties.
报表导出服务包括管理报表及其数据源的辅助方法。请注意SetupReport方法,该方法允许您在报表导出之前指定以下参数:过滤条件和排序属性数组。
C#
void SetupReport(XtraReport report, string criteria = null,
SortProperty[] sortProperties = null);
*Add Unit Tests for Report Controller(*为报表控制器添加单元测试)
Follow the steps below to add unit tests for code that queries reports from the ReportController.
按照以下步骤为从ReportController查询报告的代码添加单元测试。
1.If your solution does not have a testing project, add a new xUnit test project.(如果您的解决方案没有测试项目,请添加一个新的xUnit测试项目。)
2.Add a reference to the {SolutionName}.Blazor.Server project.(添加对{SolutionName}的引用。Blazor. Server项目。)
3.Add the Microsoft.AspNetCore.Mvc.Testing package reference.(添加Microsoft. AspNetCore.Mvc.测试包参考。)
4.Add the following test to the test project:(将以下测试添加到测试项目中:)
C#
using System.Net.Http.Headers;
using System.Text;
using DevExpress.Data.Filtering;
using DevExpress.Xpo;
using DevExpress.XtraPrinting;
using MainDemo.Module.BusinessObjects;
using Microsoft.AspNetCore.Mvc.Testing;
using Xunit;
public class ReportByNameUnitTests
: IClassFixture<WebApplicationFactory<MainDemo.Blazor.Server.Startup>> {
HttpClient httpClient;
string ApiUrl = "/api/Report/DownloadByName";
public ReportByNameUnitTests(WebApplicationFactory<MainDemo.Blazor.Server.Startup> webApplicationFactory) {
httpClient = webApplicationFactory.CreateClient();
httpClient.DefaultRequestHeaders.Add("Accept-Language", "de-DE");
}
// A simple test example (no authentication)
[Fact]
public async System.Threading.Tasks.Task LoadReport() {
string url = CreateRequestUrl("Employee List Report");
var response = await httpClient.GetAsync(url);
string loadedReport = await response.Content.ReadAsStringAsync();
// Validate the result
// ...
}
// An advanced test example
[Fact]
public async System.Threading.Tasks.Task LoadReportWithCriteria() {
string tokenString = await GetUserTokenAsync("Sam", "", "/api/Authentication/Authenticate");
var authorizationToken = new AuthenticationHeaderValue("Bearer", tokenString);
string criteria = CriteriaOperator.FromLambda<Employee>(x => x.FirstName == "Aaron" || x.LastName == "Benson").ToString();
string url = CreateRequestUrl("Employee List Report", criteria, null, null, ExportTarget.Csv);
var httpRequest = new HttpRequestMessage(HttpMethod.Get, url);
httpRequest.Headers.Authorization = authorizationToken;
var response = await httpClient.SendAsync(httpRequest);
string loadedReport = await response.Content.ReadAsStringAsync();
// Validate the result
// ...
}
private string CreateRequestUrl(
string reportName, string? criteria = null, string? reportParameters = null,
SortProperty[]? sortProperties = null, ExportTarget exportType = ExportTarget.Pdf) {
string url = $"{ApiUrl}({reportName})";
var q = $"fileType={exportType}";
if(!string.IsNullOrEmpty(criteria)) {
q += $"&criteria={criteria}";
}
if(sortProperties != null && sortProperties.Length > 0) {
foreach(var sortProperty in sortProperties) {
q += $"&sortProperty={$"{sortProperty.PropertyName},{sortProperty.Direction}"}";
}
}
if(!string.IsNullOrEmpty(reportParameters)) {
q += $"&{reportParameters}";
}
url += "?" + q;
return url;
}
async Task<string> GetUserTokenAsync(string userName, string password, string requestPath) {
var request = new HttpRequestMessage(HttpMethod.Post, requestPath);
request.Content = new StringContent(
$"{{ \"userName\": \"{userName}\", \"password\": \"{password}\" }}", Encoding.UTF8, "application/json");
var httpResponse = await httpClient.SendAsync(request);
if(!httpResponse.IsSuccessStatusCode) {
throw new UnauthorizedAccessException($"Authorization request failed! Code {(int)httpResponse.StatusCode}, '{httpResponse.ReasonPhrase}'");
}
var tokenString = await httpResponse.Content.ReadAsStringAsync();
return tokenString;
}
}