1

I want to be able to receive the Body content of a POST request inside the POST function definition in the REST API.

I have a client code that converts a C# object into JSON and then wraps it in a HTTP StringContent. This payload is then sent via a HTTP Post request to the URL. However the Post method in API always returns NULL when I try returning the received string.

Client:

public async void Register_Clicked(object sender, EventArgs e) // When user enters the Register button
{
 Sjson = JsonConvert.SerializeObject(signup);   
 var httpContent = new StringContent(Sjson);    
 using (HttpClient client = new HttpClient())
     {
        client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
        var response =  await client.PostAsync("api/values", httpContent);    
        var responseContent =  await response.Content.ReadAsStringAsync();

        StatusLabel.Text = responseContent; //To display response in client
     }
}

API POST Definition:

[SwaggerOperation("Create")]
[SwaggerResponse(HttpStatusCode.Created)]
public string Post([FromBody]string signup)
{
      return signup;
}

I want the clients input back as a response to be displayed in the client (StatusLabel.Text). However all I receive is NULL. Kindly guide me in the right direction.

Gowthaman
  • 59
  • 9
  • Possible duplicate of [How to make HTTP POST web request](https://stackoverflow.com/questions/4015324/how-to-make-http-post-web-request) – Gergő Gutyina Apr 30 '19 at 08:26
  • You would have to get the result of your Task. `var responseContent = await response.Content.ReadAsStringAsync().Result;` – Rahul Sharma Apr 30 '19 at 08:26
  • @Rahul Sharma when I added '.Result' it triggered the following error: 'string' does not contain a definition for 'GetAwaiter' and no accessible extension method 'GetAwaiter' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference?) – Gowthaman Apr 30 '19 at 08:31
  • Can you show me your Client code. What is the return type of that method? It should be something like `public async Task` – Rahul Sharma Apr 30 '19 at 08:36
  • I have shown the relevant client code in the question above. I am sorry I don't understand what 'Task' refers to. Are you asking for the return type of the server? – Gowthaman Apr 30 '19 at 08:38
  • Or if you are calling this method then: `Task result = yourmethodname(text); var finalResult = result.Result;` – Rahul Sharma Apr 30 '19 at 08:38
  • I am not using the keyword Task anywhere. The only definitions relevant to POST has been posted in the question itself. Both the clients and the servers – Gowthaman Apr 30 '19 at 08:40
  • Then remove the `await` keyword. await and async keywords are used during asynchronous programming in which each method is treated as a `Task` – Rahul Sharma Apr 30 '19 at 08:44
  • Wait wait. I am sorry. The client code is inside a switch statement which is in turn inside a function 'public async void Register_Clicked'. Should I make this a task instead? – Gowthaman Apr 30 '19 at 08:51
  • Yes, did my answer solve your question? – Rahul Sharma Apr 30 '19 at 09:02

1 Answers1

0

I have prepared a simple example on how you can retrieve your Result from your Task:

async Task<string> GetResponseString(SigupModel signup)
{
  Sjson = JsonConvert.SerializeObject(signup);   
  var httpContent = new StringContent(Sjson);    
  using (HttpClient client = new HttpClient())
   {
     client.BaseAddress = new Uri("https://apiname.azurewebsites.net");
     var response =  await client.PostAsync("api/values", httpContent);    
     var responseContent =  await response.Content.ReadAsStringAsync();   
   }
 return responseContent;
}

And you can call this as:

Task<string> result = GetResponseString(signup);
var finalResult = result.Result;
StatusLabel.Text = finalResult; //To display response in client

If you are not using async keyword, then you can call get your Result as:

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

EDIT

Basically you would have to POST your signup model to your API Controller. Use SigupModel signup as a parameter if you would like. Then whatever processing you are doing in the API, the final result in a string. Now this string can either be a null, empty or have a value. When you get this value in your client, you would have do the following:

var responseContent = await response.Content.ReadAsStringAsync(); 
var message = JsonConvert.DeserializeObject<string>(responseContent); 

Here you will get your message a string and then you can set it as: StatusLabel.Text = message ;

Rahul Sharma
  • 7,768
  • 2
  • 28
  • 54
  • I cant edit my question to show you the bigger picture. It will become a lot of code and I might get flagged. Anyways the client code is inside a switch statement which is in turn inside a Xamarin.Forms Button Click even handler. I tried replacing my code with yours and the app crashed after requesting POST – Gowthaman Apr 30 '19 at 09:09
  • You can start a chat discussion. – Rahul Sharma Apr 30 '19 at 09:09
  • I have '1' reputation so cannot chat yeah? I am sorry. Ill edit the question. See now... – Gowthaman Apr 30 '19 at 09:15
  • Not sure, you can lookup my user id. Also one more thing that I noticed was that in your Client, you are posting your signup model. So you server expects a model of type signup. It should be: `public string Post([FromBody] Signup signup)` – Rahul Sharma Apr 30 '19 at 09:24
  • For what it is worth the signup object is successfully set to user inputs and the conversion to JSON is happening with out any problem. The issue is accessing this payload inside HTTP definition in API. It is always NULL there... – Gowthaman Apr 30 '19 at 09:25
  • Yeah but we are converting the Signup object 'signup' into a string and then only POSTING it via client code yes? The POST method in API receives the payload as a string doesnt it? Also I tried changing the parameter input to type Signup and it shows inconsistency accessability type Signup is less accessible than method 'ValuesController.Post(Signup) – Gowthaman Apr 30 '19 at 09:27
  • Use this: `StatusLabel.Text = responseContent.Result;`. If you are receiving any value from your server as string, then this should get you the Result. – Rahul Sharma Apr 30 '19 at 09:32
  • Gives a missing Using Directive or assembly reference error when I do StatusLabel.Text = responseContent.Result; – Gowthaman Apr 30 '19 at 09:38
  • Do I need to enable CORS? My client is a mobile application and API is hosted on Azure as a API APP ? – Gowthaman Apr 30 '19 at 09:53
  • No, it is not necessary to enable CORS in your case. What error you get when you do: `StatusLabel.Text = responseContent.Result;`. You would need to add a reference to what is missing. – Rahul Sharma Apr 30 '19 at 09:58
  • 'string' does not contain a definition for 'Result' and no accessible extension method 'Result' accepting a first argument of type 'string' could be found (are you missing a using directive or an assembly reference). – Gowthaman Apr 30 '19 at 10:02
  • See lets debug. Forget about the response string. Inside the API POST method I convert the incoming string back to C# object of type Signup. I have copied the Signup Class file in the API folder. But when I add Deserialize, the response becomes "error message". So probably the input string is itself null yes? – Gowthaman Apr 30 '19 at 10:07
  • I did some debugging. I can confrim the payload recieved by the API is of type string because I was able to set string signup1 = signup; (signup is the parameter that API POST method takes). But it does not let me carryout anyother operation with the string signup like Deserialiize or Parse. That is what I need to figure out now.... – Gowthaman Apr 30 '19 at 10:14
  • Basically you would have to `POST` your signup model to your API Controller. Use `SigupModel signup` as a parameter if you would like. Then whatever processing you are doing in the API, the final result in a `string`. Now this string can either be a `null`, `empty` or have a value. When you get this value in your client, you would have do the following: `var responseContent = await response.Content.ReadAsStringAsync(); message = JsonConvert.DeserializeObject(responseContent );`. Here you will get your message a string and then you can set it as: `StatusLabel.Text = message ;` – Rahul Sharma Apr 30 '19 at 10:17
  • When I post my SignupModel signup from client first i serialize it then make a HTTPContent using StringContent and then send it along the POST request correct? In other words do I have to change the code in my client to make it send it purely as a object of type Signup. Can you check and client code please...? – Gowthaman Apr 30 '19 at 10:30
  • Yes it looks correct. Try using what I have mentioned in my last comment. – Rahul Sharma Apr 30 '19 at 10:46
  • Yaaay. You are right. Your method worked. Also the major reason for our troubles was the fact that Signup class in the API folder was not set to public. It defaulted to private. Thanks so much bro. Really appreciate your help. Been at this for 2 days! – Gowthaman Apr 30 '19 at 11:12