Dynamically loading report assembly

3 posts, 0 answers
  1. Nikita
    Nikita avatar
    2 posts
    Member since:
    Nov 2018

    Posted 17 Jan Link to this post

    Hello. I've faced a problem trying to use HTML5 MVC Report viewer when using a .dll file loaded during runtime. I'm using a custom report resolver which creates TypeReportSource, sets a type name which I get from the loaded .dll  and then returns the created report source. However, the report viewer displays an error. (Stack trace below).

     

    Is it possible to use reporting service with a dynamically loaded .dll like that? Or is it only possible if I reference the .dll in my project directly (when I do that, everything works, but this is obviously not a desired way for me)

    stackTrace: "   в Telerik.Reporting.Processing.TypeReportDocumentResolver.Resolve(IProcessingContext context, TypeReportSource rs)<br>↵   в Telerik.Reporting.Processing.ReportDocumentResolver`1.Telerik.Reporting.Processing.IReportDocumentResolver.Resolve(IProcessingContext context, ReportSource rs)<br>↵   в Telerik.Reporting.Processing.ReportDocumentResolver.<>c__DisplayClass1.<Resolve>b__0(IReportDocumentResolver r)<br>↵   в Telerik.Reporting.Processing.ReportDocumentResolver.Bind[T](IProcessingContext context, ReportSource source, Func`2 func)<br>↵   в Telerik.Reporting.Processing.ReportDocumentResolver.Resolve(IProcessingContext context, ReportSource source)<br>↵   в Telerik.Reporting.Processing.ResolvedReportDocument.ResolveReportsRecursively(ReportSource rs, IProcessingContext context, IDictionary`2 parentRsParameters, Boolean parentShouldDispose, List`1 result, IReportDocument& definition, ResolvedReport& tocReport, ReportBookTocPosition& tocReportPosition)<br>↵   в Telerik.Reporting.Processing.ResolvedReportDocument.Create(ReportSource rs, IProcessingContext context)<br>↵   в Telerik.Reporting.Services.Engine.ReportEngine.GetParameters(String clientID, String report, Dictionary`2 parameterValues)<br>↵   в Telerik.Reporting.Services.WebApi.ReportsControllerBase.GetParameters(String clientID, ClientReportSource reportSource) в c:\temp\reporting\RBuild-18776\Reporting_Build\Source\Code\Telerik.Reporting.Services.WebApi\ReportsControllerBase.cs:строка 166<br>↵   в lambda_method(Closure , Object , Object[] )<br>↵   в System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_1.<GetExecutor>b__3(Object instance, Object[] methodParameters)<br>↵   в System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)<br>↵   в System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)<br>↵--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)<br>↵   в System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()<br>↵--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)<br>↵   в System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()<br>↵--- Конец трассировка стека из предыдущего расположения, где возникло исключение ---<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)<br>↵   в System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)<br>↵   в System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()"
  2. Silviya
    Admin
    Silviya avatar
    335 posts

    Posted 22 Jan Link to this post

    Hi Nikita,

    The TypeReportSource gets details which report to be processed based on the report's type. Then the reporting engine uses System.Reflection to create an instance of the report through its default parameterless constructor.

    In order the report instance to be created, the type must be loaded and available before requesting the report. The assembly containing the report should be loaded in the application domain. Our suggestion is to load the assembly at a place where it can be globally accessible. For example in the Global.asax Application_Start load and resolve the assembly in the current domain: 
    protected void Application_Start(object sender, EventArgs e)
    {
        AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
    }
     
    System.Reflection.Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        if (args.Name.Contains("ReportClassLibrary"))
        {
            return System.Reflection.Assembly.Load(System.IO.File.ReadAllBytes("[absolute_path]\\ReflectionDLL\\ReportClassLibrary.dll"));
        }
     
        return null;
    }

    Regards,
    Silviya
    Progress Telerik
    Do you want to have your say when we set our development plans? Do you want to know when a feature you care about is added or when a bug fixed? Explore the Telerik Feedback Portal and vote to affect the priority of the items
  3. Nikita
    Nikita avatar
    2 posts
    Member since:
    Nov 2018

    Posted 22 Jan Link to this post

    Silviya, thanks for the clarification!
Back to Top