When developing enterprise applications, generating dynamic reports in multiple formats—such as PDF and Excel—is a common requirement. In this blog post, I will share my practical experience integrating SQL Server Reporting Services (SSRS) with an Angular frontend and ASP.NET Core backend.
This approach is useful for applications that require parameterized reports, centralized report management, and downloadable documents.
Report selection, filters, and export buttons
ASP.NET Core API
Validation, parameter preparation, and report processing
SSRS Report Server
Report execution and document rendering
Generated PDF / Excel File
Designing the Angular Report Form
The Angular frontend provides users with the necessary filters for generating a report.
The form includes:
Report selection
Office selection
Register selection
Group selection
Component selection
From date
To date
ng-select to provide searchable dropdowns and form validation.Example: Report Dropdown
The bindLabel property determines the displayed text, while bindValue determines the value stored in the form control.
Form Validation
Before generating a report, I validate the form:
if (this.dataForm.invalid) {
this.dataForm.markAllAsTouched();
this.toastr.warning(
'Please fill all required fields'
);
return;
}
I also validate the selected date range to ensure that the required dates are available.
2️⃣ Passing Parameters from Angular to the API
After validating the form, the selected values are extracted and passed to the report service.
const selectedOffice =
this.dataForm.get('officeId')?.value;
const selectedGroup =
this.dataForm.get('groupId')?.value || null;
const selectedFromDate =
this.dataForm.value.fromDate || null;
const selectedToDate =
this.dataForm.value.toDate || null;
The report service receives the selected values and prepares the API request.
An important consideration is maintaining consistent parameter names between:
Angular form controls
API endpoint parameters
SSRS report parameters
RDL report configuration
A mismatch in parameter names can cause report execution errors.
Generating PDF and Excel Reports
The frontend provides separate buttons for PDF and Excel generation.
<button
class="btn btn-danger"
(click)="generateReport('P')">
<i class="far fa-file-pdf"></i>
</button>
<button
class="btn btn-success"
(click)="generateReport('E')">
<i class="far fa-file-excel"></i>
Excel
</button>
The document type is sent to the backend, where it is mapped to the appropriate SSRS rendering format.
reportReturnFileFormat =
reportReturnFileFormat.ToLower() == "p" ||
reportReturnFileFormat.ToLower() == "pdf"
? "PDF"
: reportReturnFileFormat.ToLower() == "e" ||
reportReturnFileFormat.ToLower() == "excel" ||
reportReturnFileFormat.ToLower() == "excelopenxml"
? "EXCELOPENXML"
: "";
The supported output formats in this implementation are:
User Selection | SSRS Format |
|---|---|
|
Excel EXCELOPENXML |
Integrating SSRS with ASP.NET CoreThe backend uses The report server connection uses a SOAP endpoint and NTLM authentication. var binding = new BasicHttpBinding( BasicHttpSecurityMode.TransportCredentialOnly) { Security = { Transport = new HttpTransportSecurity { ClientCredentialType = HttpClientCredentialType.Ntlm } }, MaxReceivedMessageSize = 50 * 1024 * 1024, MaxBufferSize = 50 * 1024 * 1024, MaxBufferPoolSize = 50 * 1024 * 1024, SendTimeout = TimeSpan.FromMinutes(20), ReceiveTimeout = TimeSpan.FromMinutes(20) }; These settings configure the communication binding and allow larger report responses. Note: Timeout and message-size values should be configured according to the application's requirements and infrastructure. Increasing limits alone does not guarantee that every large report will execute successfully. 5️⃣ Loading the SSRS ReportAfter creating the report client, the report is loaded from the configured report server. var endpoint = new EndpointAddress(credential.Url); var client = new ReportExecutionServiceSoapClient( binding, endpoint); client.ClientCredentials.Windows.ClientCredential = new NetworkCredential( credential.UID, credential.PWD, credential.MachineName); var loadResponse = await client.LoadReportAsync( null, $"/Reports/{reportName}", null); var executionInfo = loadResponse.ExecutionHeader; The execution header is required for subsequent report operations, including setting credentials, configuring parameters, and rendering the report. 6️⃣ Configuring Report Data Source CredentialsThe report data source credentials are configured before executing the report. var dataSourceCredentials = new DataSourceCredentials[] { new DataSourceCredentials { DataSourceName = dataSourseName ?? "dsUpakul", UserName = _dbSettings.UserId, Password = _dbSettings.Password } }; The credentials are then applied to the report execution session: await client.SetExecutionCredentialsAsync( executionInfo, trustedUserHeader, dataSourceCredentials); Security ConsiderationReport server credentials and database credentials should not be hardcoded in production source code. Recommended practices include:
The uploaded implementation demonstrates the credential configuration process, but production security requirements should be considered separately. 7️⃣ Passing Parameters to SSRSThe backend prepares the report parameters using var paramList = new List<ParameterValue> { new ParameterValue { Name = "ServerName", Value = _dbSettings.ServerName }, new ParameterValue { Name = "DatabaseName", Value = _dbSettings.DatabaseName } }; Additional parameters are added to the list: |
if (parameters != null &&
parameters.Length > 0)
{
paramList.AddRange(parameters);
}
await client.SetExecutionParametersAsync(
executionInfo,
trustedUserHeader,
paramList.ToArray(),
"en-us");
The parameter names and values must match the parameters expected by the SSRS report.
For example:
new ParameterValue() { Name = "officeId", Value = officeId.ToString() }
Optional parameters can be represented using null according to the report's parameter configuration.
8️⃣ Rendering the Report
Once the report is loaded and its parameters are configured, the report can be rendered.
string deviceInfo =
"<DeviceInfo><Toolbar>False</Toolbar></DeviceInfo>";
var renderRequest = new RenderRequest
{
ExecutionHeader = executionInfo,
Format = reportReturnFileFormat,
DeviceInfo = deviceInfo
};
var renderResponse =
await client.RenderAsync(renderRequest);
return renderResponse.Result;
The rendering process returns the report content as a byte array.
This byte array can then be returned to the Angular application through an ASP.NET Core API response.
9️⃣ Returning the File from ASP.NET Core
The report-processing service returns the generated content and its content type.
return (
byt,
reportReturnFileFormat == "PDF"
? "application/pdf"
: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
);
The controller can return the generated file:
return File(
rtn.content,
rtn.contentType
);
This allows the frontend to receive the report as a binary response.
🔟 Opening the Report in Angular
The Angular service receives the response as a Blob.
.subscribe({
next: (blob: Blob) => {
const url =
window.URL.createObjectURL(blob);
window.open(
url,
this.dataForm.value.reportId,
'toolbar=no,location=no,status=no,' +
'menubar=no,scrollbars=no,resizable=no,' +
'fullscreen=no,width=600,height=600'
);
},
error: (err) => {
this.toastr.error(
err.message,
'Failed!'
);
}
});
The browser creates a temporary object URL for the generated file, which can then be opened in a new window.
Common Challenges
While implementing SSRS reporting, several areas require attention.
1. Parameter Mismatch
The parameter name in the API must match the parameter name configured in the RDL report.
2. Authentication
The report server requires appropriate authentication and access permissions.
3. Large Reports
Large reports may require suitable timeout and message-size configurations.
4. Optional Parameters
Optional filters must be handled consistently between the frontend, API, and report.
5. Credential Management
Database and report server credentials should be stored securely and should not be exposed in the frontend.
6. Error Handling
Report execution errors should be logged appropriately, while the API should return a meaningful response to the client.
✅ Conclusion
Integrating SSRS with Angular and ASP.NET Core provides a practical approach for building reporting functionality in enterprise applications.
The complete workflow involves:
Collecting report filters in Angular.
Validating the user input.
Passing parameters to the ASP.NET Core API.
Loading the report through the SSRS execution service.
Setting data source credentials and report parameters.
Rendering the report as PDF or Excel.
Returning the generated file to the frontend.
The most important lesson is that successful report integration requires coordination between the frontend, backend, SSRS configuration, report parameters, and security settings.
I hope this practical example helps other developers who are working with Angular, ASP.NET Core, SQL Server, and SSRS reporting.
🏷️ Tags
#Angular #ASPNetCore #DotNet #SSRS #SQLServer #WebDevelopment #EnterpriseApplications #SoftwareEngineering #CleanArchitecture #Reporting
No comments:
Post a Comment