【问题标题】:System.InvalidOperationException: This operation cannot be performed after the request has been submittedSystem.InvalidOperationException:提交请求后无法执行此操作
【发布时间】:2020-06-04 21:04:08
【问题描述】:

这个问题可能已经被问过很多次了,但他们的solution 没有一个真正有帮助。

我正在使用 OneSignal 向所有连接的客户端发送推送通知。我在服务中实现了代码并将其设为单例。

我想要什么
我的用例是我想向用户发送通知,并立即向另一个用户发送不同的通知。

问题
它仅适用于第一个请求,之后,我不断收到此错误:

System.InvalidOperationException: This operation cannot be performed after the request has been submitted.
   at System.Net.HttpWebRequest.InternalGetRequestStream()
   at System.Net.HttpWebRequest.GetRequestStream()
   at BingoAPI.Services.NotificationService.SendNotificationAsync(Byte[] buffer) in D:\Bingo\BingoAPI\Services\NotificationService.cs:line 74

这里是实现:

public NotificationService(IOptions<OneSignalNotificationSettigs> oneSignalSettings, IOptions<NotificationTemplates> notificationTemplates)
        {
            this.oneSignalSettings = oneSignalSettings;
            this.notificationTemplates = notificationTemplates;

            // request configuration
            request = WebRequest.Create(oneSignalSettings.Value.EndPoint) as HttpWebRequest;
            request.Headers.Add("authorization", oneSignalSettings.Value.Authorization);
            request.KeepAlive = true;
            request.Method = "POST";
            request.ContentType = "application/json; charset=utf-8";

        }

        private async Task SendNotificationAsync(byte[] buffer)
        {
            string responseContent = null;
            try
            {
                // here is the error
                var writer = await request.GetRequestStreamAsync();
                await writer.WriteAsync(buffer, 0, buffer.Length);
                writer.Close();

                var response = await request.GetResponseAsync() as HttpWebResponse;
                var reader = new StreamReader(response.GetResponseStream());
                responseContent = await reader.ReadToEndAsync();
            }
            catch (WebException ex)
            {
               // LOGGING
            }
        }

    }

【问题讨论】:

  • 我不得不提一下,我尝试将此服务添加为 Transient,并且成功了。但是,我认为这不是一个长期的解决方案,因为必须为每个请求重新初始化
  • 我知道这不是一个直接的答案,但是当您使用 asp net core 时,我建议您通过 IHttpClientFactory 使用 HttpClient 并使用依赖注入。

标签: c# asp.net asp.net-mvc asp.net-core onesignal


【解决方案1】:

据我所知,Singleton 意味着应用程序的每个后续请求都使用相同的实例。

这意味着所有两个请求都使用相同的HttpWebRequest

由于您的 SendNotificationAsync 是异步方法。如果你同时调用这个方法两次。它将使用相同的HttpWebRequest(request) 发送请求。

错误告诉你,第一个HttpWebRequest(request)已提交,但未执行完成,我们无法再次提交HttpWebRequest(request)

在我看来,您应该将服务注册为Transient,因为我们不能重复使用HttpWebRequest(request)

【讨论】:

    【解决方案2】:

    我最终使用了 HttpClientFactory 而不是 HttpWebRequest,尽管我可以让它暂时化。但从长远来看,这对我来说似乎不是一个解决方案,因为每个请求都必须重新初始化很多额外的东西。而且代码更少。

    public NotificationService(IOptions<OneSignalNotificationSettigs> oneSignalSettings, IOptions<NotificationTemplates> notificationTemplates,
                                       IHttpClientFactory clientFactory)
            {
                this.oneSignalSettings = oneSignalSettings;
                this.notificationTemplates = notificationTemplates;
    
                // request configuration
                httpClient = clientFactory.CreateClient();
                httpClient.DefaultRequestHeaders.Add("authorization", oneSignalSettings.Value.Authorization);
                request = new HttpRequestMessage(HttpMethod.Post, oneSignalSettings.Value.EndPoint);           
            }
    
            private async Task SerializeNotificationAsync(Object obj)
            {            
                var param = JsonConvert.SerializeObject(obj);
                var data = new StringContent(param, Encoding.UTF8, "application/json");
                await SendNotificationAsync(data);                                                
            }
    
    
            private async Task SendNotificationAsync(StringContent buffer)
            {            
                var response = await httpClient.PostAsync(request.RequestUri, buffer);
    
                if (!response.IsSuccessStatusCode)
                {
                    // logg error
    
                }
            }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 2016-02-08
      • 2020-08-16
      • 2023-03-03
      • 2019-10-01
      • 2021-03-28
      相关资源
      最近更新 更多