Xamarin.Forms HTTP Post to Web Service - 404 Error - c#

Sorry if this question has been asked already but I can not seem to find one that relates to my issue. I have a web service built using C# Asp.Net Web API, here I have the following POST method:
[HttpPost]
[Route("AddLocation")]
public void PostLocation(Locations model)
{
using (Entities db = new Entities())
{
C_btblFALocation newLocation = new C_btblFALocation()
{
cLocationCode = model.Code,
cLocationDesc = model.Description
};
db.C_btblFALocation.Add(newLocation);
db.SaveChanges();
}
}
In my Xamarin.Forms project I have my Rest Service Class:
public async Task SaveLocationAsync(Locations item)
{
var uri = new Uri(string.Format(Constants.LocationSaveRestUrl));
try
{
var json = JsonConvert.SerializeObject(item);
var content = new StringContent(json, Encoding.UTF8, "application/json");
HttpResponseMessage response = null;
response = await client.PostAsync(uri, content);
if (response.IsSuccessStatusCode)
{
Debug.WriteLine(#" Location successfully added.");
}
else
{
Debug.WriteLine(#" Oops, there seems to be a problem.");
}
}
catch (Exception ex)
{
Debug.WriteLine(#" ERROR {0}", ex.Message);
}
}
And my URL is set in my Constants class:
public static string LocationSaveRestUrl = "http://172.16.124.18/ArceusService/api/Assets/AddLocation/";
The problem is I keep getting a 404 error. I have tried every way I can think of to set the URL but no luck. The data seems to be passed through fine from debugging but I don't know how the URL should be for a POST method?
Thanks for any help!

How is your client variable declared? Usually you set a BaseAddress and in your Get/PostAsync you only set the actual resource URI.
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("http://something.com/api/");
var response = await client.GetAsync("resource/7");
}

Related

Getting 502 Bad gateway error while using facebook webhook for leadgen in asp.net Web Api

I'm trying to get facebook leads in Asp.Net Web Api by following this guide - https://medium.com/#somaraj/retrieving-facebook-lead-ads-using-asp-net-web-api-and-graph-api-web-hooks-70f6dd8bba4a
i have got all the permissions for leadgen and this is my Callback Url https://testing.harishparas.com/api/webhooks ,
enter image description here
and here i have used the Verify token same as the User token i have used in Post Api my Url is verified successfully but when i'm hitting it on the Postman it says enter image description here
502 error in the Post Api and enter image description here
500 Internal Error in the Get Api, i don't know where to set or pass the value of hub.challenge as i'm not setting it anywhere so Can you help me out with this please that what to do next to get the leadgen data in the Api.
Thanks in advance.
#region Get Request
[HttpGet]
public HttpResponseMessage Get()
{
var response = new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(HttpContext.Current.Request.QueryString["hub.challenge"])
};
response.Content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
return response;
}
#endregion Get Request
#region Post Request
[HttpPost]
public async Task<HttpResponseMessage> Post([FromBody] JsonData data)
{
try
{
var entry = data.Entry.FirstOrDefault();
var change = entry?.Changes.FirstOrDefault();
if (change == null) return new HttpResponseMessage(HttpStatusCode.BadRequest);
//Generate user access token here https://developers.facebook.com/tools/accesstoken/
const string token = "*************";
var leadUrl = $"https://graph.facebook.com/v9.0/{change.Value.LeadGenId}?access_token={token}";
var formUrl = $"https://graph.facebook.com/v9.0/{change.Value.FormId}?access_token={token}";
using (var httpClientLead = new HttpClient())
{
var response = await httpClientLead.GetStringAsync(formUrl);
if (!string.IsNullOrEmpty(response))
{
var jsonObjLead = JsonConvert.DeserializeObject<LeadFormData>(response);
//jsonObjLead.Name contains the lead ad name
//If response is valid get the field data
using (var httpClientFields = new HttpClient())
{
var responseFields = await httpClientFields.GetStringAsync(leadUrl);
if (!string.IsNullOrEmpty(responseFields))
{
var jsonObjFields = JsonConvert.DeserializeObject<LeadData>(responseFields);
//jsonObjFields.FieldData contains the field value
}
}
}
}
return new HttpResponseMessage(HttpStatusCode.OK);
}
catch (Exception ex)
{
//Console.WriteLine($"Error-->{ex.Message}");
//Console.WriteLine($"StackTrace-->{ex.StackTrace}");
Trace.WriteLine($"Error-->{ex.Message}");
Trace.WriteLine($"StackTrace-->{ex.StackTrace}");
return new HttpResponseMessage(HttpStatusCode.BadGateway);
}
}

Can't make Post requests to Web API

So I've looked around for an answer for this but nothing I've found even comes close to solving it.
I'm trying to set up a Post method on my Web API but no matter what I do it just gives me an internal server error.
I've tried adding [FromBody] (it's a simple type).
HttpClient client {get;set;}
public APICall()
{
client = new HttpClient
{
BaseAddress = new Uri("http://localhost:1472/api/")
};
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/x-protobuf"));
}
public void PostTimeTaken(long timeTaken)
{
var response = client.PostAsJsonAsync("Logging", timeTaken).Result;
if (!response.IsSuccessStatusCode)
{
Console.WriteLine(response.ReasonPhrase);
}
}
and then my controller action looks like this:
public void Post([FromBody] long timeTaken)
{
_api.DataBuilder.NumberOfAPICalls += 1;
_api.DataBuilder.ResponseTimes.Add(timeTaken);
}
I get no error message that could actually explain what's going on, just "Internal server error"
------SOLVED-------
Just in case anyone stumbles across this looking for the same answer, the issue was I was sending the data to the server in an incorrect format, it needed to be ProtoBuf serialised first, code snippet for anyone it might help:
public void PostToAPI(int ThingToSend)
{
using (var stream = new MemoryStream())
{
// serialize to stream
Serializer.Serialize(stream, ThingToSend);
stream.Seek(0, SeekOrigin.Begin);
// send data via HTTP
StreamContent streamContent = new StreamContent(stream);
streamContent.Headers.Add("Content-Type", "application/x-protobuf");
var response = client.PostAsync("Logging", streamContent);
Console.WriteLine(response.Result.IsSuccessStatusCode);
}
}
using (var client = new HttpClient())
{
string url = "http://localhost:7936";
client.BaseAddress = new Uri(url);
var jsonString = JsonConvert.SerializeObject(contentValue);
var content = new StringContent(jsonString, Encoding.UTF8, "application/json");
var result = await client.PostAsync("/Api/Logger/PostActionLog", content);
string resultContent = await result.Content.ReadAsStringAsync();
}
Have you tried to convert
long timeTaken to A model like;
public class TimeModel {
public long TimeTaken {get;set;}
}
public void Post([FromBody] TimeModel time){
// Do Stuff
}
Here the code of creating a simple server
baseUrl = "http://localhost:1472/"; // change based on your domain setting
using (WebApp.Start<StartUp>(url: baseUrl))
{
HttpClient client = new HttpClient();
var resp = client.GetAsync(baseUrl).Result;
}
Here some changes in your code
var requestData = new List<KeyValuePair<string, string>> // here
{
new KeyValuePair<string, string>( "Logging",timeTaken),
};
Console.WriteLine("request data : " + requestData);
FormUrlEncodedContent requestBody = newFormUrlEncodedContent(requestData);
var request = await client.PostAsync("here pass another server API", requestBody);
var response = await request.Content.ReadAsStringAsync();
Console.WriteLine("link response : " + response);
Pls add your controller
[HttpPost] // OWIN - Open Web Interface for .NET
public HttpResponseMessage Post([FromBody] long timeTaken)
{
_api.DataBuilder.NumberOfAPICalls += 1;
_api.DataBuilder.ResponseTimes.Add(timeTaken);
return Request.CreateResponse(HttpStatusCode.OK); //Using Post Method
}

Strange response from Asp.Net Web Api Post

I have a Asp.Net Web Api like the following
public async Task<IHttpActionResult> Post(Guid id, OrganisationModel model)
{
try
{
_orgService.AddNewOrganisationToParent(newOrg, org);
await Context.SaveChangesAsync();
return Ok(newOrg.Id);
}
catch (Exception ex)
{
Log.ErrorFormat("Problem creating new organisation {0}. Error {1}", UserId, ex);
return InternalServerError(ex);
}
}
When I call this from another Asp.Net Web application with the following;
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
var newOrg = Newtonsoft.Json.JsonConvert.SerializeObject(new
{
name = systemTree.Name,
type = 0
});
var content = new StringContent(newOrg.ToString(), Encoding.UTF8, "application/json");
var newOrgId = Guid.Empty;
using (var response = await client.PostAsJsonAsync(orgEndpoint + orgId, content))
{
response.EnsureSuccessStatusCode();
newOrgId = response.Content.ReadAsAsync<Guid>().Result;
}
The response is rather strange, the code shown throws and exception "exceptionMessage": "Unable to translate bytes [B4] at index 3 from specified code page to Unicode.",
If I read this as a string I get the following
"SJN4OMN4��MIK2�M574Ե0H6�500H1NL2J�4IR\u0002\0"
Is there something I am missing? Thanks in advance.

How can I use the access token to get a list of projects from a website in c#?

I am trying to create a C# console application to download project details from a website which supports REST OAuth 2.0. How do I make a request/response call to the website using the Access Token?
Here is my code:
public string token = "4bjskfa2-b37d-6244-8413-3358b18c91b6";
public async Task GetProjectsAsync()
{
try
{
HttpClient client = new HttpClient();
var projects = "https://app.rakenapp.com/api/v2/projects?" + token;
client.CancelPendingRequests();
HttpResponseMessage output = await client.GetAsync(projects);
if (output.IsSuccessStatusCode)
{
string response = await output.Content.ReadAsStringAsync();
project proj = JsonConvert.DeserializeObject<project>(response);
if (proj != null)
{
Console.WriteLine(proj.name); // You will get the projects here.
}
}
}
catch (Exception ex)
{
//catching the exception
}
}
you need to add a header to your request:
string url = "https://app.rakenapp.com/api/v2/projects";
using (var httpClient = new HttpClient())
{
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", authorizationToken);
HttpResponseMessage response = await httpClient.GetAsync(url);
var contents = await response.Content.ReadAsStringAsync();
var model = JsonConvert.DeserializeObject<project>.contents);
return model;
}

Access cloudant db using .Net HttpClient

I am attempting to connect to Cloudant (a couch-style DB) from a .Net MVC application. I am following the guidelines for consuming a web API using the HttpClient, as illustrated here:
http://www.asp.net/web-api/overview/web-api-clients/calling-a-web-api-from-a-net-client
I have two methods so far -- one to get a document and one to create a document -- and both have errors. The Get method returns Unauthorized and the Post method returns MethodNotAllowed.
The client is created like this:
private HttpClient CreateLdstnCouchClient()
{
// TODO: Consider using WebRequestHandler to set properties
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(_couchUrl);
// Accept JSON
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
return client;
}
The Get method is:
public override string GetDocumentJson(string id)
{
string url = "/" + id;
HttpResponseMessage response = new HttpResponseMessage();
string strContent = "";
using (var client = CreateLdstnCouchClient())
{
response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
strContent = response.Content.ReadAsStringAsync().Result;
}
else
{
// DEBUG
strContent = response.StatusCode.ToString();
LslTrace.Write("Failed to get data from couch");
}
}
return strContent;
}
The Post method is:
public override string CreateDocument(object serializableObject)
{
string url = CouchApi.CREATE_DOCUMENT_POST;
HttpResponseMessage response = new HttpResponseMessage();
string strContent = "";
using (var client = CreateLdstnCouchClient())
{
response = client.PostAsJsonAsync(url, serializableObject).Result;
strContent = response.Content.ReadAsStringAsync().Result;
}
if (response.IsSuccessStatusCode)
{
return strContent;
}
else
{
LslTrace.Write("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
return response.StatusCode.ToString();
}
}
URLs are per the API documentation: https://username:password#username.cloudant.com.
I am very confused by what is going on and having a lot of trouble finding examples. Thanks for your help!
Thomas
With the HttpClient, you need to do the following to authenticate correctly (assuming you use basic auth):
HttpClientHandler handler = new HttpClientHandler();
handler.Credentials = new NetworkCredential(_userName, _password);
HttpClient client = new HttpClient(handler) {
BaseAddress = new Uri(_couchUrl)
};
You should not specify the username/password in the _couchUrl - HttpClient doesn't support that.
I can't see your implementation of PostAsJsonAsync or the complete Url your are building, but you can try inspecting / logging response.ReasonPhrase when an error occurs to get a hint as to what went wrong.

Categories

Resources