Exception calling PutAsJsonAsync from Xamarin - c#

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.

Related

HttpClient PostAsync model is null, however it works in Postman

I'm making a call using HttpClient.
var serializedRequest= JsonConvert.SerializeObject(searchRequest);
var stringContent = new StringContent(serializedRequest, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(url, stringContent);
The object is null in the API controller:
[HttpPost]
public List<string> GetSearchResults([System.Web.Http.FromBody]SearchRequest searchRequest)
However, if I make the same call from Postman (I copied the serialized object within Visual Studio while debugging), it works. Why would that be the case? I'm trying to figure out how to send the content length with the request, but apparently that's supposed to be happening already by using StringContent.
The caller is .NET Core 2.2 and the API is .NET Framework 4.7.2.
EDIT:
This was the original call:
var response = await _httpClient.PostAsJsonAsync(url, searchRequest);
That does NOT work even when the API method isn't using [FromBody]. Looks like I need to use the above code (StringContent) along with the API method not using [FromBody]. What's weird is that a coworker isn't having this issue. It's just on my machine. Go figure.

API GET Request Returns HTML/Text instead of JSON

This is my first time working with a RESTful API and Xamarin and etc. I have so far made a simple REST API. I have written a GET call to it that, if I write http://localhost:[num]/api/Name, it will return a JSON file of the matching Emu's information. I have tested this with Postman, so I know that it works.
I have now written an app that will call this API in order to catch this information and then display it. So far, I've got it connected to the server hosting my API, but I'm unable to get it to return JSON. Instead it seems to be returning text/HTTP.
From what I've searched up on previous Stack Overflow threads, it seems that I was missing Headers requesting that reply be in a JSON format. When I added in code that was on the official .NET documentation on Microsoft's website, it gave me issues with my Json Deserialiser. I have also added in the information in the header to make sure that it returns json.
Here is the code for the function:
async private void Submit_OnClicked(object sender, EventArgs e)
{
var nameValue = EmuName.Text;
var baseAddr = new Uri("http://my_url/HelloEmu/");
var client = new HttpClient { BaseAddress = baseAddr };
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
string url = (string)nameValue;
var returnedJson = await client.GetStringAsync(url);
Models.EmuItemModel MyEmu = JsonConvert.DeserializeObject<Models.EmuItemModel>(returnedJson);
ReturnedName.Text = MyEmu.Name;
ReturnedAge.Text = MyEmu.Age.ToString();
ReturnedWeight.Text = MyEmu.Weight.ToString();
My code actually faults on the line ReturnedWeight.Text = MyEmu.Weight.ToString()
But I'm guessing the more majour issue is occuring during deserialisng the object, because it seemingly "skips" over the preceeding two lines when I run it in the debugger.
When I run it in Visual Studio 2019, the value of "returnedJson" is this:
"<html><head><meta http-equiv=\"refresh\" content=\"0;url=http://lookup.t-mobile.com/search/?q=http://my_url/HelloEmu/Keith&t=0\"/></head><body><script>window.location=\"http://lookup.t-mobile.com/search/?q=\"+escape(window.location)+\"&r=\"+escape(document.referrer)+\"&t=0\";</script></body></html>"
I think this is an HTML output. I would love any hints about what on earth I'm doing wrong!
EDIT: Since it almost seems like the HTML is returning an error message, perhaps it could do with my url??? I've published the website using the File system method. So to access the API in Postman I'll use http://localhost:[port]/api/values, calling my website in a regular ol' browser makes it go http://my_url/HelloEmu. I get a 403 "no directory" method in return...
EDIT: Here is the Postman code:
enter image description here
Usually it happens because there are missing headers or some other malformed request, Download RestSharp DLL from NuGet, and then you can use the following, in postman, go to "Code":
And choose C# you will see a code snippet (Example):

Use .NET's own httpClient class on Unity

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/

Xamarin.Forms UnhandledException when doing a request

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.

HttpClient not supporting PostAsJsonAsync method C#

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) });

Categories

Resources