5

I am calling a method of which returns Task, in the calling method I need to read the response in form of string.

Here's the code that I have put:

static public async Task<HttpResponseMessage> Validate(string baseUri,HttpContent content) {
    HttpResponseMessage response = new HttpResponseMessage();   
    response = await client.PostAsync(baseUri,content);    
    return response;
}

public string test(){
    string postJson = "{Login = \"user\", Password =  \"pwd\"}";
    HttpContent stringContent = new StringContent(postJson, 
    UnicodeEncoding.UTF8, "application/json");
    HttpResponseMessage result=Validate(Uri,stringContent);
    var json = result.Content.ReadAsStringAsync().Result;
}

I expect string but this error is thrown:

Cannot implicitly convert type 
'System.Threading.Tasks.Task<System.Net.Http.HttpResponseMessage>' to 
'System.Net.Http.HttpResponseMessage'
wonea
  • 4,783
  • 17
  • 86
  • 139
Srikanth Yadake
  • 533
  • 2
  • 11
  • 25

4 Answers4

5

Your problem is at:

HttpResponseMessage result=Validate(Uri,stringContent);

Validate is returning a task, not a HttpResponseMessage.

Change that to:

var result = Validate(Uri,stringContent).Result;

Just to clean up the code a bit and avoid using Result if you can afford to change it like:

static public async Task<HttpResponseMessage> Validate(string baseUri, HttpContent content)
{  
   return await client.PostAsync(baseUri,content);
}

public async Task<string> test()
{
   var postJson = "{Login = \"user\", Password =  \"pwd\"}";
   var stringContent = new StringContent(postJson, UnicodeEncoding.UTF8, "application/json");
   var result = await Validate(Uri,stringContent);
   return await result.Content.ReadAsStringAsync();
}

Be consistent with your coding style. As to why calling .Result is bad, as people are pointing out in the comments, check this blog.

kovac
  • 4,945
  • 9
  • 47
  • 90
0
  1. Just for readability change the method name from Validate(..) to ValidateAsync(..). Just to make clear that this method returns a task and you have to await it.

  2. You're missing an await when calling your Validate method. If you do not want or can make the caller async then use the method GetAwaiter().GetResult() and you'll get what you want.

  3. Replace ReadAsStringAsync().Result with ReadAsStringAsync().GetAwaiter().GetResult()

Like others wrote in comments calling .Result is bad because it could cause locks. The same applies in general to GetAwaiter().GetResult() but calling them is preferred over calling Result. The best option is to use await/async.

When you want to know whats the difference between GetAwaiter().GetResult() vs calling Result you can read this: Is Task.Result the same as .GetAwaiter.GetResult()?

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
user743414
  • 936
  • 10
  • 23
0

Method Validate returns the task and is asynchronous. Basically you can call this method in two different ways:

1) await the result of Validate in another async method, like this...

public async Task<string> test() {
    string postJson = "{Login = \"user\", Password =  \"pwd\"}";
    HttpContent stringContent = new StringContent(postJson, 
        UnicodeEncoding.UTF8, "application/json");
    HttpResponseMessage result = await Validate(Uri,stringContent);
    var json = result.Content.ReadAsStringAsync().Result;
}

2) block current execution while waiting for this resul, like this...

public string test() {
    string postJson = "{Login = \"user\", Password =  \"pwd\"}";
    HttpContent stringContent = new StringContent(postJson, 
        UnicodeEncoding.UTF8, "application/json");
    HttpResponseMessage result = Validate(Uri,stringContent).Result;
    var json = result.Content.ReadAsStringAsync().Result;
}

Choose the 1st way by default unless you really have an urge to block the calling thread.

Note that when using 2nd solution in WinForms, WPF or ASP.NET apps you will probably have a deadlock. modifying Validate method like this should solve the problem:

response = await client.PostAsync(baseUri,content).ConfigureAwait(false);
Jacek
  • 829
  • 12
  • 31
0

You can easily write:

var json = result.Content.ReadAsStringAsync().GetAwaiter().GetResult();
Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • Why do you prefer this over the existing answers? The existing answers also use `Content.ReadAsStringAsync().`; the only difference is that you use `GetAwaiter().GetResult()` instead of e.g. `Result`. What's the value of that here? – Jeremy Caney Aug 12 '22 at 00:44