I am trying to call a web API from my web application. I am using .Net 4.5 and while writing the code I am getting the error HttpClient does not contain a definition PostAsJsonAsync method.
Below is the code:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("http://localhost:51093/");
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
var user = new Users();
user.AgentCode = 100;
user.Remarks = "Test";
user.CollectionDate = System.DateTime.Today;
user.RemittanceDate = System.DateTime.Today;
user.TotalAmount = 1000;
user.OrgBranchID = 101;
var response = client.PostAsJsonAsync("api/AgentCollection", user).Result;
and I am getting the error message:
Error: 'System.Net.Http.HttpClient' does not contain a definition for
'PostAsJsonAsync' and No extension method 'PostAsJsonAsync' accepting a first argument of
type 'System.Net.Http.HttpClient' could be found (are you missing
a using directive or an assembly reference?)
Please have a look and advice me.
Yes, you need to add a reference to
System.Net.Http.Formatting.dll
This can be found in the extensions assemblies area.
A good way of achieving this is by adding the NuGet package Microsoft.AspNet.WebApi.Client to your project.
PostAsJsonAsync is no longer in the System.Net.Http.dll (.NET 4.5.2). You can add a reference to System.Net.Http.Formatting.dll, but this actually belongs to an older version. I ran into problems with this on our TeamCity build server, these two wouldn't cooperate together.
Alternatively, you can replace PostAsJsonAsyncwith a PostAsync call, which is just part of new dll.
Replace
var response = client.PostAsJsonAsync("api/AgentCollection", user).Result;
With:
var response = client.PostAsync("api/AgentCollection", new StringContent(
new JavaScriptSerializer().Serialize(user), Encoding.UTF8, "application/json")).Result;
Note that JavaScriptSerializer is in the namespace: System.Web.Script.Serialization.
You will have to add an assembly reference in your csproj: System.Web.Extensions.dll
See https://code.msdn.microsoft.com/windowsapps/How-to-use-HttpClient-to-b9289836
The missing reference is the System.Net.Http.Formatting.dll. But the better solution is to add the NuGet package Microsoft.AspNet.WebApi.Client to ensure the version of the formatting dll worked with the .NET framework version of System.Net.Http in my project.
As already debatted, this method isn't available anymore since .NET 4.5.2. To expand on Jeroen K's answer you can make an extension method:
public static async Task<HttpResponseMessage> PostAsJsonAsync<TModel>(this HttpClient client, string requestUrl, TModel model)
{
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(model);
var stringContent = new StringContent(json, Encoding.UTF8, "application/json");
return await client.PostAsync(requestUrl, stringContent);
}
Now you are able to call client.PostAsJsonAsync("api/AgentCollection", user).
I had this issue too on a project I'd just checked out from source control.
The symptom was the error described above and a yellow warning triangle on a reference to System.Net.Http.Formatting
To fix this, I removed the broken reference and then used NuGet to install the latest version of Microsoft.AspNet.WebApi.Client.
I know this reply is too late, I had the same issue and i was adding the System.Net.Http.Formatting.Extension Nuget, after checking here and there I found that the Nuget is added but the System.Net.Http.Formatting.dll was not added to the references, I just reinstalled the Nuget
Try to install in your project the NuGet Package: Microsoft.AspNet.WebApi.Client:
Install-Package Microsoft.AspNet.WebApi.Client
Ok, it is apocalyptical 2020 now, and you can find these methods in NuGet package System.Net.Http.Json. But beware that it uses System.Text.Json internally.
And if you really need to find out which API resides where, just use https://apisof.net/
If you are already using Newtonsoft.Json try this:
// Alternative using WebApi.Client 5.2.7
////var response = await Client.PutAsJsonAsync(
//// "api/AgentCollection", user
//// requestListDto)
var response = await Client.PostAsync("api/AgentCollection", new StringContent(
JsonConvert.SerializeObject(user), Encoding.UTF8, "application/json"));
Performance are better than JavaScriptSerializer. Take a look here https://www.newtonsoft.com/json/help/html/Introduction.htm
Instead of writing this amount of code to make a simple call, you could use one of the wrappers available over the internet.
I've written one called WebApiClient, available at NuGet... check it out!
https://www.nuget.org/packages/WebApiRestService.WebApiClient/
If you're playing around in Blazor and get the error, you need to add the package Microsoft.AspNetCore.Blazor.HttpClient.
Just expanding Jeroen's answer with the tips in comments:
var content = new StringContent(
JsonConvert.SerializeObject(user),
Encoding.UTF8,
MediaTypeNames.Application.Json);
var response = await client.PostAsync("api/AgentCollection", content);
For me I found the solution after a lot of try which is replacing
HttpClient
with
System.Net.Http.HttpClient
Based on the answers here talking about using Newtonsoft.Json, I created a helper class for this:
public class JsonContent : StringContent
{
public JsonContent(object model)
: base(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json")
{
}
}
Example usage:
using (var content = new JsonContent(user))
{
var response = client.PostAsync("api/AgentCollection", content).Result;
}
If you are using Blazor components and getting this error that means your component is not able to find the http client.
use this line on top on your blazor component.
#inject HttpClient Http
Make sure you have this line in your Program or startup file
builder.Services.AddScoped(sp =>
new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
Related
I ran into some issues with CORS when setting up my Blazor client-side API client to make requests. I think I found the solution to that, but the solution is also throwing errors.
The main error is:
"WASM: System.Net.Http.HttpRequestException: TypeError: Failed to execute 'fetch' on 'Window': The provided value '2' is not a valid enum value of type RequestCredentials."
the code is
string link = API_RequestLoginTokenEndPoint;
Http.DefaultRequestHeaders.Add("User-Agent", "HttpClientFactory-Sample");
Http.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Authorization", "basic:testuser:testpassword");
var requestMessage = new HttpRequestMessage(new HttpMethod("GET"), link);
requestMessage.Properties[WebAssemblyHttpMessageHandler.FetchArgs] = new
{
credentials = FetchCredentialsOption.Include
};
var response = await Http.SendAsync(requestMessage);
var responseStatusCode = response.StatusCode;
var responseBody = await response.Content.ReadAsStringAsync();
output = responseBody + " " + responseStatusCode;
I also tried changing the request message to:
var requestMessage = new HttpRequestMessage(HttpMethod.Get, link);
In case this was the ENUM the error referred to. In the Startup ConfigureServices I tried to add:
WebAssemblyHttpMessageHandler.DefaultCredentials = FetchCredentialsOption.Include;
I am using Blazor preview 9. I also tried adding some CORS code to my PHP script on the API route that should accept all origins, but the last question I posted I was told to use this method to fix the CORS problem, which now gives me a new error.
Am I doing something wrong or am I missing something? The error in the browser usually points to the line with the async request:
var response = await Http.SendAsync(requestMessage);
This is a bug not yet fixed. Use this instead :
requestMessage.Properties[WebAssemblyHttpMessageHandler.FetchArgs] = new
{
credentials = "include"
};
I had a similar issue and could not resolve the pre-flight activity.
I WAS ABLE TO SOLVE THIS BY COMMENTING OUT HTTP REDIRECTION MIDDLEWARE.
context: Blazor client calls asp.net.core api in different url.
Not sure if this a good solution but I felt I needed to mention this after
spending 1 week on this frustrating issue! Hope it helps someone.
I'm looking into using Protobuf to send data between my Microservices, and
I'm using the C# support in Google.ProtoBuf and not ProtoBuf-Net, since I want to compile classes from .proto files.
The reason for this is the Microservices are not strictly .Net. Some of the are written in Go etc.
I'm looking for something like the ProtoBufFormatter in the package WebApiContrib.Formatting.ProtoBuf, but support Google.ProtoBuf.
The ProtoBufFormatter returns serialized protobuf data if the client have set content type to application/x-protobuf, otherwise Json.
How can I achieve something similar for Google.ProtoBuf? Further I'm also looking into find this kind of support for the Nancy Framework on .Net Core as well.
I have found this link where it explains how to use protobuf files with Protobuf-Net, but does not seem up to date (.Net Core + VSCode).
I could not find any solution for my use case with Google.Protobuf, so I used a custom InputFormatter and OutputFormatter like in this blog post, with Protobuf-Net.
Then to call and deserialize the protobuf content in the client, I came up with this solution:
var client = new System.Net.Http.HttpClient { BaseAddress = new Uri("http://localhost:5002") };
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf"));
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await client.GetAsync("api/home");
if (response.IsSuccessStatusCode)
{
if (response.Content.Headers.ContentType.MediaType == "application/x-protobuf")
{
using(var stream = await response.Content.ReadAsStreamAsync())
{
var protoBufModel = ProtoBuf.Serializer.Deserialize<ProtobufModelDto>(stream);
return $"{protoBufModel.Name}, {protoBufModel.StringValue}, {protoBufModel.Id}";
}
}
var content = await response.Content.ReadAsStringAsync();
var jsonModel = JsonConvert.DeserializeObject<ProtobufModelDto>(content);
return $"{jsonModel.Name}, {jsonModel.StringValue}, {jsonModel.Id}";
}
return "Failed";
Next step will be to figure out how to create models from .proto files with Protobuf-Net.
I'm trying to do a HTTP Delete request from Unity and bump into the idea of use the HttpRequest class included in the System.Web namespace of .Net
How can I achieve this, I supose that some sort of import of that namespace must be done, but how?
Hope some one can give me some orientation
HttpClient is only available in 4.5 NET and above and Unity does not use that version. Unity uses about 3.5 .NET version.
If you are using Unity 5.3, UnityWebRequest.Delete can be used to make a Delete request. It can be found in the Experimental.Networking namespace. If you are using Unity 5.4 and above,UnityWebRequestcan be found in the UnityEngine.Networking; namespace.
Full working example:
IEnumerator makeRequest(string url)
{
UnityWebRequest delReq = UnityWebRequest.Delete(url);
yield return delReq.Send();
if (delReq.isError)
{
Debug.Log("Error: " + delReq.error);
}
else
{
Debug.Log("Received " + delReq.downloadHandler.text);
}
}
Usage:
StartCoroutine(makeRequest("http://www.example.com/whatever"));
Make sure to include using UnityEngine.Networking. You can find complete examples with it here.
EDIT (UPDATE)
Unity now supports .NET 4.5 so you can now use HttpClient if you wish. See this post for how to enable it.
After enabling it,
Go to <UnityInstallationDirectory>\Editor\Data\MonoBleedingEdge\lib\mono\4.5 or for example, C:\Program Files\Unity\Editor\Data\MonoBleedingEdge\lib\mono\4.5 on my computer.
Once in this directory, copy System.Net.Http.dll to your <ProjectName>\Assets directory and you should be able to use HttpClient after importing the System.Net.Http namespace. If there are some other error about missing dependencies, you can get the dlls from this path too and copy them to your <ProjectName>\Assets directory too.
In the current versions of Unity httpClient is supported out of the box even on .NET Standard 2.0 targets. Here is sample code on how I use it to access a REST api.
public static async Task<Resource> GetResource()
{
using (var httpClient = new HttpClient())
{
httpClient.BaseAddress = new Uri(URL);
httpClient.DefaultRequestHeaders.Accept.Clear();
httpClient.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var response = await httpClient.GetAsync("api/session");
if (response.StatusCode != HttpStatusCode.OK)
return null;
var resourceJson = await response.Content.ReadAsStringAsync();
return JsonUtility.FromJson<Resource>(resourceJson);
}
}
Copy of my answer on https://forum.unity.com/threads/httpclient-on-net-standard-2-0.608800/
I am trying to use the HttpClient PCL from Microsoft in an Android project but whne I attempt to make a request, after a little while I get a "System.Diagnostics.Mono_UnhandledException" and no extra info.
var client = new HttpClient();
client.BaseAddress = new Uri(_apiUrl);
var resourceUrl = "setistas?login=" + login + "&senha=" + senha;
HttpRequestMessage requestMessage = new HttpRequestMessage(HttpMethod.Post, resourceUrl);
var response = client.SendAsync(requestMessage).Result;
I am not sure why this happens, I am using the latest version of Xamarin studio, and the latest version of the libraries.
Can anyone help me?
By the way don't mind fact that I am passing secure information on the url, this is just a test. ;)
Probably you are not awaiting your request and trying to read result of unfinished task.
Last line should be
var result = await client.SendAsync(requestMessage);
The problem was on how I referenced the libraries.
When you add the nugget package for HTTPClient to the DLL project, you have to add a reference in the Android project to System.Net.Http, once you do that, it starts working.
I am trying to write a small test application using WebApi. I have it mostly working, I am able to get data from my web service and display it in Android.
I added a button, and used the same code that I had used in my Winforms test client:
async void buttonSave_Clicked(object sender, EventArgs e)
{
HttpClient client = new HttpClient ();
Customer data = new Customer () {
Surname = editSurname.Text,
GivenName = editGivenName.Text};
var result = await client.PutAsJsonAsync("http://10.0.0.4/WebApplication1/api/Customers/2", data);
if (result.IsSuccessStatusCode ) {
labelStatus.Text = "Saved";
}
}
This works fine in the Windows Forms test app, but in the Xamarin app I get an exception on client.PutAsJsonAsync:
E/mono-rt ( 7519): [ERROR] FATAL UNHANDLED EXCEPTION: System.TypeLoadException: Could not load type 'System.Net.Http.ObjectContent`1[T]' from assembly 'System.Net.Http.Formatting, Version=5.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
Any suggestions? Using Xamarin 3.
edit:
It works if I format the content manually:
string sData = Newtonsoft.Json.JsonConvert.SerializeObject(data);
HttpContent content = new System.Net.Http.StringContent(sData, System.Text.Encoding.UTF8, "application/json") ;
var result = await client.PutAsync("http://10.0.0.4/WebApplication1/api/Customers/2",content);
I have all the references correct, as far as I can see. I used the WebApi Client nuget package.
References:
Newtonsoft.Json
System.Net.Http
System.Net.Http.Extensions
System.Net.Http.Formatting
System.Net.Http.Primitives
You need to install the following Nuget packages to all the projects that reference your HttpClient project
Microsoft.Bcl.Build
Microsoft.Bcl
These are the warnings from Visual Studio when I built my project and after I done that, it worked!
Serialize your data into a JSON string like this:
string json = JsonConvert.SerializeObject(item);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
response = await client.PostAsync(url, content);
The overload list for the System.Net.Http.PutAsJsonAsync method on MSDN only shows overloads that contain three or four parameters. In your example, I see two that you are passing. It appears correct to be able to leave out the HttpClient parameter when called as a instance from HttpClient based on the code examples from MSDN.
However, with Xamarin it was built as a fork of MonoDevelop. MonoDevelop uses the Mono Framework which is a port of the .NET Framework. Due to that difference, I am interested if a bug should be opened for Mono, MonoDevelop, or Xamarin.
Back to the overload methods list though, I recommend trying to use one of these overloads.
PutAsJsonAsync(HttpClient, String, T)
PutAsJsonAsync(HttpClient, Uri, T)
PutAsJsonAsync(HttpClient, String, T, CancellationToken)
PutAsJsonAsync(HttpClient, Uri, T, CancellationToken)
I recommend trying to pass the HttpClient to the PutAsJsonAsync method without PutAsJsonAsync being called from an instance of HttpClient.
BTW, this is not a guaranteed solution, for it was simply too much information to put into comments. Hope this helps.