How to use singleton class for get and Post the json values in xamarin forms? - xamarin.forms

I developing a xamarin application using singleton based to get the server values. Searched the example by StackOverflow in this site(Show List in Xamarin consuming REST API). but I have small doubts about this. no one reply to my comment to this question.
My Code:
public async Task<Response> GetList<T>(string urlBase, string servicePrefix, string controller)
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(urlBase);
var url = string.Format("{0}{1}", servicePrefix, controller);
var response = await client.GetAsync(url);
var result = await response.Content.ReadAsStringAsync();
if (!response.IsSuccessStatusCode)
{
return new Response
{
IsSuccess = false,
Message = result,
};
}
var list = JsonConvert.DeserializeObject<List<T>>(result);
return new Response
{
IsSuccess = true,
Message = "Ok",
Result = list,
};
}
catch (Exception ex)
{
return new Response
{
IsSuccess = false,
Message = ex.Message,
};
}
}
My doubt what is Response in this code. It is a separate class or HTTP response message. but I changed the HTTP response message, it gives an error in the above-declared variables(Success, Message).

Response is a Custom class like following code,.It contails three properties.
public class Response
{
public bool IsSuccess { get; set; }
public string Message { get; set; }
public object Result { get; set; }
}

Related

Object is null after JsonConvert.DeserializeObject

I have looked at some forum posts and found no solution to my problem, so now I ask you for help. First i show you what the result of my HttpGet is and then i show you the not working deserialization.
Working example: I use the same code for an HttpGet to get a json result.
[HttpGet]
[Route("~/get_new_authtoken")]
public async Task<IActionResult> GetNewAuthTokenAsync()
{
try
{
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://testApi/WebService/");
string APIConnection = _configuration.GetValue<string>("APIConnection");
HttpResponseMessage response = client.PostAsync("authtoken", new StringContent(string.Format(APIConnection))).Result;
if (response.IsSuccessStatusCode)
{
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
}
catch (Exception ex)
{
SentrySdk.CaptureException(ex);
return Ok(ex.Message);
}
}
with following result when i call it via Postman
Not working deserialization: I store the token in a database and want to update it when it expires.
Object i want to desiralize in:
public class AuthToken
{
[JsonPropertyName("access_token")] public string AccessToken { get; set; }
[JsonPropertyName("refresh_token")] public string RefreshToken { get; set; }
[JsonPropertyName("token_type")] public string TokenType { get; set; }
[JsonPropertyName("expires_in")] public int ExpiresIn { get; set; }
}
when i add the following code to the httpget above to test the deserializationthe object Authtoken is always null.
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
Like this->
if (response.IsSuccessStatusCode)
{
//To test
AuthToken newAccessToken = new AuthToken();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
//To test
var token = JsonConvert.DeserializeObject<AuthToken>(await response.Content.ReadAsStringAsync());
return Ok(response.Content.ReadAsStringAsync().Result);
}
else
{
return BadRequest(response.Content.ReadAsStringAsync().Result);
}
Updated the testint to following code:
AuthToken newAccessToken = new AuthToken();
var responseString = await response.Content.ReadAsStringAsync();
newAccessToken = JsonConvert.DeserializeObject<AuthToken>(responseString);
result of the responseString:
JsonPropertyNameAttribute is from System.Text.Json while JsonConvert.DeserializeObject is part of Newtonsoft.Json either switch to former completely by using System.Text.Json.JsonSerializer.Deserialize:
AuthToken newAccessToken = JsonSerializer.Deserialize<AuthToken>(...);
// or just use ReadFromJsonAsync instead of ReadAsStringAsync
Or use attributes for latter:
public class AuthToken
{
[JsonProperty("access_token")]
public string AccessToken { get; set; }
// ...
}

Call a rest web api in asp.net and receive error

Hi I want to call a rest Web Api and I use asp.net MVC+Web Api.
I write a get Token Method like below :
public TokenViewModel GetToken()
{
//string Result = string.Empty;
TokenViewModel token = null;
string baseAddress = "http://$$$$$$$$$$/api/security/login";
using (HttpClient client = new HttpClient())
{
try
{
var url = new Uri(baseAddress);
MultipartFormDataContent form = new MultipartFormDataContent();
Dictionary<string, string> parameters = new Dictionary<string, string>();
parameters.Add("UserName", "###");
parameters.Add("Password", "$$$");
HttpContent DictionaryItems = new FormUrlEncodedContent(parameters);
form.Add(DictionaryItems, "model");
var response = client.PostAsync(url.ToString(), form, System.Threading.CancellationToken.None);
if (response.Result.StatusCode == System.Net.HttpStatusCode.OK)
{
//Get body
var bodyRes = response.Result.Content.ReadAsStringAsync().Result;
token = JsonConvert.DeserializeObject<TokenViewModel>(bodyRes);
//Get Header
// var headers = response.Result.Headers.GetValues("appToken");
}
else
{
var a = response.Result.Content.ReadAsStringAsync().Result;
}
}
catch (Exception ex)
{
}
return token;
}
}
And also webController:
namespace WebAPI.Controllers
{
public class WebApiController : ApiController
{
private readonly GetToken_BLL _tokenService;
public WebApiController(GetToken_BLL tokenService)
{
_tokenService = tokenService;
}
public object Verfiybll { get; private set; }
public class stcAPIMessage
{
public string Message { get; set; }
public HttpStatusCode StatusCode { get; set; }
}
[HttpPost]
[Route("api/Token")]
public IHttpActionResult Token()
{
stcAPIMessage message = new stcAPIMessage();
GetToken_BLL tokenbll = new GetToken_BLL();
var result = tokenbll.GetToken();
if (result == null)
{
message.Message = "error in recieveing token";
message.StatusCode = HttpStatusCode.BadRequest;
return Content(message.StatusCode, message.Message);
}
else if (string.IsNullOrEmpty(result.Token))
{
message.Message = "Error";
message.StatusCode = HttpStatusCode.BadRequest;
return Content(message.StatusCode, message.Message);
}
return Ok(result);
}
}
}
When I run the program it throw out error:
An error occurred when trying to create a controller of type 'Web ApiController'.
Make sure that the controller has a parameter less public constructor.
System. Invalid Operation Exception Type 'WebAPI.Controllers.
Web ApiController' does not have a default constructor
System.
The parameter less constructor error is common in ASP.NET web applications that use dependency injection.
I have noticed there is a constructor parameter being used:
GetToken_BLL _tokenService
Use a dependency injection resolver for the type GetToken_BLL so that the parameter _tokenService can be instantiated.

Error retrieving data from Api Controller

I'm working on an ASP.NET Core Api and Xamarin forms client using Visual Studio 2017.
I'm getting an error
System.Runtime.Serialization.SerializationException: Invalid JSON string
because response.Content is null, when retrieving data from API but when paste this Url in browser "https://localhost:44305/api/Agreement/GetAgreementText/1" it shows data in the browser. When I run using client it's not hit to api method debug point .
Here is my APi method
[HttpGet]
[Route("GetAgreementText/{id}")]
public DefaultApiResult GetAgreementText(long Id)
{
Company com = _companyRepository.Get(Id);
string st = com.AgreementText;
DefaultApiResult result = new DefaultApiResult
{
Data = st
};
return result;
}
Here is my client application Api invoking method
public string GetAgreementTextLoading(long idCompany)
{
string agreementText = "";
// var token = _tokenService.GetLastActivateToken().Hash;
var clientURL = "https://localhost:44305/";
var client = new RestClient(clientURL);
var request = new RestRequest("api/Agreement/GetAgreementText/{Id}", Method.GET);
request.AddUrlSegment("Id", idCompany.ToString());
IRestResponse response = client.Execute(request);
AppRestResponse apiResponse = SimpleJson.DeserializeObject<AppRestResponse>(response.Content);
var statusMessage = "";
if (apiResponse.Success)
{
statusMessage = "Success.";
if (!string.IsNullOrEmpty(response.Content))
{
agreementText = apiResponse.Data.ToString();
}
else
{
throw new Exception("Invalid response");
}
}
else
{
agreementText = "Error retrieving agreement text";
}
return agreementText;
}
public class AppRestResponse
{
public bool Success { get; set; }
public object Data { get; set; }
public IEnumerable<AppRestReponseError> ErrorMessages { get; set; }
}
public class DefaultApiResult
{
public bool Success
{
get
{
return ErrorMessages.Count == 0;
}
private set { }
}
public List<ErrorMessage> ErrorMessages { get; set; }
public object Data { get; set; }
public DefaultApiResult()
{
ErrorMessages = new List<ErrorMessage>();
}
public DefaultApiResult(string errorMessage)
:this()
{
ErrorMessages.Add(new ErrorMessage()
{
Message = errorMessage
});
}
public DefaultApiResult(string[] errorMessages)
:this()
{
foreach (var errorMessage in errorMessages)
{
ErrorMessages.Add(new ErrorMessage()
{
Message = errorMessage
});
}
}
}
I'm not sure about the SimpleJson and the rest client you are using .
However , assuming you're using the RestSharp , it seems that there's no need to use the SimpleJson to deserialize response here .
I just remove the following codes :
IRestResponse response = client.Execute(request);
AppRestResponse apiResponse = SimpleJson.DeserializeObject<AppRestResponse>(response.Content);
and add the following two lines:
IRestResponse<AppRestResponse> response = client.Execute<AppRestResponse>(request);
var apiResponse= response.Data;
It works as expected .

ASP.NET MVC Controller Method GET to external API

I have an external api that is hosted on a different domain for now we can use the following url as an example
https://myapi.mydomain/api/data
This API returns the following data
{"data":[
{
"id":1,
"company":"JUST A DEMO",
"ext_identifier":"DEMO1"
},
{
"id":2,
"company":"ANOTHER DEMO",
"ext_identifier":"DEMO2"
}
]}
I need to call a controller method that does the GET request against this API and then returns the JSON data for me to consume.
So far I have the following code, I think I am close....
Here is the controller code
string url = "https://myapi.mydomain/";
[HttpGet]
public async Task<ActionResult> Search()
{
CustomerList customers = null;
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// New code:
HttpResponseMessage response = await client.GetAsync("api/data");
if (response.IsSuccessStatusCode)
{
customers = await response.Content.ReadAsAsync<CustomerList>();
}
}
return Json(new
{
data = customers
},
JsonRequestBehavior.AllowGet);
}
public class CustomerList
{
public int id { get; set; }
public string company { get; set; }
public string ext_identifier { get; set; }
}
Why is it that when I ask a question 10 minutes later I come up with the answer so here it is if anyone is interested.
This seems to be the most elegant solution I can come up with but if anyone has any improvements please let me know thanks.
[HttpGet]
public async Task<ActionResult> GetCustomers()
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(customerApi);
if (response.IsSuccessStatusCode)
{
string jsondata = await response.Content.ReadAsStringAsync();
return Content(jsondata, "application/json");
}
return Json(1, JsonRequestBehavior.AllowGet);
}
}

ASP.NET Web API send JSON array

I am using ASP.NET Web API and I want to send a list of objects as a JSON array but keep receiving
"The remote server returned an error: (400) Bad Request."
When I send a single object it works fine.
Here's my code:
"Server" Side Code:
public class Trigger
{
public string TriggerID { get; set; }[Required]
public string TriggerName { get; set; }[Required]
public string TriggerDescription { get; set; }
}
public class TriggersController : Controller
{
[HttpPost]
public HttpResponseMessage AddTriggers(IQueryable<Trigger> TriggerEvent)
{
if (SetUserDetails())
{
if (ModelState.IsValid)
{
return _repository.AddTriggers(TriggerEvent);
}
else
{
return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
}
}
else
{
throw new HttpResponseException(new HttpResponseMessage(System.Net.HttpStatusCode.Unauthorized) { Content = new StringContent("Incorrect token") });
}
}
}
"Client" side Code:
string JSON = [{"TriggerID":"1","TriggerName":"My 1 Event","TriggerDescription":"This is my 1 event"},{"TriggerID":"2","TriggerName":"My 2 Event","TriggerDescription":"This is my 2 event"}]
public string AddTrigger(string URL, string JSON)
{
string ret = string.Empty;
StreamWriter requestWriter;
var webRequest = System.Net.WebRequest.Create(URL) as HttpWebRequest;
if (webRequest != null)
{
webRequest.Headers.Add("Authorization-Token", AuthenticationCode);
webRequest.Method = "POST";
webRequest.ContentType = "application/json";
//POST the data.
using (requestWriter = new StreamWriter(webRequest.GetRequestStream()))
{
requestWriter.Write(JSON);
}
}
HttpWebResponse resp = (HttpWebResponse)webRequest.GetResponse();
Stream resStream = resp.GetResponseStream();
StreamReader reader = new StreamReader(resStream);
ret = reader.ReadToEnd();
return ret;
}
OK, found my mistake, should use IEnumerable instead of IQueryable and everything works fine.

Resources