在ASP.NET 4.7.2中使用SendAsync()函数时,mscorlib.dll引发“System.NullReferenceException”

kqlmhetl  于 2023-10-21  发布在  .NET
关注(0)|答案(4)|浏览(181)

我有一个Web应用程序(ASP.NET 4.7.2,C#)。我正在使用HttpClient向WebService发送POST请求。当执行此response = await client.SendAsync(request);时,
它抛出An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll
我把它 Package 在一个try/catch上,但是这个异常没有被捕获。

完全相同的代码在WinForms应用程序和控制台项目上完美工作(!!).

下面是我得到的例外

at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
   at System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
   at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task& currentTask)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.AwaitTaskContinuation.<>c.<ThrowAsyncIfNecessary>b__18_0(Object s)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</StackTrace><ExceptionString>System.NullReferenceException: Δεν έχει οριστεί αναφορά αντικειμένου at μια παρουσία αντικειμένου.
   at System.Web.ThreadContext.AssociateWithCurrentThread(Boolean setImpersonationContext)
   at System.Web.HttpApplication.OnThreadEnterPrivate(Boolean setImpersonationContext)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallbackPossiblyUnderLock(SendOrPostCallback callback, Object state)
   at System.Web.LegacyAspNetSynchronizationContext.CallCallback(SendOrPostCallback callback, Object state)
   at System.Web.LegacyAspNetSynchronizationContext.Post(SendOrPostCallback callback, Object state)
   at System.Threading.Tasks.SynchronizationContextAwaitTaskContinuation.PostAction(Object state)
   at System.Threading.Tasks.AwaitTaskContinuation.RunCallback(ContextCallback callback, Object state, Task&amp;amp; currentTask)
--- End of stack trace from previous location ---
   at System.Threading.Tasks.AwaitTaskContinuation.&amp;lt;&amp;gt;c.&amp;lt;ThrowAsyncIfNecessary&amp;gt;b__18_0(Object s)
   at System.Threading.QueueUserWorkItemCallback.WaitCallback_Context(Object state)
   at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
   at System.Threading.ThreadPoolWorkQueue.Dispatch()
   at System.Threading._ThreadPoolWaitCallback.PerformWaitCallback()</ExceptionString></Exception></TraceRecord>
An unhandled exception of type 'System.NullReferenceException' occurred in mscorlib.dll

这是精简后的代码

public async Task<bool> SendPostRequestAsync()
{
    string endpoint = "endpointname";
    url = endpointUrl;
    var client = new HttpClient();
    var queryString = HttpUtility.ParseQueryString(string.Empty);

    // adding Request headers for authentication
    client.DefaultRequestHeaders.Add(...);
    client.DefaultRequestHeaders.Add(...);
    var uri = url + endpoint + "?" + queryString;

    HttpResponseMessage response = new HttpResponseMessage();

    byte[] byteData = Encoding.UTF8.GetBytes(bodyxml);
    using (var content = new ByteArrayContent(byteData))
    {
        try
        {
            Uri myUri = new Uri(uri, UriKind.Absolute);
            HttpRequestMessage request = new HttpRequestMessage
            {
                Method = HttpMethod.Post,
                RequestUri = myUri,
                Content = content
            };

            content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
            
            //this is to check if there nothing is null for the action
            bool iAmOk = ((client != null) && (response != null) && (url != null) && (request != null) && (bodyxml != null));
            if (!iAmOk) { return false; }
            
            try
            {
               response = await client.SendAsync(request);
               //here throws the exception
            }
            catch (Exception ex)
            {
                string msg = ex.Message;
                //it never goes here
            }
            var contents = response.Content.ReadAsStringAsync().Result;
            
            if (response.StatusCode == HttpStatusCode.OK)
            {
                // the call is successfull
                return true;
            }
            else
            {
                _log.Error("errordata");
                //the call is not successfull
                return false;
            }
        }
        catch (Exception exx)
        {
            //it doesn't go neither here
            _log.Error("exceptiondata");
            return false;
        }
   }
}

我正在使用

  • Microsoft Visual Studio Community 2019版本16.11.29
  • ASP.NET和Web Tools 2019 16.11.116.46506
  • ASP.NET Web框架和工具2019 16.11.116.46506
  • .Net Framework 4.7.2

是应用程序类型的问题吗?或与一些图书馆??(找到了this post,看起来很相似,但还没有任何答案。任何输入将不胜感激!

ct3nt3jp

ct3nt3jp1#

代码中的一个潜在问题是,在进行异步调用之前初始化HttpResponseMessage变量response,然后尝试从它读取。但是,由于异常是在SendAsync调用期间抛出的,因此response在此时可能仍然是null
您可以在进行异步调用之前,尝试在try块中初始化response。这可以确保当您尝试访问它时,它不是null
Eg.

//...

HttpResponseMessage response = null; // Initialize to null here

byte[] byteData = Encoding.UTF8.GetBytes(bodyxml);
using (var content = new ByteArrayContent(byteData))
{
     try
     {
        //...

        // Initialize response here
        response = await client.SendAsync(request);

        //...
    }
    catch (Exception ex)
    {
        string msg = ex.Message;
    }
    //...
}
egdjgwm8

egdjgwm82#

由于这个异常来自System.Threading命名空间,我假设是因为xrc/awaits有问题。而且,每个框架都有不同的线程管理(更准确地说,* 同步上下文 *),代码在CLI和WinForms中正常工作,而在ASP.NET上失败并不奇怪
在你的代码中,有一种代码气味,这是非常可疑的:

var contents = response.Content.ReadAsStringAsync().Result;

这是一个异步方法中的同步等待-一个大禁忌。根据此方法的内部实现以及同步上下文在ASP.NET中的工作方式,它可能会导致死锁或其他故障。请在JavaScript方法中使用await call:

var contents = await response.Content.ReadAsStringAsync();

我希望这将解决这个问题

0pizxfdo

0pizxfdo3#

我把它 Package 在一个try/catch上,但是这个异常没有被捕获。
这几乎总是由于在抛出异常的点之上的调用链中的某个地方错过了await而导致的。try { .. } catch { .. }async方法中无法工作或断点,如果调用链 * 上面 * 中的任何内容没有正确执行await
我会从调用堆栈开始,并四重检查你没有意外地错过await在某个地方的任务。你经常会意识到你传递了一个Task<T>而不是T到一个泛型方法中。
常见的例子是,当你执行类似Deserialize(someObject)的操作时,你可能会意外地将Task<YourClass>而不是YourClass传入that方法,因为该方法只接受泛型object,所以它不会抛出编译器异常。
但是当您运行代码时,您会遇到问题,异常无法捕获,一切都中断了,因为您的Task没有得到await的艾德

yi0zb3m4

yi0zb3m44#

谢谢大家的建议。每个人都帮助我更好地理解我的问题。
经过几天的努力,我想通了。
在我的.aspx文件中,我有一个触发整个过程的按钮:

<asp:LinkButton runat="server" ID="button1" data-uk-tooltip="{pos:'left'}" title="start posting data" OnClick="button1_Click" class="md-fab md-fab-accent md-fab-wave"  >
             <i class="material-icons">cloud_upload</i>
 </asp:LinkButton>

protected void button1_ClickAsync(object sender, EventArgs e)里面有这样的代码

_ = myClass.RunSendAsync(var1,var2);

这是调用public async Task<bool> SendPostRequestAsync()(从我的问题),但我可以理解,这并没有等待SendPostRequestAsync()。
尝试这些:
1.将项目更新到.NET Framework 4.8 -没有太大变化
1.从.NET临时文件夹中清理临时文件,清理解决方案并重建-无任何更改
1.在进行异步调用之前,在try块内初始化响应-仍然得到错误
1.将var contents = response.Content.ReadAsStringAsync().Result;更改为var contents = await response.Content.ReadAsStringAsync();-仍然出现相同的错误
1.将button1_ClickAsync更改为cxdc-我得到了一个编译器错误“The button1_ClickAsync has a wrong return type”
最后,我将LinkButton更改为anchor,然后从jQuery Ajax进行了xmlc调用

$("#button1").click(function () {
    
    $.ajax({
            type: 'POST',
            contentType: "application/json; charset=iso-8859-7",
            url: 'myurl/asyncmethod()',
            async: true,
            data: "{'var1':'value1'}",
            success: function (response) { //dothings
                },
            error: function (xhr) {
                    console.log(xhr.responseText);
                }
            });
});

并在我的.cs文件中创建了一个新的WebMethod,它调用并等待myClass.RunSendAsync(var1,var2);

[WebMethod]
public static async void myAsyncMethod(string var1)
{
  //...
  await myClass.RunSendAsync(var1,var2);
  // ...
 }

这就像一个魅力!
更新:
当我将WebMethod的返回类型从void更改为Task<List<Results>>并在response = await client.SendAsync(request);之后进行调试时,它只是停止并不继续。
那里能有什么问题吗

相关问题