title: Web api rest service null reference exception thrown on first request
body: <p><strong>The Setup</strong></p>
  
  <p>We have a .net web api rest service that basically will render a web page as an image and attach that image to an email and send it to an address.  We pass the service a JSON email object that contains the from, to, subject, body, mailServerName, and html to render.  This service will be called a a lot, however, its the first call that gives the problem.</p>
  
  <p><strong>The problem</strong></p>
  
  <p>The first .net web api rest service request of the day always throws the following exception:</p>
  
  <blockquote>
    <p>Message: "An error has occurred.",  ExceptionMessage: "Object
    Reference not set to an instance of an object",  ExceptionType:
    "System.NullReferenceException", Stacktrace: "at<br>
    EmailService.Controllers.EmailController.Post(Email email) at<br>
    lambda_method(Closure, Object, Object[]) at ...</p>
  </blockquote>
  
  <p><strong>Note:</strong>  </p>
  
  <p><strong>After adding the custom exceptions below, the exception message is now the following:</strong>  </p>
  
  <blockquote>
    <p>ExceptionMessage: "Exception happened while saving Image to Jpeg stream"</p>
  </blockquote>
  
  <p><strong>Stacktrace:</strong></p>
  
  <blockquote>
    <p>at EmailService.Controllers.EmailController.Post(Email email) at<br>
    lambda_method(Closure, Object, Object[]) at
    System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.&lt;>c_DisplayClass10.b_9(Object
    instance,Object[] methodParameters) at 
    System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext
    controllerContext,IDictionary`2 arguments, CancellationToken
    cancellationToken) at
    System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Tasktask)
    at
    System.RuntimeCompilerServices.TaskAwaiter.HandleNonSuccessAnsDebuggerNotification(Task
    task)....</p>
  </blockquote>
  
  <p><strong>which is related to this line of code:</strong></p>
  
  <pre><code>websiteImage.Save(websiteStream, System.Drawing.Imaging.ImageFormat.Jpeg);
  </code></pre>
  
  <p>The service works fine after the first request in performed.  Again, its only after a long wait, typically until the next day, do we see the above exception thrown.</p>
  
  <p><strong>The Question</strong></p>
  
  <p>What is causing the service to throw the NullReferenceException and how can I fix it?</p>
  
  <p>The C# code for the controller class and the jQuery that performs the actual requst are below.</p>
  
  <p><strong>Controller class:</strong></p>
  
  <pre><code>namespace EmailService.Controllers
  {
  
      public class EmailController : ApiController
      {
  
          // POST api/email
          public HttpResponseMessage Post(Email email)
          {
  
              if (email == null)
              {
                  throw new Exception("Email parameter is null");
              }
  
              Bitmap websiteImage;
  
              try
              {
                  websiteImage = WebsiteToImage.Generate();
              }
  
              catch (Exception)
              {
  
                  // 500 Internal Server Error
                  response.StatusCode = HttpStatusCode.InternalServerError;
  
                  throw new Exception("Exception happened while generating Image");
              }
  
  
  
              // create memory stream from bitmap and save it as a jpeg, this allows us to attach the image from memory, without having to store it on the server
              System.IO.Stream websiteStream = new System.IO.MemoryStream();
              try
              {
                  websiteImage.Save(websiteStream, System.Drawing.Imaging.ImageFormat.Jpeg);
              }
  
  
              catch (Exception)
              {
  
                  // 500 Internal Server Error
                  response.StatusCode = HttpStatusCode.InternalServerError;
  
                  throw new Exception("Exception happened while saving Image to Jpeg stream");
              }
  
  
              try
              {
  
                  websiteStream.Position = 0;
              }
  
  
              catch (Exception)
              {
  
                  // 500 Internal Server Error
                  response.StatusCode = HttpStatusCode.InternalServerError;
  
                  throw new Exception("Exception happened while setting stream posiiton=0");
              }
  
  
              // create response with status code 200 OK, since we aren't actually creating anything 
              var response = this.Request.CreateResponse(HttpStatusCode.OK);
  
  
              try
              {
                  // MailMessage is used to represent the e-mail being sent
                  using (MailMessage message = new MailMessage(email.from, email.to, email.subject, email.body))
                  {
  
                      // attach jpeg from memory
                      message.Attachments.Add(new Attachment(websiteStream, "letter.jpg", "image/jpeg"));
  
                      // create mail client
                      SmtpClient mailClient = new SmtpClient(email.mailServerName);
  
                      // use the Windows credentials of the account (i.e. user account) 
                      mailClient.UseDefaultCredentials = true;
  
                      // send the message
                      mailClient.Send(message);
                  }
  
              }
              catch (Exception)
              {
  
                  // 500 Internal Server Error
                  response.StatusCode = HttpStatusCode.InternalServerError;
  
                  throw new Exception("Exception happened while creating and sending mail message");
  
              }
  
              //return new HttpResponseMessage() { Content = new StringContent(html) };
              return response;
  
          }
  
          // PUT api/email/5
          public HttpResponseMessage Put(int id, [FromBody]string value)
          {
              // return response status code of 501 Not Implemented
              return this.Request.CreateResponse(HttpStatusCode.NotImplemented);
          }
  
      }
  }
  </code></pre>
  
  <p><strong>Service request code:</strong></p>
  
  <pre><code>$.ajax ({
          type: "POST",
          url: "/api/email/",
          contentType: "application/json; charset=utf-8",
          data: JSON.stringify(email),
          success: finish,
          error: error
  
      });
  </code></pre>
  
  <p><strong>Global.asax</strong></p>
  
  <pre><code>   public class MvcApplication : System.Web.HttpApplication
      {
          protected void Application_Start()
          {
  
              // add details to server errors 
              GlobalConfiguration.Configuration.IncludeErrorDetailPolicy = IncludeErrorDetailPolicy.Always;
  
              AreaRegistration.RegisterAllAreas();
  
              WebApiConfig.Register(GlobalConfiguration.Configuration);
              FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
              RouteConfig.RegisterRoutes(RouteTable.Routes);
  
  
          }
      }
  </code></pre>
  
  <p><strong>WebApiConfig.cs</strong></p>
  
  <pre><code> public static class WebApiConfig
      {
          public static void Register(HttpConfiguration config)
          {
  
              config.Routes.MapHttpRoute(
                  name: "DefaultApi",
                  routeTemplate: "api/{controller}/{id}",
                  defaults: new { id = RouteParameter.Optional }
              );
          }
      }
  </code></pre>
  
  <p><strong>WebsiteToImage.cs</strong></p>
  
  <pre><code>public class WebsiteToImage
  {
      private Bitmap m_Bitmap;
      private string m_Url;
      private string m_FileName = string.Empty;
  
      private string m_html;
  
      public WebsiteToImage(string html)
      {
          // Without file 
          //m_Url = url;
  
          m_html = html;
  
      }
  
      public WebsiteToImage(string url, string fileName)
      {
          // With file 
          m_Url = url;
          m_FileName = fileName;
      }
  
      public Bitmap Generate()
      {
          // Thread 
          var m_thread = new Thread(_Generate);
          m_thread.SetApartmentState(ApartmentState.STA);
          m_thread.Start();
          m_thread.Join();
          return m_Bitmap;
      }
  
      private void _Generate()
      {
          WebBrowser browser = new WebBrowser { ScrollBarsEnabled = false };
          //browser.Navigate(m_Url);
          browser.DocumentText = m_html;
  
          browser.DocumentCompleted += WebBrowser_DocumentCompleted;
  
          while (browser.ReadyState != WebBrowserReadyState.Complete)
          {
              Application.DoEvents();
          }
  
          browser.Dispose();
      }
  
      private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
      {
          // Capture 
          var browser = (WebBrowser)sender;
          browser.ClientSize = new Size(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);
          browser.ScrollBarsEnabled = false;
          m_Bitmap = new Bitmap(browser.Document.Body.ScrollRectangle.Width, browser.Document.Body.ScrollRectangle.Bottom);
          browser.BringToFront();
          browser.DrawToBitmap(m_Bitmap, browser.Bounds);
  
          // Save as file? 
          if (m_FileName.Length &gt; 0)
          {
              // Save 
              m_Bitmap.SaveJPG100(m_FileName);
          }
      }
  }
  
  public static class BitmapExtensions
  {
      public static void SaveJPG100(this Bitmap bmp, string filename)
      {
          var encoderParameters = new EncoderParameters(1);
          encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
          bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
      }
  
      public static void SaveJPG100(this Bitmap bmp, Stream stream)
      {
          var encoderParameters = new EncoderParameters(1);
          encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
          bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
      }
  
      public static ImageCodecInfo GetEncoder(ImageFormat format)
      {
          var codecs = ImageCodecInfo.GetImageDecoders();
  
          foreach (var codec in codecs)
          {
              if (codec.FormatID == format.Guid)
              {
                  return codec;
              }
          }
  
          // Return 
          return null;
      }
  }
  </code></pre>
  
  <p><strong>Email.cs</strong></p>
  
  <pre><code>namespace EmailService.Models
  {
      public class Email
      {
          // email properties
          public string mailServerName {get; set;}
          public string from {get; set;}
          public string to {get; set;}
          public string subject {get; set;}
          public string body {get; set;}
          public string content { get; set; }
  
      }
  }
  </code></pre>