Base solution for your next web application
Open Closed

DevExpress Reporting - how to integrate successfully? #11733


User avatar
0
lschelvan created

If there's anybody who's successfully integrated DevExpress Reporting (23.1.5) with AspNetZero (11.3, .NET Core + Angular), I am very interested to know how you got it working....

I've followed this process : https://docs.aspnetzero.com/en/aspnet-core-angular/latest/DevExpress-Reporting-Implementation-Angular

But this throws an exception referencing WebDocumentViewerController, because DevExpress has recently made their controller classes abstract: https://supportcenter.devexpress.com/ticket/details/t1019255/reporting-for-asp-net-core-blazor-server-the-report-designer-web-document-viewer-and

Following their recommended procedure, I've added the explicit controller classes.

But doing this breaks my Web.Host app during Swagger generation:

An unhandled exception occurred while processing the request. SwaggerGeneratorException: Ambiguous HTTP method for action - MyApp.Web.Controllers.CustomQueryBuilderController.Invoke (MyApp.Web.Host). Actions require an explicit HttpMethod binding for Swagger/OpenAPI 3.0 Swashbuckle.AspNetCore.SwaggerGen.SwaggerGenerator.GenerateOperations(IEnumerable<ApiDescription> apiDescriptions, SchemaRepository schemaRepository)


17 Answer(s)
  • User Avatar
    0
    m.aliozkaya created
    Support Team

    Hi @lschelvan,

    It looks like the current document is deprecated (written 2 years ago). We will update the document as soon.

    You can follow the progress https://github.com/aspnetzero/aspnet-zero-core/issues/5014

  • User Avatar
    0
    lschelvan created

    Thank you.

    I was able to get past the Swashbuckle issue and get the routing working by adding custom classes for the DevExpress controllers, as follows:

    `ApiExplorerSettings(IgnoreApi = true)]
     [Route("DXXRDV")]
      
     public class CustomWebDocumentViewerController : WebDocumentViewerController
     {
         public CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService controllerService) : base(controllerService) { }
         public override Task&lt;IActionResult&gt; Invoke()
         {
             return base.Invoke();
         }
     }
    

    `

    The main problem I'm now having (in the MVC Core Web.Host) is related to dependency injection:

    `An unhandled exception occurred while processing the request.
    ComponentNotFoundException: No component for supporting the service MyApp.Web.Controllers.CustomWebDocumentViewerController was found
    Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, Arguments arguments, IReleasePolicy policy, bool ignoreParentContext)
    
    ComponentNotFoundException: No component for supporting the service MyApp.Web.Controllers.CustomWebDocumentViewerController was found
    Castle.MicroKernel.DefaultKernel.Castle.MicroKernel.IKernelInternal.Resolve(Type service, Arguments arguments, IReleasePolicy policy, bool ignoreParentContext)
    Castle.MicroKernel.DefaultKernel.Resolve(Type service, Arguments arguments)
    Castle.Windsor.MsDependencyInjection.ScopedWindsorServiceProvider.GetServiceInternal(Type serviceType, bool isOptional)
    Microsoft.Extensions.DependencyInjection.ServiceProviderServiceExtensions.GetRequiredService(IServiceProvider provider, Type serviceType)
    Microsoft.AspNetCore.Mvc.Controllers.ServiceBasedControllerActivator.Create(ControllerContext actionContext)`
    

    This error has been reported by a few other users. I've tried implementing various fixes but still get the same Castle error.

    For example, I'm doing this (as described in https://aspnetzero.com/blog/devexpress-reporting-angular )

    ` options.IocManager.Register(typeof(WebDocumentViewerController), DependencyLifeStyle.Transient);
     options.IocManager.Register(typeof(QueryBuilderController), DependencyLifeStyle.Transient);
     options.IocManager.Register(typeof(ReportDesignerController), DependencyLifeStyle.Transient);`
    
    

    Unfortunately, that makes no difference.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @lschelvan

    Could you share where do you register controllres to DI ? I mean the place of the below code block, is it in your web module ?

    options.IocManager.Register(typeof(WebDocumentViewerController), DependencyLifeStyle.Transient);
    options.IocManager.Register(typeof(QueryBuilderController), DependencyLifeStyle.Transient);
    options.IocManager.Register(typeof(ReportDesignerController), DependencyLifeStyle.Transient);
    
  • User Avatar
    0
    lschelvan created

    Yes, I have tried this in the web module code IocManager.Register(typeof(WebDocumentViewerController), DependencyLifeStyle.Transient); IocManager.Register(typeof(QueryBuilderController), DependencyLifeStyle.Transient); IocManager.Register(typeof(ReportDesignerController), DependencyLifeStyle.Transient);

    and also tried in Startup (using the code in the previous message).

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @lschelvan

    Sorry for my late reply, did you place it into Initialize method or PostInitialize method ?

  • User Avatar
    0
    lschelvan created

    It was in PreInitialize()

  • User Avatar
    0
    lschelvan created

    Woops I didn't mean to close this. The Castle Windsor DI issue is still an problem and I have not yet figured out how to get around it.

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @lschelvan

    Don't worry, we will try to find the problem and share it with you.

  • User Avatar
    0
    lschelvan created

    If it helps, we are planning to upgrade from AspNetZero 11.4 to 12.4 in the next couple of weeks...

  • User Avatar
    0
    ismcagdas created
    Support Team

    This document and related blog post is updated, see https://aspnetzero.com/blog/devexpress-reporting-angular

  • User Avatar
    0
    lschelvan created

    Thanks for the help!

  • User Avatar
    0
    lschelvan created

    I was able to use the updated instructions to install DevExpress reporting, and can now see my blank sample report.

    Next question: what is the best method for configuring data sources for reporting? In my ASPNetZero app, most of my tenants have their own SQL database. I'd like to have a single report configuration, with a single data source, that can work for any tenant. Does it make sense to create a connection string at runtime, which can then be used in the DevExpress report? Or is there some other easy way to do this ? ( perhaps by using the API and passing the current auth token as a parameter)?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    I think, using and API with the current auth token is better and works well with AspNet Zero.

  • User Avatar
    0
    lschelvan created

    What's the best way to get the current auth token from within the Web.Host app? Is there an Abp*** property that can be accessed?

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    You can access it using request headers with Abp.AuthToken key.

  • User Avatar
    0
    maharatha created

    I am currently trying to integrate Devexpress reporting. I have the latest version of Angular & .NetCore Abpzero.

    I was able to integrate successfully and was able to pass tokens as well.

    Issue : 1

    I was testing the Authorization by adding Authorize attribute like the below :

    one at the Controller :

    [AbpMvcAuthorize(AppPermissions.Pages_Tenants)]
    public class CustomWebDocumentViewerController(IWebDocumentViewerMvcControllerService controllerService) : WebDocumentViewerController(controllerService), ITransientDependency
    {
    

    The other one at the report level :

     [AbpMvcAuthorize(AppPermissions.Pages_Tenants)]
     public partial class SampleReport : DevExpress.XtraReports.UI.XtraReport
    

    If I don't pass a token, it throws an error which tells me it respects the Authentication.

    But when i remove the Page_Tenants permission and try to access the report from Angular app, I am still able to access the report.

    So it tells me the Authorization piece is not working or i have not implemented properly. I even tried with AbpAuthorize with the permission on the SampleReport class as well and that didn't work either.

    Issue : 2

    I have created an App Service called

    public class HostOrganizationUnitReportingAppService : DocuManageAppServiceBase, IHostOrganizationUnitReportingAppService
    {
        public async Task<OrganizationTenantReport> GetOrganizationTenantReport(OrganizationTenantReportInputDto input)
        {
            return new OrganizationTenantReport(1,"aa",4);
        }
    }
    

    How do I use this as Data Source for my report?

  • User Avatar
    0
    maharatha created

    Can I get some update on this ?