Popular Posts

Sep 22, 2026

Integrating SSRS Reports with Angular and ASP.NET Core

 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

I used Angular Reactive Forms and ng-select to provide searchable dropdowns and form validation.

Example: Report Dropdown


<ng-select
  formControlName="reportId"
  [items]="reportListDropdown"
  bindLabel="text"
  bindValue="value"
  [searchable]="true"
  [clearable]="true"
  placeholder="Select Report"
  [class.is-invalid]="
    dataForm.get('reportId')?.touched &&
    dataForm.get('reportId')?.invalid
  ">
</ng-select>


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:

  1. Angular form controls

  2. API endpoint parameters

  3. SSRS report parameters

  4. 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>

  PDF

</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

        

PDF                                 PDF

Excel                                                        EXCELOPENXML


                                    


Integrating SSRS with ASP.NET Core

The backend uses ReportExecutionServiceSoapClient to communicate with the SSRS Report Server.

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 Report

After 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 Credentials

The 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 Consideration

Report server credentials and database credentials should not be hardcoded in production source code.

Recommended practices include:

  • Using secure configuration providers.

  • Avoiding credentials in source control.

  • Restricting access to configuration secrets.

  • Using environment-specific configuration.

  • Applying the principle of least privilege.

The uploaded implementation demonstrates the credential configuration process, but production security requirements should be considered separately.

7️⃣ Passing Parameters to SSRS

The backend prepares the report parameters using ParameterValue.


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:

  1. Collecting report filters in Angular.

  2. Validating the user input.

  3. Passing parameters to the ASP.NET Core API.

  4. Loading the report through the SSRS execution service.

  5. Setting data source credentials and report parameters.

  6. Rendering the report as PDF or Excel.

  7. 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