I am using the Facebook C# SDK in my Silverlight 4 browser app to perform some requests to the Facebook Graph API. I followed the example in the SDK documentation to request the user's information (using the asynchronous method to make it work on Silverlight):
var fb = new FacebookClient(accessToken);
fb.GetAsync("/me");
fb.GetCompleted += (o, ea) =>
{
var result = (JsonObject)ea.GetResultData();
var name = (string)result["name"];
};
This way I get the JsonObject without any problem and I can read all data, but when I make request to "me/feed" or "me/home" instead of "/me":
fb.GetAsync("/me/home");
fb.GetCompleted += (o, ea) =>
{
var result = (JsonObject)ea.GetResultData();
var data = (JsonArray) result["data"];
foreach (JsonObject post in data)
{
id = (string)post["id"];
}
};
then the JsonObject is empty and I get a exception when trying to access its elements. I successfully managed to POST a message to "me/feed", but why do I receive an empty response when making a GET request? I have set the access token in the FacebookClient I'm using to make the calls, is there something else that I'm missing?
Thanks!
Related
Good morning,
I am trying to develop a webapp using Blazor and Net5. I have successfully implemented the 3 legged authentication system and attached the token to the default header for further requests.
I have implemented also the 2 legged authentication request in the same process and saved both in the local storage.
Now I need to start to call some Data Management service to store and retrieve models and also submit work items to design automation. All of these will require to send the bearer token together with the request.
I would like to manage this bit of the application on the server side and the question is: is there a way to use the token on the server side other then just try to retrieve that from the local storage?
Also, is is possible to setup two different HttpClient in the client app to be able to attach two different tokens and then use the same http client in the server-side Blazor? I assume I can not inject a service from the client to the server thou.
I can easily do it in the client side using DI
public async Task<string> PostSignedUrlAsync(string bucketKey, string objectKey)
{
using (var client = new HttpClient())
{
var token = await tokenManager.GetTwoFactorAsync();
using (var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://{configurationManager.Host}/oss/v2/buckets/{bucketKey}/objects/{objectKey}/signed"
)
)
{
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token);
using (var response = await client.SendAsync(request))
{
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<PostObjectSigned>(json).SignedUrl;
}
}
return null;
}
}
}
public async Task PostTwoFactorAsync()
{
using (var client = new HttpClient())
{
using (var request = new HttpRequestMessage(
HttpMethod.Post,
$"https://{configurationManager.Host}/authentication/v1/authenticate"
)
)
{
var body = $"client_id={configurationManager.ClientId}&client_secret={configurationManager.ClientSecret}&grant_type=client_credentials&scope={configurationManager.ScopesInternal}";
request.Content = new StringContent(body, Encoding.UTF8, "application/x-www-form-urlencoded");
using (var response = await client.SendAsync(request))
{
if (response.IsSuccessStatusCode)
{
var json = await response.Content.ReadAsStringAsync();
TokenInternal = JsonConvert.DeserializeObject<Token>(json);
TokenInternal.ExpiresOn = DateTime.UtcNow.AddSeconds(TokenInternal.ExpiresIn) - TimeSpan.FromMinutes(10);
await localStorage.SetItemAsync(configurationManager.LocalStorageKeyInternal, TokenInternal);
}
}
}
}
}
Maybe is a simple question with a simple answer but I can't find any example that can explain how to solve this "connection" and there are now example in the Forge documentation around Blazor implementation that are suitable for this task.
Thanks in advance
Firstly, please don't call APIs from client side, send the token with only scope: viewables:read for viewing in forge viewer. Other than this, call all the forge APIs from server side. This is for security reasons. Because if you send and store tokens to client side, it's easy to get access to your resources for any client.
Regarding token scopes please refer these links:
Documentation
Tutorial
I'm trying to code a middleman API that logs calls and other details from internal users to an external API.
When I try to POST to the external API from my Controller, I get 415 unsupported media type.
I set up my client in the controller constructor like this:
client.BaseAddress = new Uri("https://restapi.***.com/customers/");
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("X-AppSecretToken", Auth.APPSECRETTOKEN);
client.DefaultRequestHeaders.Add("X-AgreementGrantToken", Auth.AGREEMENTGRANTTOKEN);
My POST method looks like this:
var json = JsonConvert.SerializeObject(customer, Formatting.Indented);
using (var stringContent = new StringContent(json))
{
stringContent.Headers.ContentType.CharSet = "";
HttpResponseMessage response = await client.PostAsync(client.BaseAddress, stringContent);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
}
return CreatedAtAction("GetCustomer", new { id = customer.ID }, customer);
I've been looking around and found a lot of comments telling me to use Stringcontent, but I also found a couple of responses saying ByteArrayContent - none of them work.
Can anyone help me?
EDIT: When I run the code with breakpoints it seems like some of the properties in the incoming customer object are set even though I didn't set them in my Postman call.
Example; the external API returns a customernumber when I give it the 5 properties that are obligatory. But when I call my internal API from Postman, sending only those 5 obligatory properties, it autopopulates the customernumber with a 0.
Could this be the source of the error? and how do I tell .net core to not autopopulate the customernumber?
EDIT2: I changed my stringContent to include encoding and used a different overload, so the using line now says
using (var stringContent = new StringContent(json, Encoding.UTF8, "application/json"))
And I removed
stringContent.Headers.ContentType.Charset = "";
to reflect the fact that I tried setting the encoding.
The return code changed from 415 to 400 Bad Request when I changed that.
EDIT3:
Tried NOT serializing with Json.Net, and instead used JObjects and Jproperties;
public async Task<ActionResult<Customer>> PostCustomer([FromBody]Customer customer)
{
JObject payload = new JObject(
new JProperty("currency", customer.Currency),
new JProperty("name", customer.Name),
new JProperty("customergroup",
new JObject(new JProperty("customergroupNumber",
customer.CustomerGroup.CustomerGroupNumber)
)),
new JProperty("paymentTerms",
new JObject(new JProperty("paymentTermsNumber",
customer.PaymentTerms.PaymentTermsNumber)
)),
new JProperty("vatZone",
new JObject(new JProperty("vatZoneNumber",
customer.VatZone.VatZoneNumber)
))
);
using (var stringContent = new StringContent(payload.ToString(), Encoding.UTF8, "application/json"))
{
HttpResponseMessage response = await client.PostAsync(client.BaseAddress, stringContent);
if (!response.IsSuccessStatusCode)
{
return StatusCode((int)response.StatusCode);
}
}
return CreatedAtAction("GetCustomer", new { id = customer.CustomerNumber }, customer);
}
Still 400 Bad Request
This is a case of capitalizing - simple really.
My POST request JSON had an object named customergroup - changed it to customerGroup, and it worked.
I'm trying to get some custom columns values (longitude,latitude) from ASPNetUsers Table from the DB , When I send a Get request throw browser I get a 200 ok with the requested json .. but when I try to use GetStringAsync to deserialize the response in my xamarin app I don't get any response .
In AccountController class
// POST api/Account/GetUserPostion
[Route("GetUserPostion")]
public LocationDataToPostAsync GetUserPostion()
{
var store = new UserStore<ApplicationUser>(new ApplicationDbContext());
var manager = new ApplicationUserManager(store);
LocationDataToPostAsync locationData = new LocationDataToPostAsync();
var model = manager.FindById(User.Identity.GetUserId());
locationData.UserId = User.Identity.GetUserId();
if (model.Longitude != null) locationData.Longitude = (double) model.Longitude;
if (model.Latitude != null) locationData.Latitude = (double) model.Latitude;
return locationData;
}
In ApiService class in xamarin forms app
public async Task<LocationDataToPostAsync> GetUserLocationAsync(string accessToken)
{
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
var json = await client.GetStringAsync("http://10.0.2.2:45455/api/Account/GetUserPostion");
var location = JsonConvert.DeserializeObject<LocationDataToPostAsync>(json);
return location;
}
It is unclear from your code if the Task is awaited or you are calling .Result or .GetAwaiter().GetResult() on the Task. However, as we found out in the comments adding .ConfigureAwait(false) fixed your issue.
This indicates that the code cannot return to the context it came from, so adding .ConfigureAwait(false) the code doesn't return to the context.
In your case the context is probably the UI thread and when it tries to return the UI thread is blocked.
The most likely scenario why the UI Thread is block is because you called your Task in a wrong manner. If you call it with .Result on the UI thread you are synchronously blocking the UI thread, hence anything that tries to return to the UI thread, will deadlock, since you are blocking that.
The easy fix here is to just add .ConfigureAwait(false) in your code. The better solution would be not to block the UI thread by awaiting the Task.
Hello im new developing using the framework7 in order to make an app, my problem is when i connect to the webservices i send this in my controller.js
var postdata = {};
postdata.cantidad = cantidad;
postdata.ultimoValor = ultimoValor;
postdata.id = id;
myApp.showIndicator();
$$.post('http://192.168.0.134:8090/Test.asmx/GetCliente', {cantidad:'5', ultimoValor:'0',id:'0'}, function (data) {
myApp.hideIndicator();
console.log(data);
});
The "data" receives the response and the console prints in xml,
and what i need is json to use it.
How can i change it?
i would be great if you can explain me with an example?
I am using ServiceStack to create a C# client to a JSON RESTful service. I have this code that returns my DTO:
Search result = restClient.Get (search);
This works fine, but in order to effectively debug the search results coming back I need to output the text content from the underlying HTTP Response object. (I don't know all the elements in the response yet in order to add them to the DTO).
Is there any way I can get hold of the underlying HTTP response, and thus the full text content, from my result object?
Thanks in advance.
#adamfowleruk
When inheriting from ServiceStack's built-in Service you can access the underlying Request and Response directly from the Response class with:
public class MyService : Service
{
public object Get(Request request)
{
base.Request ...
base.Response ...
}
}
You won't see the response output in your service or filters since it writes directly to the response stream and is the last thing that ServiceStack does after executing your service and all response filters.
For diagnosing HTTP I recommend using Fiddler or WebInspector also ServiceStack's built-in Request Logger might help as well.
Consuming a ServiceStack service
If you're using the C# Service Clients you can simply ask for what you want, e.g. you can access the returned response as a raw string:
string responseJson = client.Get<string>("/poco/World");
Or as raw bytes:
byte[] responseBytes = client.Get<byte[]>("/poco/World");
Or as a Stream:
using (Stream responseStream = client.Get<Stream>("/poco/World")) {
var dto = responseStream.ReadFully().FromUtf8Bytes().FromJson<PocoResponse>();
}
Or even access the populated HttpWebResponse object:
HttpWebResponse webResponse = client.Get<HttpWebResponse>("/poco/World");
webResponse.Headers["X-Response"] //World
using (webResponse)
using (var stream = webResponse.GetResponseStream())
using (var sr = new StreamReader(stream)) {
string response = sr.ReadToEnd();
}
You can also introspect the HttpWebResponse by using Global and Local Response filters, e.g:
JsonServiceClient.HttpWebResponseFilter = httpRes => { .. };
Or using a Local filter:
var client = new JsonServiceClient(baseUrl) {
ResponseFilter = httpRes => { .. }
};
Consuming a 3rd Party Service
If you're consuming a 3rd Party REST/HTTP API you can use a responseFilter: in ServiceStack's HTTP Util extensions:
List<GithubRepo> repos = "https://api.github.com/users/{0}/repos".Fmt(user)
.GetJsonFromUrl(responseFilter: httpRes => {
var remaining = httpRes.Headers["X-Api-Remaining"];
})
.FromJson<List<GithubRepo>>();
I use Fiddler to debug my services. It gives you all sorts of cool HTTP debugging facilities.
http://www.fiddler2.com/fiddler2/
I like to use RestConsole. It is a Chrome Extension and you can easily submit POST requests and see the response. It is also handy to create sample data and then step into the ServiceStack code and see what's happening. The ServiceStack PluralSight course has a nice demo of how to use them together.
Thanks to the above help I found the right answer. Documenting here for others:-
SearchResponse result = null; // my ServiceStack DTO
HttpWebResponse webResponse = restClient.Get<HttpWebResponse>(
completePath("/v1/search",qp)); // builds the URL with parameters
using (var stream = webResponse.GetResponseStream())
using (var sr = new StreamReader(stream)) {
var text = sr.ReadToEnd();
log.log ("response text: " + text); // *** PRINTING STRING VALUE HERE FOR DEBUG
result = text.FromJson<SearchResponse>();
}
// Now do something useful with the result DTO object
log.log ("RESULT: " + result.ToString ());
for (int i = 0; i < result.Results.Length; i++) {
log.log ("Result " + i + ": " + result.Results[i].ToString());
}