Xamarin upload image to a REST web server (Bad Request) - c#

I know that this question has already been posted more than one time but I’m still hanged with the problem of sending one image from a Xamarin client to a REST web server. I receive a BadRequest error on the client side but I don’t know if it comes from the server or from the client.
Here is the Xamarin code (client side) :
public class WsDest
{
public string D_ID { get; set; }
public string D_NOM { get; set; }
public string D_CAT1 { get; set; }
public string D_CAT2 { get; set; }
public string D_ANNEE { get; set; }
public Byte[] D_PHOTO1 { get; set; }
}
static async Task<string> Do_UpdateVehiculeInfos(WsDest Dest)
{
string cRet = "";
string cIP = Application.Current.Properties["IPSERVEUR"].ToString().Trim();
using (HttpClient client = new HttpClient())
{
try
{
var oJson = JsonConvert.SerializeObject(Dest);
var cJson = new StringContent(oJson, Encoding.UTF8, "application/json");
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("Application/json"));
client.Timeout = TimeSpan.FromMilliseconds(8000);
client.MaxResponseContentBufferSize = 3000000;
client.BaseAddress = new Uri(cIP + "/MyWebService.svc/");
using (HttpResponseMessage r = await client.PostAsync("UpdateVehicule", cJson))
{
if (r.IsSuccessStatusCode)
{
await Application.Current.MainPage.DisplayAlert("", "Mise à jour effectuée !", "+OK+");
await Application.Current.MainPage.Navigation.PopAsync(); //Remove the page currently on top (= retourne à la page d'avant)
}
else
{
await Application.Current.MainPage.DisplayAlert("", r.ReasonPhrase.ToString(), "-OK-");
}
}
}
catch (Exception e)
{
await Application.Current.MainPage.DisplayAlert("", e.Message, "/OK/");
}
}
return cRet;
}
On the server side :
[DataContract]
public class WsDest
{
[DataMember]
public string D_ID { get; set; }
[DataMember]
public string D_NOM { get; set; }
[DataMember]
public string D_CAT1 { get; set; }
[DataMember]
public string D_CAT2 { get; set; }
[DataMember]
public string D_ANNEE { get; set; }
[DataMember]
public Byte[] D_PHOTO1 { get; set; }
}
[OperationContract]
[WebInvoke(Method = "POST", RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json, UriTemplate = "UpdateVehicule")]
bool UpdateVehicule(WsDest DestUpdate) ;
public bool UpdateVehicule(WsDest DestRecep)
{
// my code to process data and image
}
The BadRequest message desapears when I set Dest.D_PHOTO1 to null on client side.
Does anybody have an idea on this subject?

Can you show us how the JSON looks like with the byte having a value?<<
Before the Json.SerializeObject(Dest), DEST.D_PHOTOS1 is {byte[6855981]}.
[137,80,70,....]
After the serialization, it's something more 'exotic' :
Before and after serialization
Eric

Related

Why API doesn't response correctly for my request?

I am testing request for API from Baselinker. I have created simple app in c#, which takes input as JSON file with parameters, then converts it to API request model, send it to API and receive response.
But I have problem with one request, https://api.baselinker.com/index.php?method=getOrders. When I try to get orders from my test account by this request I got response "Order source does not exist.", idk why - I have checked every variable in my class which represents this request but didn't find anything wrong. When I do the same on testing API request site (https://api.baselinker.com/index.php?tester) it works correct.
Here is my source code:
Class representing getOrder request:
public class GetOrders : IRequest<GetOrders.Response> {
[JsonPropertyName("order_id")]
public int? OrderId { get; set; }
[JsonPropertyName("date_confirmed_from")]
public int? DateConfirmedFrom { get; set; }
[JsonPropertyName("date_from")]
public int? DateFrom { get; set; }
[JsonPropertyName("id_from")]
public int? IdFrom { get; set; }
[JsonPropertyName("get_unconfirmed_orders")]
public bool? GetUnconfirmedOrders { get; set; }
[JsonPropertyName("include_custom_extra_fields")]
public bool? IncludeCustomExtraFields { get; set; }
[JsonPropertyName("status_id")]
public int? StatusId { get; set; }
[JsonPropertyName("filter_email")]
public string? FilterEmail { get; set; }
[JsonPropertyName("filter_order_source")]
public string? FilterOrderSource { get; set; }
[JsonPropertyName("filter_order_source_id")]
public int? FilterOrderSourceId { get; set; }
public class Product {
```Product class properties...```
}
public class Order {
```Order class properties...```
}
public class Response : Output {
[JsonPropertyName("orders")]
public List<Order> Orders { get; set; }
}
}
Class sending requests:
public class BaselinkerRequestManager {
private string _token;
private const string _url = "https://api.baselinker.com/connector.php";
public BaselinkerRequestManager(string token) { _token = token; }
private string GetRequestMethodName(object userRequest) {
return JsonNamingPolicy.CamelCase.ConvertName(userRequest.GetType().Name);
}
private RestRequest CreateRequest(string method, object parameters) {
var request = new RestRequest();
request.Method = Method.Post;
request.AddHeader("Content-Type", "application/x-www-form-urlencoded");
request.AddHeader("X-BLToken", _token);
request.AddParameter("method", method);
if ( parameters != null ) {
request.AddParameter("parameters", JsonSerializer.Serialize(parameters));
}
return request;
}
private async Task<RestResponse> ExecuteRequestAsync(RestClient client, RestRequest request) {
return await client.ExecuteAsync(request);
}
//TResponse - generic which represents Response Class in each Request
public async Task<TResponse> SendRequestAsync<TResponse>(IRequest<TResponse> userRequest) {
var client = new RestClient(_url);
var method = GetRequestMethodName(userRequest);
var request = CreateRequest(method, userRequest);
var response = await ExecuteRequestAsync(client, request);
return JsonSerializer.Deserialize<TResponse>(response.Content);
}
}
Here is call:
var requestManager = new BaselinkerRequestManager("token_to_connect");
//this request doesn't need parameters so i dont have to initialize it
var r_getOrders = await requestManager.SendRequestAsync(new Requests.Orders.GetOrders());

In .net5.0 - Extranal API response time takes too long time - httpclient

I'm trying to get response a external API using httpclint in .netcore5.0.
Initially I got timeout exception. So I add client.Timeout = Timeout.InfiniteTimeSpan; after adding this response is come. but it takes more than 20 mins.
But I browser I can get API result within milliseconds.
How can I get response from API with a short time. Any idea to decrease this responding time?
startup.cs
services.AddHttpClient<IHolidayService, HolidayService>("PublicHolidaysApi", c => c.BaseAddress = new Uri("https://api.xmltime.com"));
service.cs
public class HolidayService : IHolidayService
{
private readonly IHttpClientFactory _clientFactory;
private readonly HttpClient _client;
public HolidayService(HttpClient client)
{
_client = client;
client.Timeout = Timeout.InfiniteTimeSpan;
}
public HolidayService(IHttpClientFactory clientFactory)
{
_clientFactory = clientFactory;
_client = clientFactory.CreateClient("PublicHolidaysApi");
}
public async Task<Holiday> GetHolidays(string country,int year)
{
string url = string.Format($"/holidays?accesskey="MyAccessKey"&secretkey="MySecretKey"&version=3&country=ro&year=2021&lang=en");
var result = new Holiday();
using (var cts = new CancellationTokenSource(Timeout.InfiniteTimeSpan))
{
var response = await _client.GetAsync(url, cts.Token).ConfigureAwait(false);
if (response.IsSuccessStatusCode)
{
using var responseStream = await response.Content.ReadAsStreamAsync();
result = await JsonSerializer.DeserializeAsync<List<Holiday>>(responseStream);
}
else
{
throw new HttpRequestException(response.ReasonPhrase);
}
}
return result;
}
}
}
model
public class Holiday
{
[JsonPropertyName("urlid")]
public string UrliId { get; set; }
[JsonPropertyName("url")]
public string Url { get; set; }
[JsonPropertyName("country")]
public Country Country { get; set; }
[JsonPropertyName("name")]
public Name Name { get; set; }
[JsonPropertyName("oneliner")]
public OneLiner OneLiner { get; set; }
[JsonPropertyName("date")]
public Date Date { get; set; }
[JsonPropertyName("types")]
public List<string> Types { get; set; }
[JsonPropertyName("uid")]
public string UId { get; set; }
}
public class Country
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("name")]
public string Name { get; set; }
}
public class Name
{
[JsonPropertyName("lang")]
public string Lang { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class OneLiner
{
[JsonPropertyName("lang")]
public string Lang { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class Date
{
[JsonPropertyName("iso")]
public string iso { get; set; }
[JsonPropertyName("datetime")]
public DateTime? Datetime { get; set; }
}
}
There are so many possibilities in this situation and I can only give you a way to solve the problem.
First of all, we need to locate the reason why it is so slow. Is it the server or the client?
We can use packet capture tools such as Fiddler ,and then observe the corresponding network requests.
If client had send but server not response , you should think about the api limit...
And if not, the request are not send at all, may be you should the check the connection pool of the HttpClient, or the WorkThreadPool of dotnet.
there are a few problems with your question.
it doesn't compile.
it is incomplete.
it has sensitive data.
but I can get the data from API in no time. just open this link https://dotnetfiddle.net/ryjakT and run the program.
I changed few things
Return Type, it should be List
var result = new Holiday(); to var result = new List();
I am using Newtonsoft.Json for Deserialization.
you were trying to Deserialize to an incorrect model, it should be Root.

How to convert JArray to generic List<>

Via an http Post, I send html FormData to my Web Api2 controller.
The FormData contains one or more images, as well as client properties.
My front end Angular 5 service sends the http post (working fine):
var url = this.host + 'import/MediaUpload';
return this.http.post(url, formData, options)
.map((result: any) => result._body)
.catch(this.handleError);
I would like to convert the FormData to a generic List of MediaInfo class (defined below this MediaUpload() method) :
public async Task<HttpResponseMessage> MediaUpload(int projectId, int sectionId)
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
var provider = await Request.Content.ReadAsMultipartAsync<InMemoryMultipartFormDataStreamProvider>(new InMemoryMultipartFormDataStreamProvider());
//access form data
NameValueCollection formData = provider.FormData;
List<MediaInfo> listMedia = new List<MediaInfo>();
//dynamic jsonData = JObject.Parse(formData["MediaInfo"]); // THROWS ERROR
JArray ary = JArray.Parse(formData["MediaInfo"]);
foreach (var item in ary) {
//listMedia.Add((MediaInfo)item); // ???
Console.WriteLine(item);
}
//access files
IList<HttpContent> files = provider.Files;
HttpContent file1 = files[0];
var thisFileName = file1.Headers.ContentDisposition.FileName.Trim('\"');
// additional file upload code removed, working fine..
var response = Request.CreateResponse(HttpStatusCode.OK);
response.Headers.Add("DocsUrl", URL);
return response;
}
public class MediaInfo
{
public string PatientID { get; set; }
public string PatientFirstName { get; set; }
public string PatientLastName { get; set; }
public string PatientUID { get; set; }
public string PatientDOB { get; set; }
public string ExamDate { get; set; }
public string ExamDevice { get; set; }
public string SerialNo { get; set; }
public string Eye { get; set; }
public int DeviceID { get; set; }
public int CSIInstanceID { get; set; }
public int MediaNo { get; set; }
public string Procedure { get; set; }
public string FileName { get; set; }
public int FileSize { get; set; }
}
I thought I could do something like :
listMedia.Add((MediaInfo)item;
But I'm missing the correct conversion somewhere.
You can convert a JObject to a type of your choosing with the .ToObject<T>() method.
https://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Linq_JToken_ToObject__1_1.htm
In this case you want your code to look like this:
listMedia.Add(item.ToObject<MediaInfo>());
You could also use JsonConvert.DeserializeObject to convert it directly into the desired type provided formData["MediaInfo"] returned well formed JSON.
List<MediaInfo> listMedia = JsonConvert.DeserializeObject<List<MediaInfo>>(formData["MediaInfo"]);

how to convert list obj to client.PostAsJsonAsync

how to convert list obj to client.PostAsJsonAsync
Class model
public class CheckStatusModel
{
public int OBJID { get; set; }
public string SUPID { get; set; }
public string STATUSPTC { get; set; }
public int DATEACTIVESUP { get; set; }
}
public class CheckStatus
{
public CheckStatusModel Data { get; set; }
public string StatusCode { get; set; }
}
Sending request to find web api REST service resource using
HttpClient**
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsJsonAsync("api/RPDeployment/BIL_CFP_BOX_CHECK_STATUSPTC", checkStatusParam);
if(response.IsSuccessStatusCode)
{
var EmpResponse = response.Content.ReadAsStringAsync().Result;
ListStatusPTC = JsonConvert.DeserializeObject<List<CheckStatus>>(EmpResponse);// not convert ????
}
}
EmpResponse
{
"data": [**
{
"OBJID": 1012540462,
"SUPID": 1041252952,
"STATUSPTC": 1,
"DATEACTIVESUP": 0
}
**],
"StatusCode": 200
}
help me please ??
Oh I see. You're trying to deserialize an object (denoted by { and }) into a list (in JSON, denoted by [ and ]).
You need to change your CheckStatus class as follows:
public class CheckStatus
{
public List<CheckStatusModel> Data { get; set; } // data is an array so this needs to be some kind of collection
public string StatusCode { get; set; }
}
And deserialize like so:
ListStatusPTC = JsonConvert.DeserializeObject<CheckStatus>(EmpResponse); // the JSON contains an object, so this needs to deserialize to an object. you can't deserialize to a list.

RestSharp - Problems with Nested JSON data

I've tried other answers with people who had the same issue, but I can't get it to work. Plus I'm new to this. Any help is appreciated.
When I run this, my phone data is null.
Here's the JSON data I get back from my service.
{"GetDirectoriesResult":"[{\"id\":1,\"department\":\"Admitting\",\"subdepartment\":\"\",\"phone\":\"555-444-4013\",\"comments\":\"Press 1\"},{\"id\":2,\"department\":\"Ambulatory Surgery Center\",\"subdepartment\":\"\",\"phone\":\"555-444-4013\",\"comments\":\"\"}]"}
My Code
public class PhoneList
{
// public string GetDirectoriesResult { get; set; }
public List<Phone> Phones { get; set; } //- can't get this working
}
public class Phone
{
public int id { get; set; }
public string department { get; set; }
public string subdepartment { get; set; }
public string phone { get; set; }
public string comments { get; set; }
}
public IRestResponse<PhoneList> Execute<PhoneList>(RestRequest request) where PhoneList : new()
{
PhoneList ro = new PhoneList();
var client = new RestClient();
client.BaseUrl = BaseUrl;
// var request = new RestRequest();
request.RequestFormat = DataFormat.Json;
request.AddHeader("Content-Type", "application/json");
request.AddJsonBody(ro);
IRestResponse<PhoneList> response = client.Execute<PhoneList>(request);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var Exception = new ApplicationException(message, response.ErrorException);
throw Exception;
}
return response;
}

Categories