Reputation: 552
I have an async function which is used to send request message to a server. The function is like following:
class http
{
public async Task<string> HttpRequest()
{
HttpRequestMessage request = GetHttpRequestMessage();
var str1 = await ExecuteRequest(request);
return str1;
}
private async Task<string> ExecuteRequest(HttpRequestMessage request)
{
string result = string.Empty;
try
{
using (HttpClient client = new HttpClient())
{
var responses = await client.SendAsync(request);
responses.EnsureSuccessStatusCode();
result = await responses.Content.ReadAsStringAsync();
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
return result;
}
private const string _DataTypeJson = @"application/json";
private HttpRequestMessage GetHttpRequestMessage()
{
Dictionary<string, string> headers = GetHeadersUsedForToken();
string str = "https://test.com//tokens";
Uri uri = new Uri(str);
HttpRequestMessage request = new HttpRequestMessage
{
RequestUri = uri,
};
if (null != headers)
{
foreach (string key in headers.Keys)
{
request.Headers.Add(key, headers[key]);
}
}
// Hard code Accpt type is Json
request.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue(_DataTypeJson));
request.Method = HttpMethod.Get;
return request;
}
private Dictionary<string, string> GetHeadersUsedForToken()
{
return new Dictionary<string, string>
{
{ "id", "abc" },
{ "secret", "***" }
};
}
}
This function works fine in console project, but when I try to move this function to WCF service, and try to call HttpRequest()
function in service,
[ServiceContract]
public interface IService1
{
[OperationContract]
Task<string> GetData();
}
public class Service1 : IService1
{
public Task<string> GetData()
{
http test = new http();
return test.HttpRequest();
}
}
Exception was thrown:
Message An error occurred while sending the request.
InnerException {"The underlying connection was closed: An unexpected error occurred on a send."}
Upvotes: 0
Views: 3302
Reputation: 247163
With async/await you need to make it async all the way through.
Make the service a Task-based asynchronous service
[ServiceContract]
public interface IService1 {
[OperationContract]
Task<string> GetData();
}
With that, it is a simple matter of making the rest of the code async all the way through.
public class http {
public async Task<string> HttpRequestAsync() {
var request = GetHttpRequestMessage();
string str1 = await ExecuteRequest(request);
Console.WriteLine(str1);
return str1;
}
//...code removed for brevity as they are already Task-based
}
This should now allow the function to be used in the service implementation
public class Service1 : IService1 {
public Task<string> GetData() {
http test = new http();
return test.HttpRequestAsync();
}
}
In the original example provided the code was mixing async and blocking calls .Result
, which can lead to deadlocks
Reference Async/Await - Best Practices in Asynchronous Programming
I would also advise making the HttpClient
static and reuse it rather than creating multiple instances and disposing of them.
UPDATE:
Another possibility is that the URL being called is HTTPS.
Consider applying the following before making the request via the HttpClient
//Handle TLS protocols
System.Net.ServicePointManager.SecurityProtocol =
System.Net.SecurityProtocolType.Tls
| System.Net.SecurityProtocolType.Tls11
| System.Net.SecurityProtocolType.Tls12;
Upvotes: 2