How to use System.Net.HttpClient to post a complex type?
The generic HttpRequestMessage<T>
has been removed. This :
new HttpRequestMessage<Widget>(widget)
will no longer work.
Instead, from this post, the ASP.NET team has included some new calls to support this functionality:
HttpClient.PostAsJsonAsync<T>(T value) sends “application/json”
HttpClient.PostAsXmlAsync<T>(T value) sends “application/xml”
So, the new code (from dunston) becomes:
Widget widget = new Widget()
widget.Name = "test"
widget.Price = 1;
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:44268");
client.PostAsJsonAsync("api/test", widget)
.ContinueWith((postTask) => postTask.Result.EnsureSuccessStatusCode() );
How to send a complex object using Get with c# HttpClient
You can use Reflection
:
public IEnumerable<string> ToQueryStringItem<T>(T entity)
{
foreach(var pi in typeof(T).GetProperties())
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
public IEnumerable<string> ToQueryString<T>(T entity)
=> $"?{string.Join("&", ToQueryString(entity).ToList())}";
now simply you can do it like:
string qs = ToQueryString(someClassInstance);
Please note that if the class properties are not of primitive types, you will need a more complex code for reflection.
And also if you want some customized values it will also be doable, for instance lets say instead of true
and false
, you want 1
and 0
:
foreach(var pi in typeof(T).GetProperties())
{
switch(pi.PropertyType.ToString())
{
case "Boolean":
yield return $"{pi.Name}={(pi.GetValue(entity)?1:0)};
//....
default:
yield return $"{pi.Name}={pi.GetValue(entity)}";
}
}
You may also want to hide some properties from being used in query string, for that you can create an attribute:
public class IgnoreInQueryStringAttribute: Attribute {}
and use it for any property you don't want to be in the query string:
public class Customer
{
[IgnoreInQueryString]
public int Id { get; set; }
public string Firstname { get; set; }
}
and then:
foreach(var pi in typeof(T).GetProperties())
{
if(pi.GetCustomAttributes(typeof(IgnoreInQueryString), false).Length == 0)
{
//....
}
}
Post complex data type using HttpClient
By converting the object into a json string you can transfer the json object.
You can use the JavaScriptSerializer
class:
using System.Web.Script.Serialization;
var json = new JavaScriptSerializer().Serialize(obj);
Then you can return the object from webapi.
How do I pass an object to HttpClient.PostAsync and serialize as a JSON body?
The straight up answer to your question is: No. The signature for the PostAsync
method is as follows:
public Task PostAsync(Uri requestUri, HttpContent content)
So, while you can pass an object
to PostAsync
it must be of type HttpContent
and your anonymous type does not meet that criteria.
However, there are ways to accomplish what you want to accomplish. First, you will need to serialize your anonymous type to JSON, the most common tool for this is Json.NET. And the code for this is pretty trivial:
var myContent = JsonConvert.SerializeObject(data);
Next, you will need to construct a content object to send this data, I will use a ByteArrayContent
object, but you could use or create a different type if you wanted.
var buffer = System.Text.Encoding.UTF8.GetBytes(myContent);
var byteContent = new ByteArrayContent(buffer);
Next, you want to set the content type to let the API know this is JSON.
byteContent.Headers.ContentType = new MediaTypeHeaderValue("application/json");
Then you can send your request very similar to your previous example with the form content:
var result = client.PostAsync("", byteContent).Result
On a side note, calling the .Result
property like you're doing here can have some bad side effects such as dead locking, so you want to be careful with this.
How to pass complex type using httpClient with DeleteAsync?
You could use httpPost to post your complex object to your delete method.
E.g.
[System.Web.Http.AcceptVerbs("Post")]
public HttpResponseMessage DeleteComplexObject(Models.ComplexObject deleteme)
{
this.ComplexObjectService.Delete(deleteme);
var response = Request.CreateResponse(HttpStatusCode.Accepted);
return response;
}
Here model binding is used to convert your json object into the ComplexObject automatically so you don't need to use [FromBody]
Send HTTP POST message in ASP.NET Core using HttpClient PostAsJsonAsync
You should add reference to "Microsoft.AspNet.WebApi.Client" package (read this article for samples).
Without any additional extension, you may use standard PostAsync
method:
client.PostAsync(uri, new StringContent(jsonInString, Encoding.UTF8, "application/json"));
where jsonInString
value you can get by calling JsonConvert.SerializeObject(<your object>);
POSTing JsonObject With HttpClient From Web API
With the new version of HttpClient
and without the WebApi
package it would be:
var content = new StringContent(jsonObject.ToString(), Encoding.UTF8, "application/json");
var result = client.PostAsync(url, content).Result;
Or if you want it async
:
var result = await client.PostAsync(url, content);
Related Topics
How to Create an Audit Trail with Entity Framework 5 and MVC 4
Visual Studio Installer > How to Launch App at End of Installer
Run a Background Task from a Controller Action in ASP.NET Core
How to Know the Selected Checkboxes from Within the Httppost Create Action Method
I Have to Access/Commit/Update Svn Repository in Wpf Application Using Svn API or Libraries
How to Implement Permission Based Access Control with ASP.NET Core
Installing Windows Service Programmatically
Is There a C# Type for Representing an Integer Range
Use Different Name for Serializing and Deserializing with JSON.Net
How to Find Reason of Failed Build Without Any Error or Warning
How to Use Custom Authorize Attribute for Roles as Well as a Specific User
How to Find Certificate by Its Thumbprint in C#
Print the Source Filename and Linenumber in C#
How to Run Code Before Program Exit
How to Copy File - Access to the Path Is Denied
Binding to Custom Control Inside Datatemplate for Itemscontrol