I want to access data on the openrouteservice API - specifically the distance between two given coordinates on the globe - from my Android application.
I have made requests and gotten viable responses from another API that converts two given addresses into their latlong coordinates using the same style of code this request is trying to execute. It works fine, the coordinates arrive and i can further utilize them no problem.
My problem is that i seem to be accessing the API wrongly because if I Log the URL as seen below and copy it from the Debug window into my browser it sends the request, gets a response and shows it in the browser window.
But my application doesn't recieve a response from the API as the onResponse code bit is never executed and the "Fetch done" Log never appears in the actual Debug Log.
The following is my setup of code, which uses Volley to access HTTP Requests and which works fine for other APIs.
#Override
protected String doInBackground(String... strings) {
Log.d("Run =>","Query 3");
String targetKoordURL = null;
String startKoordURL = null;
try {
startKoordURL = startK.getString("lon").concat(",").concat(startK.getString("lat"));
targetKoordURL = targetK.getString("lon").concat(",").concat(targetK.getString("lat"));
} catch (JSONException e) {
e.printStackTrace();
}
String URLfin = "https://api.openrouteservice.org/v2/directions/driving-car?api_key=5b3ce3597851110001cf624823e587e7a80c4c6ab02af6d394585213&start="+startKoordURL+"&end="+targetKoordURL;
Log.d("Debug =>", URLfin);
JsonObjectRequest req = new JsonObjectRequest(Request.Method.GET, URLfin, null, new Response.Listener<JSONObject>() {
#Override
public void onResponse(JSONObject response) {
store = response;
Log.d("Run =>", "Fetch done!");
continueImp();
}
}, new Response.ErrorListener() {
#Override
public void onErrorResponse(VolleyError error) {
if(error instanceof TimeoutError || error instanceof NoConnectionError){
sideFetcherHTTPRequestStart replace = new sideFetcherHTTPRequestStart();
replace.execute();
Log.d("VOLLEY_ERROR", "Retrying on Kilometer request");
}
error.printStackTrace();
}
}){
#Override
public Map<String, String> getHeaders() throws AuthFailureError {
Map<String, String> params = new HashMap<String, String>();
params.put("Accept", "application/json,application/geo+json,application/gpx+xml,img/png; charset=utf-8");
return params;
}
};
return null;
}
You forget to add the request to request queue, try to do as following:
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
JsonObjectRequest req = new JsonObjectRequest(/*params*/);
//add above request to queue
queue.add(req);
Related
I'm trying to get a response from a simple protected Endpoint in the back end.
I've tested the Endpoint in Postman. I set up GET request with the KEY: Authorization and a VALUE: bearer eyxhsls...(this is the Jwt)
and the response gives me Status: 200 OK and the requested String. So everything works fine in the back end.
Now I want to replicate this process on the Client-side using Retrofit. Based on some research I using an OkHttpClient.Builder to insert the Jwt(String) into the header.
I try different things like simply inserting the Jwt(String) into header value:
Request.Builder newRequest = request.newBuilder().header("Authorization", bearerToken);
This returns a 401 status
I have also added the "Bearer " to the VALUE, just like I did in Postman, but the caller referred me to the onFailure method with the Message:
use jsonreader.setlenient(true) to accept malformed json at line 1 column 1
So I have added a GsonBuilder with setLeniet to the addConverterFactory. the caller again referred me to the onFailure method, but with the Message:
JSON document was not fully consumed.
Plz, let me know if anyone has a better idea, or understands what is going on. But stuck now for a number of days now.
public CoffeeController() {
okhttpBuilder = new OkHttpClient.Builder()
.addInterceptor(new Interceptor() {
#NonNull
#Override
public okhttp3.Response intercept(#NonNull Chain chain) throws IOException {
Request request = chain.request();
bearerToken = "Bearer " +LoginController.getToken();
bearerToken = LoginController.getToken();
Request.Builder newRequest = request.newBuilder().header("Authorization", bearerToken);
return chain.proceed(newRequest.build());
}
});
gson = new GsonBuilder()
.setLenient()
.create();
retrofit = new Retrofit.Builder()
.baseUrl("http://10.0.2.2:8080/")
.client(okhttpBuilder.build())
//.addConverterFactory(GsonConverterFactory.create())
.addConverterFactory(GsonConverterFactory.create(gson))
.build();
}
public static void CoffeeRead(Context context, TextView ResponseView) {
try {
CoffeeRepo repo = retrofit.create(CoffeeRepo.class);
Call<String> call = repo.Read();
call.enqueue(new Callback<String>() {
#Override
public void onResponse(Call<String> call, Response<String> response) {
message = "Read Coffee: " +"\nToken: " +bearerToken +"\nResponse: " + response.code();
ResponseView.setText(message);
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
#Override
public void onFailure(Call<String> call, Throwable t) {
message = "Failed to read coffee: \n" + t.getMessage();
ResponseView.setText(message);
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
});
} catch (Exception e) {
message = "Caught Exception: \n" + e.getMessage();
ResponseView.setText(message);
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
}
}
public interface CoffeeRepo {
#Headers({
"Cache-Control: max-age=3600",
"User-Agent: Android"
})
#GET("coffee")
Call<String> Read();
}
After I've added a logger, I found out the response was 200. After some research I found out I needed different ConverterFactory, instead of:
.addConverterFactory(ScalarsConverterFactory.create())
I used
.addConverterFactory(GsonConverterFactory.create(gson));
yesterday I wanted to implement the DidReceiveData method to my NSUrlSessionDataDelegate. I noticed that the DidReceiveData method never gets called, and while I tried to track down the error I noticed that the other methods don't get called either. I'm pretty sure that the other methods worked before, I don't know if I changed something or maybe a Xamarin.iOS update is the cause, but maybe I am wrong here and they never worked.
I can confirm this problem for the methods DidReceiveResponse, DidReceiveData, and DidCompleteWithError.
Here is the code that creates the NSUrlSession and handles the response (note: I call IIS WebMethods that answer in XML):
public async Task<string> Invoke(string sUrl)
{
session = NSUrlSession.FromConfiguration(NSUrlSessionConfiguration.DefaultSessionConfiguration,
(INSUrlSessionDelegate)new SessionDelegate((x)=> _fehlermeldung = x), // Übergebe Methode damit der SessionDelegate die Fehlermeldung weiterreichen kann
null);
request = CreateGETRequest(CreateNSUrl(sUrl));
var data = session.CreateDataTaskAsync(request, out dataTask);
dataTask.Resume();
NSUrlSessionDataTaskRequest response = null;
try
{
response = await data;
}
catch (NSErrorException ex)
{
throw new Exception(ex.Error.LocalizedDescription + ": " + _fehlermeldung);
}
var doc = new XmlDocument();
doc.LoadXml(response.Data.ToString());
XmlNode elem = doc.DocumentElement.FirstChild;
return elem.InnerText;
}
private NSUrl CreateNSUrl(string url)
{
string converted = ((NSString)url).CreateStringByAddingPercentEscapes(NSStringEncoding.UTF8);
var nsurl = NSUrl.FromString(converted);
if (nsurl == null)
throw new Exception("Fehlerhafte URL: Aus '" + url + "' konnte kein gültiges NSUrl Objekt erzeugt werden.");
return nsurl;
}
private NSMutableUrlRequest CreateGETRequest(NSUrl nsurl)
{
return new NSMutableUrlRequest(nsurl) { HttpMethod = "GET" };
}
And here is my implementation of the session delegate:
private class SessionDelegate : NSUrlSessionDataDelegate, INSUrlSessionDelegate
{
private readonly Action<string> setFehler;
public SessionDelegate(Action<string> setFehler)
{
this.setFehler = setFehler;
}
public override void DidReceiveResponse(NSUrlSession session, NSUrlSessionDataTask dataTask, NSUrlResponse response, Action<NSUrlSessionResponseDisposition> completionHandler)
{
var http_response = response as NSHttpUrlResponse;
if (http_response == null)
{
setFehler($"Keine HTTP Url Antwort erhalten: {Environment.NewLine}'{response}'");
completionHandler(NSUrlSessionResponseDisposition.Cancel);
return;
}
var status_code = (int)http_response.StatusCode;
if (status_code == 200)
{
completionHandler(NSUrlSessionResponseDisposition.Allow);
}
else
{
setFehler($"Verbindung abgewiesen, HTTP Status: { status_code}, '{ http_response.ToString()}'");
completionHandler(NSUrlSessionResponseDisposition.Cancel);
}
}
public override void DidReceiveData(NSUrlSession session, NSUrlSessionDataTask dataTask, NSData data)
{
// THIS DOES NOT GET CALLED :-(
}
public override void DidCompleteWithError(NSUrlSession session, NSUrlSessionTask task, NSError error)
{
if (error != null)
{
task.Cancel();
var ex = new NSErrorException(error);
throw (ex);
}
}
public override void DidReceiveChallenge(NSUrlSession session, NSUrlSessionTask task, NSUrlAuthenticationChallenge challenge, Action<NSUrlSessionAuthChallengeDisposition, NSUrlCredential> completionHandler)
{
[...] // This is working fine for Client Cert Authentication or Basic Authentication
}
}
The DidReceiveChallenge method does get called and is working. I cut it out for readability.
All the other methods don't get called. I would like to know what I am doing wrong. You can find the same questions from native iOS users, but I can't figure out how to implement their solutions with Xamarin.iOS.
Any help is appreciated, thanks in advance.
I have an Azure Web Job built using the Azure SDK whose only job is to call a web service (Web API) and then log a response based on the return value (a class). The problem is that as soon as it calls the HttpClient PostAsJsonAsync method to call the service, it exits out of the web job without executing any of the response handling. My code is:
public class Result
{
// Properties ---------------------------------------------------------
public bool Success { get; set; }
public string Error { get; set; }
}
public class Functions
{
// This function will be triggered based on the schedule you have set for this WebJob
// This function will enqueue a message on an Azure Queue called queue
[NoAutomaticTrigger]
public async static void ManualTrigger(TextWriter log, int value)
{
using (var client = new HttpClient())
{
var rootUrl = ConfigurationManager.AppSettings.Get("WebJobTargetUrl");
client.BaseAddress = new System.Uri(rootUrl);
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Console.WriteLine("Call service");
var response = await client.PostAsJsonAsync("api/Reminder/ProcessDueReminders", new { ItemID = 1 });
Console.WriteLine("After service");
var result = await response.Content.ReadAsAsync<Result>();
Console.WriteLine("After result");
if (result.Success)
Console.WriteLine("Reminders Processed");
else
Console.WriteLine("Reminder process error: " + result.Error);
}
}
}
and the execution logs from the portal are:
I believe it has something to do with the asynchronous operation but I can't figure out a pattern that will work. Any help would be appreciated.
You must define the return value of your own async method as Task instead of void.
On a related note, you should suffix the name of your method with Async. That's not going to solve the problem, but it indicates that you're using the async/await pattern.
There is probably an exception in your PostAsJsonAsync call. Try to put a try catch around it to and log the error:
try {
var response = await client.PostAsJsonAsync("api/Reminder/ProcessDueReminders", new { ItemID = 1 });
} catch (Exception ex){
Console.WriteLine("Exception: "+ ex);
}
Console.WriteLine("After service");
I am developping a BlackBerry application which communicates with the server via HTTP requests(javax.microedition.io.HttpConnection). On device, user clicks some UI items, and device sends the requests to server, when the response comes, UI changes. Communication takes place under new thread, while UI thread pushes and pops ProgressDialogScreen.
The problem is sometimes, when response comes and ProgressDialogScreen is popped, UI does not change but after couple seconds UI changes. If you have requested in between when ProgressDialogScreen is popped and when new Screen is pushed, there comes the mess. First oldest new Screen is pushed, and the newest new Screen is pushed. And this situation can be observed like server responsing wrong requests. This problems occur on simulator and device.
The other problem is, sometimes two same response returns for one request. I was able to see these two problems on simulator at the logs, but i have not able to see this issue on device since i can not see the logs.
EDIT:
String utf8Response;
HttpConnection httpConn = null;
try{
httpConn = (HttpConnection) Connector.open(url);
httpConn.setRequestMethod(HttpConnection.GET);
httpConn.setRequestProperty("Content-Type", "text/html; charset=UTF8");
if(sessionIdCookie != null){
//may throw IOException, if the connection is in the connected state.
httpConn.setRequestProperty("Cookie", sessionIdCookie);
}
}catch (Exception e) {
//...
}
try{
httpConn.getResponseCode();
return httpConn;
}catch (IOException e) {
// ...
}
byte[] responseStr = new byte[(int)httpConn.getLength()];
DataInputStream strm = httpConn.openDataInputStream();
strm.readFully(responseStr);
try{
strm.close();
}catch (IOException e) {
// ....
}
utf8Response = new String(responseStr, "UTF-8");
If this code successfully run, this piece of code runs and new screen is pushed:
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS);
if (accounts.size() == 0){
DialogBox.inform(Account.NO_DEPOSIT);
return;
}
currentScreen = new AccountListScreen(accounts);
changeScreen(null,currentScreen);
}
});
public void changeScreen(final AbstractScreen currentScreen,final AbstractScreen nextScreen) {
if (currentScreen != null)
UiApplication.getUiApplication().popScreen(currentScreen);
if (nextScreen != null)
UiApplication.getUiApplication().pushScreen(nextScreen);
}
EDITv2:
private static void progress(final Stoppable runThis, String text,boolean cancelable) {
progress = new ProgressBar(runThis, text,cancelable);
Thread threadToRun = new Thread() {
public void run() {
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
try{
UiApplication.getUiApplication().pushScreen(progress);
}catch(Exception e){
Logger.log(e);
}
}
});
try {
runThis.run();
} catch (Throwable t) {
t.printStackTrace();
}
UiApplication.getUiApplication().invokeLater(new Runnable() {
public void run() {
try {
UiApplication.getUiApplication().popScreen(progress);
} catch (Exception e) { }
}
});
}
};
threadToRun.start();
}
By the way ProgressBar is extended from net.rim.device.api.ui.container.PopupScreen and Stoppable is extended from Runnable
I preferred to pop progress bar after new Screen is prepared and pushed. This way there will be no new request between request and response.
Why not do:
private static void progress(final Stoppable runThis, String text,boolean cancelable) {
progress = new ProgressBar(runThis, text,cancelable);
UiApplication.getUiApplication().pushScreen(progress);
[...]
Seems like you are parsing on the UI Thread. Please remove Vector accounts = Parser.parse(utf8Response,Parser.ACCOUNTS); from ui thread and do it in a separate thread.
I have a WCF REST service that takes some parameters and sends an email. The template for the email is an MVC3 action. Essentially I want to render that action to a string.
If it were an ASP.NET WebForm, I could simply use Server.Execute(path, stringWriter, false). However when I plug in the path to my action, I get Error executing child request.
I have full access to HttpContext from my service (AspNetCompatibilityRequirementsMode.Allowed).
I know there are other answers out there for rendering actions to strings from within the context of a controller. How do I do this when I'm outside that world, but still on the same server (and, for that matter, in the same app)?
I cobbled together an answer based on several different google searches. It works, but I'm not 100% sure it's as lean as it could be. I'll paste the code for others to try.
string GetEmailText(TemplateParameters parameters) {
// Get the HttpContext
HttpContextBase httpContextBase =
new HttpContextWrapper(HttpContext.Current);
// Build the route data
var routeData = new RouteData();
routeData.Values.Add("controller", "EmailTemplate");
routeData.Values.Add("action", "Create");
// Create the controller context
var controllerContext = new ControllerContext(
new RequestContext(httpContextBase, routeData),
new EmailTemplateController());
var body = ((EmailTemplateController)controllerContext.Controller)
.Create(parameters).Capture(controllerContext);
return body;
}
// Using code from here:
// http://blog.approache.com/2010/11/render-any-aspnet-mvc-actionresult-to.html
public class ResponseCapture : IDisposable
{
private readonly HttpResponseBase response;
private readonly TextWriter originalWriter;
private StringWriter localWriter;
public ResponseCapture(HttpResponseBase response)
{
this.response = response;
originalWriter = response.Output;
localWriter = new StringWriter();
response.Output = localWriter;
}
public override string ToString()
{
localWriter.Flush();
return localWriter.ToString();
}
public void Dispose()
{
if (localWriter != null)
{
localWriter.Dispose();
localWriter = null;
response.Output = originalWriter;
}
}
}
public static class ActionResultExtensions
{
public static string Capture(this ActionResult result, ControllerContext controllerContext)
{
using (var it = new ResponseCapture(controllerContext.RequestContext.HttpContext.Response))
{
result.ExecuteResult(controllerContext);
return it.ToString();
}
}
}