1

I am trying to create a web site using ASP.NET (C#) and MVC. I have searched everywhere for an answer and am hoping for some help here.

Ideas and some code taken from: http://www.codecapers.com/post/Build-a-Dashboard-With-Microsoft-Chart-Controls.aspx

I was able to make the above work with a simple MVC project and bogus data.

I am trying to display a chart in a Partial View and keep getting the following error: Object reference not set to an instance of an object

I am not sure why I am getting this. When debugging, the list shows that it has the one chart in it. I am also able to print out information about the chart (i.e. height, width) that were set in the model. I just cannot render it in the partial view. Creating the chart as an image will not be useful to me.

Thanks in advance for your help!

I don't think it has anything to do with web.config but will include it anyways:

web.config

    <configuration>
      <appSettings>
        <add key="ChartImageHandler" value="Storage=file;Timeout=20;Url=/tempImages/;"/>
      </appSettings>
      <system.web>
      <httpHandlers>
         <add verb="GET,HEAD,POST" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" validate="false"/>
      <add verb="GET,HEAD,POST" path="Reserved.ReportViewerWebControl.axd" type="Microsoft.Reporting.WebForms.HttpHandler,     Microsoft.ReportViewer.WebForms, Version=9.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"   />
    </httpHandlers>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.Mvc, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
        <add assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"/>
      </assemblies>
    </compilation>
    <authentication mode="Forms">
      <forms loginUrl="~/Account/LogOn" timeout="2880"/>
    </authentication>
    <pages>
      <namespaces>
        <add namespace="System.Web.Mvc"/>
        <add namespace="System.Web.Mvc.Ajax"/>
        <add namespace="System.Web.Mvc.Html"/>
        <add namespace="System.Web.Routing"/>
      </namespaces>
      <controls>
        <add tagPrefix="asp" namespace="System.Web.UI.DataVisualization.Charting" assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
      </controls>
    </pages>
  </system.web>
  <system.webServer>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules runAllManagedModulesForAllRequests="true"/>
    <handlers>
      <remove name="ChartImageHandler"/>
      <add name="ChartImageHandler" preCondition="integratedMode" verb="GET,HEAD,POST" path="ChartImg.axd" type="System.Web.UI.DataVisualization.Charting.ChartHttpHandler, System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"/>
    </handlers>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0" newVersion="2.0.0.0"/>
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

Controller

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using Dashboard.WebUI.Models;

namespace Dashboard.WebUI.Controllers
{
    public class DashboardController : Controller
    {
        //
        // GET: /Dashboard/

        public ActionResult Index()
        {
            //LineSummaryModel model = new LineSummaryModel();
            PieChartModel model = new PieChartModel();
            return View(model);
        }

    }
}

Model

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI.DataVisualization;
using System.Web.UI.DataVisualization.Charting;

namespace Dashboard.WebUI.Models {
    public class PieChartModel {
        public PieChartModel() {
        }

        internal class PieChartData {
            public String Title { get; set; }
            public String[] Data { get; set; }
            public double[] xValues { get; set; }
            public double[] yValues { get; set; }
        }

        private Chart BuildServerPieChart() {
            String[] temp = { "France", "Canada", "Germany", "USA", "Italy" };
            double[] x = {1.0, 2.3, 4.5, 5.5, 5.6 };
            double[] y = {1.0, 2.0, 3.0, 4.0, 5.0 };

            PieChartData data = new PieChartData {
                Title = "Test Server",
                Data = temp,
                xValues = x,
                yValues = y
            };

            return BindChartData(data);
        }

        private Chart BindChartData(PieChartData data) {
            Chart chart = new Chart();
            chart.Width = 150;
            chart.Height = 300;
            chart.Attributes.Add("align", "left");

            chart.Titles.Add(data.Title);
            chart.ChartAreas.Add(new ChartArea());

            chart.Series.Add(new Series());

            chart.Legends.Add(new Legend("Countries"));
            chart.Legends[0].TableStyle = LegendTableStyle.Auto;

            chart.Legends[0].Docking = Docking.Bottom;

            chart.Series[0].ChartType = SeriesChartType.Pie;

            for(int i = 0; i < data.xValues.Length; i++){
                double x = data.xValues[i];
                double y = data.yValues[i];

                int ptIdx = chart.Series[0].Points.AddXY(x, y);
                var c = data.Data[i];

                DataPoint pt = chart.Series[0].Points[ptIdx];
                pt.ToolTip = c + ""+ x;
            }
            chart.Series[0].Legend = "Countries";
            return chart;
        }

        public List<Chart> PieCharts {
            get {
                List<Chart> charts = new List<Chart>();
                charts.Add(BuildServerPieChart());
                return charts;
            }
        }


    }
}

Master Page (Partial)

<!-- CONTENT -->
                    <div id="fps-main" style="width: 100%">
                        <div>
                            <asp:ContentPlaceHolder ID="LineSummary" runat="server">
                            </asp:ContentPlaceHolder>
                        </div>
                        <div>
                            <asp:ContentPlaceHolder ID="MiddleRow" runat="server">
                            </asp:ContentPlaceHolder>
                        </div>
                        <div>
                            <asp:ContentPlaceHolder ID="BottomRow" runat="server">
                            </asp:ContentPlaceHolder>
                        </div>
                    </div>
                    <!-- //CONTENT -->

Index.aspx

<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Dashboard.Master" Inherits="System.Web.Mvc.ViewPage<dynamic>" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>
<asp:Content  ContentPlaceHolderID="TopSpotLight" runat="server">
    <% Html.RenderPartial("TopSpotlight"); %>
</asp:Content>
<asp:Content ID="Content2" ContentPlaceHolderID="LineSummary" runat="server">
     <% Html.RenderPartial("LineSummary"); %>
</asp:Content>
<asp:Content ID="Content3" ContentPlaceHolderID="BottomRow" runat="server">
    <h2>Section 3</h2>
</asp:Content>

Parital View (Line Summary.ascx)

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Dashboard.WebUI.Models.PieChartModel>" %>
<%@ Register Assembly="System.Web.DataVisualization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
Namespace="System.Web.UI.DataVisualization.Charting" TagPrefix="asp" %>

    <h2>Line Summary</h2>
    <%
        //Error Occurs here but I don't think this is the problem
        foreach (Chart chart in Model.PieCharts) {

            try {

                //In this section, I tried to render the control a couplie
                //different ways. Neither worked.
                PieSummaryChartPanel.Controls.Add(chart);
                //This prints out the correct height I set in model
                Response.Write(chart.Height + "<br />");
                HtmlTextWriter writer = new HtmlTextWriter(Page.Response.Output);
                chart.RenderControl(writer);

            } catch (System.NullReferenceException e) {
                Response.Write("ERROR:  " + e.Message);
            }

        }

            //Response.Write("Test " + LineSummaryChartPanel.BorderWidth.Value);
        //}
    %>

    <asp:Panel ID="PieSummaryChartPanel" runat="server"></asp:Panel>

I am not sure why, if it is null, I can print out the properties of the object. Thanks for your help.

Server Error in '/' Application.
    Object reference not set to an instance of an object.
    Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

    Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.

    Source Error:

    Line 11:         
    Line 12: 
    Line 13:         foreach (Chart chart in Model.PieCharts) {
    Line 14:             //if (chart != null && PieSummaryChartPanel != null) {
    Line 15:                // try {


    Source File: c:\Users\Scott\Documents\Projects\Visual Studio 2010\Projects\DashboardSolution\Dashboard.WebUI\Views\Shared\LineSummary.ascx    Line: 13

    Stack Trace:

    [NullReferenceException: Object reference not set to an instance of an object.]
       System.Web.UI.DataVisualization.Charting.ChartHttpHandler.GetHandlerUrl() +96
       System.Web.UI.DataVisualization.Charting.ChartHttpHandler.GetUrl(String query, String fileKey, String currentGuid) +32
       System.Web.UI.DataVisualization.Charting.ChartHttpHandler.GetChartImageUrl(MemoryStream stream, String imageExt) +339
       System.Web.UI.DataVisualization.Charting.Chart.Render(HtmlTextWriter writer) +420
       System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
       System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208
       System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
       System.Web.UI.WebControls.WebControl.RenderContents(HtmlTextWriter writer) +10
       System.Web.UI.WebControls.WebControl.Render(HtmlTextWriter writer) +32
       System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
       ASP.views_shared_linesummary_ascx.__Render__control1(HtmlTextWriter __w, Control parameterContainer) in c:\Users\Scott\Documents\Projects\Visual Studio 2010\Projects\DashboardSolution\Dashboard.WebUI\Views\Shared\LineSummary.ascx:13
       System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +109
       System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
       System.Web.UI.Control.Render(HtmlTextWriter writer) +10
       System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
       System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208
       System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8
       System.Web.UI.Page.Render(HtmlTextWriter writer) +29
       System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +56
       System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100
       System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25
       System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3060
tereško
  • 58,060
  • 25
  • 98
  • 150
ScottCollier
  • 373
  • 3
  • 10
  • possible duplicate of [What is a NullReferenceException in .NET?](http://stackoverflow.com/questions/4660142/what-is-a-nullreferenceexception-in-net) – John Saunders Oct 07 '11 at 01:11
  • I added the following to check for null objects inside the for loop in LineSummary.ascx. if(chart != null && PieSummaryChartPanel != null){ ... try catch block here } So, I don't think it is a duplicate of the above. I am guessing that it has something to do with Partial views. I am new to MVC though. – ScottCollier Oct 07 '11 at 14:26
  • There is exactly one reason for `NullReferenceException` - somebody didn't set something before using it. What's the line the exception happens on? Post the complete exception. – John Saunders Oct 07 '11 at 15:21
  • This is a hard one. Something you've done has caused the code you _call_ to throw a `NullReferenceException`. That's much harder to debug. I'm only guessing, but it's failing when it tries to find the handler. Check your web.config to see if you have the handler for the chart controls configured correctly. – John Saunders Oct 07 '11 at 16:30
  • I am highly suspicious of your Model creating controls. The innocent-looking act of enumerating part of your model is actually creating UI controls – John Saunders Oct 07 '11 at 16:32
  • I have this working in a test project that uses master pages but does not use partial views. And, except for using partial views, it uses same controller and model code. This is only suppose to show one chart but eventually it will show several. That is the reason for enumerating and creating the controls. I will double check web.config again just to make sure. – ScottCollier Oct 07 '11 at 16:47
  • Just because it works in one case doesn't mean it's a good idea, or that it won't break the next time you make a change. This is a violation of separation of concerns, as well. The model should hold the information that will be used to create the chart, but should not know how to create the chart. I would move all of that chart creation code into the partial view. – John Saunders Oct 07 '11 at 16:51
  • You are right. I am just trying to throw something together as a quick mockup. I will work on breaking it out correctly. – ScottCollier Oct 07 '11 at 18:24
  • You are using the Attributes and Titles properties without initialising them. Does the constructor initialise these? – jhsowter Feb 09 '12 at 03:35

1 Answers1

2

I'm not quite sure if your problem is the same as mine, but I've come across this problem too. For me it turned out that at some point during rendering of the chart the ChartHttpHandler calls its (private) static GetHandlerUrl() method which contains the following line:

string str = Path.GetDirectoryName(HttpContext.Current.Request.CurrentExecutionFilePath ?? "").Replace(@"\", "/");

Unfortunately for me (and possibly you) the way my URL rewriting code works the value for 'HttpContext.Current.Request.CurrentExecutionFilePath' can sometimes be '/' and Path.GetDirectoryName() returns null for '/'.

Since they decided to smack a .Replace() straight to the result of the GetDirectoryName() result you end up with a nasty NullReferenceException.

For me the solution was to just make sure there's never a chart on the root page of the site... yeah, really... (Did win me an 'ugliest workaround of the year'-prize though)

Robba
  • 7,684
  • 12
  • 48
  • 76