Posts Tagged 'power view'

Power View – how it works: part 3

So far in this series we’ve explored some of the internals of Power View, how it communicates with Reporting Services and how it’s possible to create our own service to mimic the SSRS web service. Last year at  the PASS Summit 2011 Microsoft demonstrated Power View working on various mobile devices, but over a year later all we currently have is a Silverlight version.

So in this final post I want to explore the possibility of creating a HTML5 version of Power View using the existing interfaces in order to simply replace the Silverlight version with a HTML5 one. To some this may seem like a strange thing to do, but I really believe the future of BI (especially mobile BI) is based on open web standards. In fact it was one of my main motivators in liberating PivotViewer from Silverlight.

However it turns out there are quite a few challenges to overcome in order to render an rdlx report using only JavaScript. This post will cover just a few of the pieces of the puzzle that I’ve investigated and is not the entire solution.

The first task is to extract the actual report definition from the rdlx zip file. To do this I found a really great library called zip.js that uses HTML5 web workers to enumerate and extract the contents of zip files. It’s actually a pretty impressive library, and allows for extraction from http, blob or string encoded zip files.

Reading the RDLX

// use a HttpReader to read the zip from URL
            zip.createReader(new zip.HttpReader('/Content/rdlx/Report1.rdlx.zip'), function (reader) {
                // get all entries from the zip
                reader.getEntries(function (entries) {
                    if (entries.length) {
                        for (var i = 0; i < entries.length; i++) {
                            if (entries[i].filename.indexOf('.rdl') >= 0) {
                                //get rdl
                                entries[i].getData(new zip.TextWriter(), function (text) {
                                    // text contains the entry data as a String
                                    console.log(text);
                                    // close the zip reader
                                    reader.close(function () {
                                        // onclose callback
                                    });
                                }, function (current, total) {
                                    // onprogress callback
                                });
                            }
                        }
                    }
                });
            }, function (error) {
                // onerror callback
                console.log(error);
            });

In the example above I’m using a zip.js HttpReader object to grab my rdlx file from a URL. The created reader has a getEntries method that enumerates the zip file and returns it’s contents as an array of files. I’m then looking for files with ‘.rdl’ in their name and dumping the contents out to the console.

Next Steps

Once we’ve extracted the rdl file we can start parsing the xml to create the elements of our report in HTML. As you can imagine this is not a trivial task, and I’m not going to go into this in any detail. I did however discover that the updated schema for Power View reports hasn’t been published anywhere by Microsoft (http://schemas.microsoft.com/sqlserver/reporting/2011/01/reportdefinition) even though the SQL Server 2012 SSRS schema has been (http://schemas.microsoft.com/sqlserver/reporting/2010/01/reportdefinition/ReportDefinition.xsd). I’ve only spent a little time looking around for it, so if anyone else finds it please let me know. Without the schema creating a one-for-one copy of a Power View report is a little trickier, but still possible.

Regardless, lets assume that parsing the rdl and building up the UI has been done, the next step is to start calling the report server web service with the RenderEdit command to grab the actual data. This could be done with a series of ajax calls, and the binary result could be parsed in JavaScript – but this would be horribly inefficient. JavaScript just isn’t built to handle data in that way.

Final Thoughts

While I believe a HTML5 version of Power View is possible, it would require a serious amount of effort to implement based on the current SSRS architecture. In it’s current incarnation the SSRS web service returns mostly binary data instead of web friendly XML or JSON formats, which could quite easily be consumed by client side code. In my opinion it’s a shame that PowerPivot and Power View are not more open and queryable.

The conclusion is that if Microsoft does release a HTML5 version of Power View some big changes are going to have to be made to the way the SSRS web service communicates.

Power View – how it works: part 2

In the last post on Power View I had a bit of a look at how Power View communicates with Reporting Services. You can read more about that in Part 1.

Having a basic understanding on the inner workings of Power View allows us to appreciate all that is going on when a Power View report is requested. In addition we are able to use that insight to enhance the Power View experience and even create solutions to make it a better experience for our users.

Warm the Cache

For example one thing that is lacking in a Power View .rdlx file is a caching mechanism like what is possible with their .rdl cousins. By default the PowerPivot database in Analysis Services will get cleaned up after 48 hours of inactivity, the duration can be configured in Central Administration > General Application Settings > Configure service application settings > Disk Cache.
PowerPivot Disk CacheBut what if you’ve got a report that is accessed infrequently? Well based on our knowledge of the Reporting Services web service, we could, for instance write a PowerShell script to pre-load or warm the cache by sending an rs:GetReportAndModels request:

$web = Get-SPWeb http://server2008r2
$list = $web.Lists["PowerPivot Gallery"]

$spQuery = New-Object Microsoft.SharePoint.SPQuery
$spQuery.ViewAttributes = "Scope='Recursive'";
$spQuery.RowLimit = 2000
$caml = '<Where><Eq><FieldRef Name="File_x0020_Type" /><Value Type="Text">rdlx</Value></Eq></Where>' 
$spQuery.Query = $caml 

do
{
    $listItems = $list.GetItems($spQuery)
    $spQuery.ListItemCollectionPosition = $listItems.ListItemCollectionPosition
    foreach($item in $listItems)
    {
		$reportAddress = $web.Url + "/_vti_bin/reportserver/?" + [System.Uri]::EscapeDataString($web.Url + "/" + $item.Url) + "&rs:Command=GetReportAndModels"
		$request = [System.Net.WebRequest]::Create($reportAddress)
		$request.Credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
		$request.ContentType = "application/progressive-report"
		$request.GetResponse()
    }
}
while ($spQuery.ListItemCollectionPosition -ne $null)

Powerless View

One of the early criticisms of Power View is that there are so many dependencies, and not everyone wants to have a full blown SharePoint Enterprise install just to make it work – in fact there is even a connect item about it spearheaded by Jen Stirrup (blog|twitter) (and yes, I do realise that in a lot of respects Excel 2013 makes this issue moot).

Well now that we know how Power View communicates with Reporting Services we can use that knowledge to simulate our own web service, slice out Power View from SharePoint, transplant it to a regular web application and then stitch it all up.

With ASP.NET MVC and custom routes this is remarkable easy. I’m using MVC 4, but custom routes are one of the core features of ASP.NET MVC and so this could be done in any version of MVC.

routes.MapRoute(
  name: "ReportServer",
  url: "_vti_bin/{controller}/{action}/{id}",
  defaults: new { controller = "ReportServer", action = "Index", id = UrlParameter.Optional }
);

We need to listen for calls to the _vti_bin/ReportServer start address, in my version I’ve set the second part of the string to be the controller, which defaults to ReportServer.

Once we’ve created the route, we then need to create a controller called ReportServer to handle to requests. I’ve put together a simple controller that looks for the rs:command query parameter and then returns a custom ActionResult for each rs:command type.

public class ReportServerController : Controller
{
  public ActionResult Index()
  {
    if(String.IsNullOrEmpty(Request.QueryString["rs:Command"]))
      return View();
    var command = Request.QueryString["rs:Command"];

    if (command == "GetReportAndModels")
      return new GetReportAndModelsActionResult(string.Format("http://{0}/Content/rdlx/Report.rdlx", Request.Url.Authority));
    else if (command == "RenderEdit")
    {
      if (!String.IsNullOrEmpty(Request.QueryString["rs:ProgressiveSessionId"]))
        return new RenderEditActionResult(string.Format("http://{0}/Content/rdlx/RenderEdit.bin", Request.Url.Authority));
    }

    //if unknown request
    return View();
  }
}

The project is still very much a work in progress and currently I’ve hard-coded parts to suit the demo report, but with a little more effort it could be completely dynamic. If you’re interested in the code I’m hosting it up on CodePlex with the cheeky name of Powerless View. Feel free to download and fork it. The only part that is missing from the project is the Power View Silverlight application itself – you’ll have to supply that.

I’d also like to point out that while this solution allows Power View to be hosted without SharePoint, we cannot get away from SharePoint completely as it’s still required to generate the initial .rdlx.

Power View – how it works: part 1

I’ve been meaning to check out Power View for a while now but with getting ready for my PASS Summit 2012 talk and PivotViewer (more on that soon) I haven’t had much spare time to dig deep into it.

Since I first saw it I was curious to know why it had so many dependencies – SharePoint 2010 (Enterprise), SSRS and SSAS, and how all those different systems are used to coordinate the rendering of a Power View report.

I’ve broken this little investigation up into a series of three posts which which I will cover:

  1. What is a Power View report and how does it fit with SharePoint, SSAS, SSRS and Sliverlight (this post).
  2. How to create a standalone version of Power View (without SharePoint and Reporting Services)
  3. If it’s possible to create a HTML5 equivalent of Power View that can be swapped-in and still use the existing web services.

What is an .rdlx?

Power View reports are based on a .rdlx file which is generated by SharePoint when you create a new Power View report. If you are interested in what makes up the internals of an .rdlx file then Dan English (blog|twitter) has already cracked one open - http://denglishbi.wordpress.com/2012/06/12/inside-the-power-view-rdlx.

As Dan discovers Power View reports are based on an .rdl file like Reporting Services, but with a slightly different xml schema. The .rdl file is then wrapped in a .zip file with the extension .rdlx – just like all the other office document files (as they are all based on the Open XML standard).

Contents of an .rdlx file

However if you are curious enough to try and run the .rdl file that is inside the Power View report in BIDS/SSDT you’ll be greeted with an error saying something like “The report definition is not valid or supported  by this version of Reporting Services”.

If you are not aware Power View reports are rendered by a Sliverlight application called Microsoft.Reporting.AdHoc.Shell.Bootstrapper.xap which comes in two flavours – one for SharePoint (version 11.0.2100.60), and another for Excel 2013 (version 11.0.2809.6).
The Sliverlight control that hosts Power View in SharePoint takes two key initialisation parameters. The first is ItemPath which is the path to the Power View .rdlx file on SharePoint. The second ReportServerUri is the path to the Reporting Services web service – located at /_vti_bin/reportserver/. There are a few other parameters but those two are the most important.

Loading a Power View report

When a Power View report is first requested it sends a request to the SSRS web service with the path to the .rdlx file (specified in the ItemPath parameter) and an rs:command parameter of GetReportAndModels. A typical first request would look something like this (parameters are URL encoded):

http://intranet/_vti_bin/reportserver/?http%3A%2F%2Fintranet%2FPowerPivot%20Gallery%2FReport.rdlx&rs:Command=GetReportAndModels

Reporting services then signals to SharePoint that the PowerPivot mode has been requested and then streams the model into the Analysis Services instance (in SharePoint integrated mode). SharePoint does this basically because it doesn’t understand what a tabular model is, and because Analysis Services is much better a processing and distributing the query load. What’s interesting about the relationship that SharePoint has with SSAS is that it’s only a temporary model, once it’s no longer in use a SharePoint timer process will come along and remove it from SSAS (which is why it gets such a horrible name).

After Cache

The reporting services web service then returns a response to Power View, it’s contents contain two parts – the binary .rdlx file and an xml document. The xml document contains all the data source connection details from the Power View report which (I assume) is so Power View can start requesting the datasets in one thread while it  extracts the contents of the .rdlx and builds the UI in the other. This is what’s happening when you see this kind of behaviour:

Report Waiting

Power View has finished rendering the report UI and is waiting for the asynchronous request to come back for the actual dataset.

Dataset requests use a different command of rs:RenderEdit, along with the current session id. Once the request had been processed  the reporting services web service then sends a binary response which contains the requested dataset back. A typical request looks like the following:

http://intranet/_vti_bin/reportserver/?rs:Command=RenderEdit&rs:ProgressiveSessionId=fe51a94b919c421380a57093caecb725y0y1yb552ckd2dbjqmmhpy45

In the next post I’m going to show how I’ve been able to host a Power View report outside of SharePoint and Reporting Services.


Roger Noble

Developer and Data Visualisation Consultant at Roger Noble Analytics
Follow me on Twitter
LinkedIn

Twitter