在第一次请求时抛出Web api rest服务空引用异常

本文关键字:服务 rest 引用 异常 api Web 请求 第一次 | 更新日期: 2023-09-27 18:02:45

设置

我们有一个。net web api rest服务,基本上将渲染一个网页作为一个图像,并将该图像附加到电子邮件,并将其发送到一个地址。我们向该服务传递一个JSON电子邮件对象,该对象包含from、to、subject、body、mailServerName和要呈现的html。这个服务会被调用很多次,但是,它是第一次调用时出现问题的。

一天中的第一个。net web api rest服务请求总是抛出以下异常:

Message: "An error has occurred.", ExceptionMessage: "Object .引用未设置为对象的实例",ExceptionType:"系统。NullReferenceException", Stacktrace: "at
EmailService.Controllers.EmailController。邮件地址:
lambda_method(Closure, Object, Object[]) at…

注意:

在添加了下面的自定义异常之后,异常消息现在如下:

ExceptionMessage: "保存图像到Jpeg流时发生异常"

异常堆栈

:

在EmailService.Controllers.EmailController

。邮件地址:
lambda_method(Closure, Object, Object[]System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor灵活;> c_DisplayClass10.b_9(对象实例,对象[]方法参数)System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync (HttpControllerContextcontrollerContext,字典的两个参数,CancellationTokencancellationToken)System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess (Tasktask)在System.RuntimeCompilerServices.TaskAwaiter.HandleNonSuccessAnsDebuggerNotification(任务任务)…

与这行代码有关:

websiteImage.Save(websiteStream, System.Drawing.Imaging.ImageFormat.Jpeg);

服务在执行第一个请求后工作正常。同样,只有在长时间等待之后,通常直到第二天,我们才会看到上述异常被抛出。

是什么导致服务抛出NullReferenceException,我该如何修复它?

控制器类的c#代码和执行实际请求的jQuery在下面。

控制器类:

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);
        }
    }
}

服务请求代码:

$.ajax ({
        type: "POST",
        url: "/api/email/",
        contentType: "application/json; charset=utf-8",
        data: JSON.stringify(email),
        success: finish,
        error: error
    });

Global.asax

   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);

        }
    }

WebApiConfig.cs

 public static class WebApiConfig
    {
        public static void Register(HttpConfiguration config)
        {
            config.Routes.MapHttpRoute(
                name: "DefaultApi",
                routeTemplate: "api/{controller}/{id}",
                defaults: new { id = RouteParameter.Optional }
            );
        }
    }

WebsiteToImage.cs

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 > 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;
    }
}

Email.cs

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; }
    }
}

在第一次请求时抛出Web api rest服务空引用异常

从我一直在阅读的一切看来,在ASP中使用单线程公寓状态(STA)存在一些问题。网络应用程序。请查看这里的文章,其中描述了作者如何能够解决这些问题。

我还不能确定为什么这种行为只发生在你的第一个请求。

可以在这里和这里找到更多的资源。我希望这对你有帮助!

尝试更改您的生成方法(假设m_Bitmap已在该类的其他地方构造):

public Bitmap Generate()
{
    return m_Bitmap;
}