Search code examples
javascriptasp.net-mvcweb-servicesrazorshieldui

Using Shield Chart in ASP.NET MVC to bind to web service data


For a new project I'm working on, I am considering using Shield Chart for ASP.NET MVC to display some user stats. I have successfully rendered a shield javascript chart from my razor view using the Html.ShieldChart() wrapper methods. The actual data for the chart is coming from a local rest service in JSON format. The thing is, I can't quite manage to make the chart display the JSON data. The Shield UI demos show one approach for binding the MVC chart to remote web service, but my scenario is quite different.

In our web portal, we have implemented a REST service under url /api/users/12652/stats that will return some JSON stats for a user with the given ID. The responsone contains the sessions property that lists the user's sessions for the current month:

{
    sessions: [{ start: 1379624400000, end: 1377023690271 }, { ... }]
}

The difference between start and end times gives the duration of the session.I need to display a bar chart that will show the duration of all sessions in a line on the Y axis, while the X axis will contain all session dates (taken from the start value).


Solution

  • Something like this should get you going:

    <div id="chart"></div>
    
    <script type="text/javascript">
    $(function () {
        $.get("/api/users/12652/stats", function (data) {
            var sessions = sessions;
    
            @(Html.ShieldChart()
                .Name("chart")
                .PrimaryHeader(header => header.Text("User session duration (in minutes)"))
                .DataSeries(series => series.Bar()
                    .Data(@<text>
                        (function () {
                            return $.map(sessions, function (item) {
                                //return the difference between the end and start time in minutes
                                return (item.end - item.start) / 1000 / 60;
                            });
                        })()
                    </text>))
                .GetScript())
        });
    });
    </script>
    

    Note how the Shield Chart is defined using a Razor server expression inside the javascript callback from the service request. We do this, because we need the session variable to contain the actual data returned from the service. Then we can use a self-calling function in a <text></text> template as a parameter to the series' .Data() method in MVC.This has the effect of rendering a self-calling function expression in the javascript initialization options that helps us map the service response to series data options.

    Note the last .GetScript() method call. We use it to render only the initialization script of the chart widget and not the entire widget markup and scripts. This allows the widget to be initialized in javascript code in your HTML page.

    For binding the X axis categorical values to the service response, however, you do not have a similar approach with the @<text></text> template available. For this case, it is best to use pure javascript initialization:

    $(function() {
      $("#chart").shieldChart({
        primaryHeader: {
          text: "User session duration (in minutes)"
        },
        dataSeries: [{
          seriesType: 'bar',
          data: $.map(sessions, function(item) {
            return (item.end - item.start) / 1000 / 60;
          })
        }],
        axisX: {
          axisType: "datetime",
          dataStart: sessions[0].start,
          categoricalValues: $.map(sessions, function(item) {        
            return new Date(item.start);
          })
        }
      });
    });
    

    Here is a JSBin of the above scenario with some hard-coded data just to concentrate on the chart initialization.