This is a migrated thread and some comments may be shown as answers.

Cannot use sub-report that have objectDataSource parameter populated from code-behind using dependency injection with Spring.NET

4 Answers 160 Views
General Discussions
This is a migrated thread and some comments may be shown as answers.
Guillaume
Top achievements
Rank 1
Guillaume asked on 18 Jul 2012, 05:44 AM

Here is the description of my problem. It occurs when using Spring.NET dependency injection:

- Create a new Asp.NET project in C# with Visual Studio 2010 SP1.
- Add a reference to Spring.Core (version 0.0.0.40704)
- Add a new Telerik report called Report1.cs (cancel the wizard).
- Add a new Telerik report called Report2.cs (cancel the wizard).
- Compile the solution.
- Add a new class in your project named Class1.
- Add a new class in your project named Class2.
- Add a new interface named IClass2 and make Class2 implement it.
- In Class1 add the following code:

public int GetValue(Class2 myObject)
{
    return 1;
}

In the code behind of the Global.asax file add the following field and the following method:

private static IApplicationContext _applicationContext;
public static T GetInstance<T>(String objectName)
{
    return (T)_applicationContext.GetObject(objectName);
}

- Update the method Application_Start so that it looks like the following:

void Application_Start(object sender, EventArgs e)
{
    // Code that runs on application startup
    _applicationContext = ContextRegistry.GetContext();
}

- Add the required Spring namespaces in the class (Spring.Context and Spring.Context.Support).
- The configuration of Spring.NET doesn't matter here as we will see later. Actually you don't even need to configure Spring.NET
- In Report1, in the detail section add a sub-report. Set its ReportSource property to point to Report2.
- In Report2, add an ObjectDataSource.
- Set the DataSource property of the ObjectDataSource to Class1.
- Set the DataMember property of the ObjectDataSource to GetValue.
- Keep the parameter value empty.
- In the code-behind of Report2, update the constructor so that it looks like this:

public Report2()
{
    //
    // Required for telerik Reporting designer support
    //
    InitializeComponent();
    //
    // TODO: Add any constructor code after InitializeComponent call
    //
    if (!DesignMode)
    {
        IClass2 myObject = Global.GetInstance<IClass2>("Class2");
        objectDataSource1.Parameters["myObject"].Value = myObject;
    }
}

- If it is open, close the Report1 designer. Compile. Reopen the designer. You get the following errors:

- "Object reference not set to an instance of an object."
- "The variable 'report21' is either undeclared or was never assigned."

If you check the designer-generated code of Report1 you will notice that the variable report21 is correctly declared AND assigned.

Now, go back to Global.asax code-behind and update the GetInstance method so that it looks like this;

public static T GetInstance<T>(String objectName)
{
    return (T)(object)new Class2();
}

- If it is open, close the Report1 designer. Compile. Reopen the designer. It's working fine.

My understanding is that the property DesignMode does not work as expected when it is used from within a SubReport. The code in GetInstance should never be called from within the designer. The fact that I have an error when using Spring.NET (probably due to the fact that my config doesn't handle design-time mode correctly but it's another issue) means that this piece of code is actually called at design time. If I open Report2 directly, it is showing as expected.

My issue is the following: I cannot open a report that contains a subreport which constructor is used to handle parameter of type object which are retrieved through dependency injection with Spring.NET

Am I doing something wrong? Is there any fix or workaround for this issue?

Thanks a lot for your help

4 Answers, 1 is accepted

Sort by
0
Accepted
Hrisi
Telerik team
answered on 20 Jul 2012, 01:05 PM
Hello Guillaume,

Thank you for the detailed explanations. In short, the DesignMode property is valid after the Report class was instantiated, as there is no ISite set in the constructor. You can defer instantiation of the inner report to run-time by changing the ReportSource type from InstanceReportSource to TypeReportSource. For more information please check the Report Sources help article.

Kind regards,
Hrisi
the Telerik team

BLOGGERS WANTED! Write a review about Telerik Reporting or the new Report Designer, post it on your blog and get a complimentary license for Telerik Reporting. We’ll even promote your blog and help bring you a few fresh readers. Yes, it’s that simple. And it’s free. Get started today >

0
Guillaume
Top achievements
Rank 1
answered on 17 Sep 2012, 07:40 AM
Hello Hrisi,

Sorry for not coming back to you earlier. I tried your solution and it worked. Thanks a lot!
0
Chandra
Top achievements
Rank 1
answered on 05 Aug 2020, 07:25 AM

I am getting error "The variable 'items' is either undeclared or was never assigned." in design view when I use below code in InitializeComponent method:

ReportItemBase.ItemCollection items = this.detail.Items;

items.AddRange(reportItemBaseArray);

but the designer works fine when I don't declare a local variable like shown below:

this.detail.Items.AddRange(reportItemBaseArray);

Can you please tell me why this is happening and how to fix it?

Thanks,

Abhi

0
Katia
Telerik team
answered on 10 Aug 2020, 08:44 AM

Hello Abhi,

It is not recommended to add custom code inside InitializeComponent method as this code is generated by the designer. A better option is to add your custom code after InitializeComponent method in the report constructor.

 

Regards,
Katia
Progress Telerik

Tags
General Discussions
Asked by
Guillaume
Top achievements
Rank 1
Answers by
Hrisi
Telerik team
Guillaume
Top achievements
Rank 1
Chandra
Top achievements
Rank 1
Katia
Telerik team
Share this question
or