I have a web page with HTML5 Telerik report viewer, which should generate and show a report in the web page.
How does Telerik report viewer get data?
You create an implementation of the class ReportControllerBase, which is a class of the Telerik framework derived from ApiController. The class you create, which in few words is simply an ApiController, is used by the report viewer to retrieve the report, or more precisely a ReportSource.
The report viewer retrieves a ReportSource, and the ReportSource retrieves data for the report.
So, inside the ReportController you istantiate a ReportSource, you configure it so that it knows where to retrieve data, and you return it.
In my case ReportSource retrieves data thanks to a method of a class called OffersCRUD. This method, before to call a WCF service to get data from the database, must extract the username from the session, but the problem is that HttpContext.Current.Session is null.
I know that by deafault sessions are not enabled in Web api, but I wrote some lines of code to force it using sessions, which seems to work well in general.
There are two important requests during the report generation.
Request 1: ReportController is called, the ReportSource is istantiated to use OffersCRUD as datasource and then returned. Here the session works.
Request 2: Now that that the Report Viewer has retrieved the ReportSource, it performs an other request to obtain data, and so we are now inside the class OffersCRUD. Here the session doesn't work, it is null..
So, from now I will only speak about the second request. From the point of view of the debugger, everything starts in the following method (before this there is External code, the code which calls the method is encapsulated)
[DataObjectMethod(DataObjectMethodType.Select)]
public static PersonOfferDTO GetPersonOfferByNumber(string offerNumber)
{
PersonOfferDTO result = null;
List<IError> errors = new List<IError>();
ServiceCaller.GetDataWithServiceUsingParameter(GetPersonOffer, errors, ref result, offerNumber);
return result;
}
Then, after some lines of code, we are inside the class UserSession, which is a wapper of the session.
public static class UserSession
{
private static UserDTO _currentUser;
public static UserDTO GetCurrentUser()
{
HttpContext context = HttpContext.Current;
if(context.Session["UserLogin"] == null)
{
return null;
}
UserDTO currentUser = context.Session["UserLogin"] as UserDTO;
return currentUser;
}
public static void SaveUserStatus(UserDTO user)
{
Validate.EnsureArgumentIsNotNull(user);
HttpContext context = HttpContext.Current;
context.Session["UserLogin"] = user;
}
}
In the method UserDTO GetCurrentUser(void), the state of HttpContext.Current is what you can see in the picture below.
As you can see, Session is null, so it will fail when it will try to access Session["UserLogin"].
If you want more details you only have to write a comment here below.
Create Telerik Report => Start Process in Background Thread => UI => Load processed report from Background Thread
The background thread does not have access to the current context and the current session.
You also tightly coupled your business logic to the ASP.NET session object.
You could try a regular MVC Controller/Action instead of WebAPI, but if its called in a background thread and does not pass browser cookies then it would not have knowledge of the current session.
You could try to set the username/password as report parameters, and then pass those into your webservice in the NeedsDataSource event.
Or if its a known report, you could load and attach the data to a public property on the report and bind it in the NeedsDataSource event.