I'm trying to pass a big string in my controller using json. Also i need Controller to send me an answer.
Here is my controller in web api:
public class CustomersController : ApiController
{
// GET: api/Customers
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET: api/Customers/5
public string Get(int id)
{
return "value";
}
// POST: api/Customers
public void Post([FromBody]string value)
{
}
// PUT: api/Customers/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE: api/Customers/5
public void Delete(int id)
{
}
}
First of all where i should read my string and where should i send an answer?
And here is my client which try to send a string
using (var client = new HttpClient())
{
var response = await client.PostAsync("http://192.168.1.15:8282/",new StringContent("Mystring", Encoding.UTF8, "application/json"));
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
}
I need my web api to read my string, and then to send me an answer
Instead of having the methods as void you need to return the string value from the controller methods.
Also, don't forget to decorate the methods with respective http verb attribubte (HttpGet, HttpPost, HttpPut etc.) which the method is responsible to serve.
Here's an example where the method returns an Ok result, this generate an http status code 200 with the string in the response body
[HttpPost]
public IHttpActionResult Post([FromBody]string value)
{
return Ok(value);
}
Then for the client call.
First of, you need to specify the route to the controller correctly
192.168.1.15:8282/api/Customers
Then, sending a single string as content when using the content-type of application/json is not suitable as json always start parsing from an object {} or array [].
The easiest way of sending a single string is therefore to just change the content type to application/x-www-form-urlencoded and adding a = sign infront of the string
using (var client = new HttpClient())
{
var response = await client.PostAsync("http://192.168.1.15:8282/api/Customers",new StringContent("=Mystring", Encoding.UTF8, "application/x-www-form-urlencoded"));
if (response.IsSuccessStatusCode)
{
string content = await response.Content.ReadAsStringAsync();
}
}
Related
I have an endpoint which is used to create an item. The controller calls the service which creates the item, makes some changes on the db and db returns data based on the procedure. The db returns a json like response, but is not always the same, so I have to adjust on the backend so that I can formalize the response type.
The problem is that create item service is asynchronous and I need to be able to await the response so I can make a new response based on that. How can I await the response and that I get from db client and then return data based on that.
This is my Action and I want to be able to serialize async response from service
[HttpPost]
public IActionResult CreateItem([FromBody] InputModel item)
{
var jsonString = _itemService.CreateItem(item);
ResponseModel? response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
return new ObjectResult(response.Response) { StatusCode = response.StatusCode };
}
The default response model
public class ResponseModel
{
public string Response { get; set; }
public int StatusCode { get; set; }
}
Create Item service, which makes the post request to the client and it has to be async.
Depending on the status code that is coming from the client, I want to be able to set my action status code as well.
public async Task<string> CreateItem(InputModel item)
{
if (item.VersionType != 1)
{
return new { Response = "Incorrect data", StatusCode = 400 }.ToString()!;
}
var json = JsonSerializer.Serialize(item);
var data = new StringContent(json, Encoding.UTF8, "application/json");
var response = await client.PostAsync(url, data);
var content = await response.Content.ReadAsStringAsync();
return content;
}
You can make your action method async and then await the method call _itemService.CreateItem for it :
[HttpPost]
public async Task<IActionResult> CreateItem([FromBody] InputModel item)
{
var jsonString = await _itemService.CreateItem(item);
ResponseModel? response = JsonSerializer.Deserialize<ResponseModel>(jsonString);
return new ObjectResult(response.Response) { StatusCode = response.StatusCode };
}
Now your action method would asyncrounously wait for the result from CreateItem and when it returs result, it will continue executing further and send the deserialized response back to client.
As I am new to WebAPI I have been experimenting with samples from the web. I have an ApiController based class which handles Post, Get, etc. From my client application, I can perform a Get and a Delete successfully but when I do a Post or a Put of a string, I can see the string value is null at the server and I get StatusCode 204, No Content at the client. Using Postman I can successfully do a Post or Put so it seems to be a problem with my client app.
Have tried basing the client on .Net 4.7.2 as well as .NET Core 2.2
Here is the entire controller class of my WebAPI program:
namespace WebApplication1.Controllers
{
public class ValuesController : ApiController
{
static List<string> strings = new List<string>()
{
"value0", "value1", "Value2"
};
// GET api/values
public IEnumerable<string> Get()
{
return strings;
}
// GET api/values/5
public string Get(int id)
{
return strings[id];
}
// POST api/values
public void Post([FromBody]string value)
{
strings.Add(value);
}
// PUT api/values/5
public void Put(int id, [FromBody]string value)
{
strings[id] = value;
}
// DELETE api/values/5
public void Delete(int id)
{
strings.RemoveAt(id);
}
}
}
Here is code from my client Program:
class Program
{
static HttpClient client = new HttpClient();
static void Main()
{
RunAsync().GetAwaiter().GetResult();
}
static async Task RunAsync()
{
client.BaseAddress = new Uri("http://localhost:56037/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
try
{
var response = await client.PutAsJsonAsync($"api/values/2", new StringContent("zzz"));
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}
I set breakpoints in the Put and Post methods but the value of the string being passed is null, not the value I sent to the server.
Id maybe try
var response = await client.PutAsJsonAsync($"api/values/2", new StringContent("zzz"), System.Text.Encoding.UTF8, "application/json");
Turns out that I needed to enclose the string in quotes as follows:
var response = await client.PutAsync("api/values/0", "\"zzz\"", new StringTypeFormatter());
response = await client.PostAsync("api/values", "\"zzz\"", new StringTypeFormatter());
If you want the item at the index, try:
strings.ElementAt(id) = value;
I have an Asp Net Core 2.1 application with a REST controller like this:
[Produces("application/json")]
[Route("api/Test")]
public class TestController : Controller
{
// GET: api/Test
[HttpGet]
public IEnumerable<string> Get() { return new string[] { "value1", "value2" }; }
// GET: api/Test/5
[HttpGet("{id}", Name = "Get")]
public string Get(int id) { return "value"; }
// POST: api/Test
[HttpPost]
public void Post([FromBody]string value)
{
//.. testing code..
}
// PUT: api/Test/5
[HttpPut("{id}")]
public void Put(int id, [FromBody]string value) {}
// DELETE: api/ApiWithActions/5
[HttpDelete("{id}")]
public void Delete(int id) {}
}
I'm trying to use "System.Net.HttpWebRequest" object to make a POST request to Rest controller.
In my client application, I have a method that receives data as a string. The string content is a dynamic array of values such "param1=value1;param2=value2" (the number of elements is variable).
Can you help me to understand the correct way to send this data to the controller?
this is the code I'm trying to use in the client:
public static string PostWebApi(string postData)
{
var request = (HttpWebRequest)WebRequest.Create("http://localhost:64817/api/test");
// for example, assumes that postData value is "param1=value1;param2=value2"
var data = Encoding.ASCII.GetBytes(postData);
request.Method = "POST";
request.ContentType = "application/json";
//request.ContentType = "application/x-www-form-urlencoded";
request.ContentLength = data.Length;
using (var stream = request.GetRequestStream()) {
stream.Write(data, 0, data.Length);
}
var response = (HttpWebResponse)request.GetResponse();
var responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
return responseString;
}
I'm using content type "application/json": if I try to use "application/x-www-form-urlencoded" I get "(415) Unsupported Media Type" error.
so... when I exec PostWebApi I receive a Null value parameter in the POST: api/Test method..
how can I receive the data I sent?
Thanks in advance.
you can use HTTPClient for this. it'll ease up the process for you.
public static string PostWebApi(string postData)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://localhost:64817/api/test");
var content = new FormUrlEncodedContent(new[]
{
new KeyValuePair<string, string>("value", postData)
});
var result = await client.PostAsync("/api/Membership/exists", content);
string resultContent = await result.Content.ReadAsStringAsync();
Console.WriteLine(resultContent);
}
}
Reference:- How to make HTTP POST web request
I'm trying to post anonymous object via httpclient, however orderId is null and collection empty when it hits controller.
public async Task<Response> CancelOrderAsync(int orderId, ICollection<int> ids)
{
Response result = null;
using (IHttpClient client = HttpClientFactory.CreateHttpClient())
{
var obj = new {OrderId = orderId, Ids = ids};
string json = JsonConvert.SerializeObject(obj);
HttpContent postContent = new StringContent(json, Encoding.UTF8, "application/json");
using (var response = await client.PostAsync($"{url}/admin/cancel", postContent).ConfigureAwait(false))
{
if (response != null && response.IsSuccessStatusCode)
{
...
}
}
}
return result;
}
// Controller
[HttpPost]
[ActionName("cancel")]
public async Task<Response> Cancel(int orderId, ICollection<int> ids)
{
// order is null, collection empty
...
EDIT:
Changed my controller to this for simplicity
[HttpPost]
[ActionName("cancel")]
public async Task<SimpleResponse> Cancel(int orderId)
Via Postman, i'm posting this body:
{
"orderId": "12345"
}
Still, orderId comes in as 0 (zero) ??
The controller action on the server side will need a concrete type to read the entire body of the request
public class Order {
public int OrderId { get; set; }
public int[] Ids { get; set; }
}
This is primarily because the action can only read from the body once.
Update action to...
[HttpPost]
[ActionName("cancel")]
public async Task<Response> Cancel([FromBody]Order order) {
if(ModelState.IsValid) {
int orderId = order.OrderId;
int[] ids = order.Ids;
//...
}
//...
}
the original code used to send the request in the example will work as is, but as mentioned it can be improved.
The HttpClient can do the serialisation for you. See if
var response = await client.PostAsJsonAsync($"{url}/admin/cancel", obj);
works better. Then you don't need to write the serialisation code yourself.
If you still have a problem, use a tool such as Fiddler to monitor the actual request and see what parameter and values are submitted in the request body, to see if they match what's expected by the endpoint.
In my WebApi I have a HttpGet and HttpPost method, the get method is working fine and the post method is called but the body content is always null, unless used in a HttpRequestMessage. I tried providing the body content in a string format(preferred datatype) aswell as in a model but neither one of those methods worked. I also tried switching the content type without success. Does anyone know if I'm doing something wrong or how I can easily get the variable data from the HttpRequestMessage, which in the example below is "test".
Method 1:
[System.Web.Http.HttpPost]
[Route("api/v1/AddItem")]
public IHttpActionResult AddItem([FromBody]string filecontent, string companycode)
{
MessageBox.Show(filecontent);
Return Ok("");
}
Method 2 (with model):
[System.Web.Http.HttpPost]
[Route("api/v1/AddItem")]
public IHttpActionResult AddItem([FromBody]ItemXML filecontent, string companycode)
{
MessageBox.Show(filecontent.XMLContent);
Return Ok("");
}
Model:
public class ItemXML
{
public ItemXML(string content)
{
XMLContent = content;
}
public string XMLContent { get; set; }
}
Method 3:
[System.Web.Http.HttpPost]
[Route("api/v1/AddItem")]
public IHttpActionResult AddItem(HttpRequestMessage filecontent, string companycode)
{
var content = filecontent.Content.ReadAsStringAsync().Result;
MessageBox.Show(content);
Return Ok("");
}
Method 3 content string ("test" is the provided value): " content "------WebKitFormBoundarydu7BJizb50runvq0\r\nContent-Disposition: form-data; name=\"filecontent\"\r\n\r\n\"test\"\r\n------WebKitFormBoundarydu7BJizb50runvq0--\r\n" string"
Create a model store data to be sent to server
public class Model {
public string filecontent { get; set;}
public string companycode { get; set;}
}
Update Action
[HttpPost]
[Route("api/v1/AddItem")]
public IHttpActionResult AddItem([FromBody]Model model) {
if(ModelStat.IsValid) {
return Ok(model); //...just for testing
}
return BadRequest();
}
On the client make sure the request is being sent properly. In this case going to use JSON.
public client = new HttpClient();
var model = new {
filecontent = "Hello World",
companycode = "test"
};
var response = await client.PostAsJsonAsync(url, model);
If using another type of client ensure that the data being sent is formatted correctly for the Web API action to accept the request.
Reference Parameter Binding in ASP.NET Web API