Hello All I am using Azure's vision analyze api to extract text from my documents,
here is the example code for your reference
//My main function fi.fullfile is the path of my uploaded document
AzureAnalyzeRequest(System.IO.File.ReadAllBytes(fi.FullName));
analyze function
static async void AzureAnalyzeRequest(byte[] byteData)
{
var client = new HttpClient();
var queryString = HttpUtility.ParseQueryString(string.Empty);
// Request headers
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "MyKey");
// Request parameters
queryString["language"] = "en";
queryString["pages"] = "1,2";
var uri = "https://url-ocr.cognitiveservices.azure.com/vision/v3.2/read/analyze?" + queryString;
HttpResponseMessage response;
using (var content = new ByteArrayContent(byteData))
{
content.Headers.ContentType = new MediaTypeHeaderValue("application/json");
response = await client.PostAsync(uri, content);
}
}
when the above function executed I am getting the error of 400 bad request
but when I tested my api on the below URL
Azure Vision api
it worked fine.
what I am doing wrong here?
According to this MSDOCS the api needs a Json object in the following form:
{
"url":""
}
I think you are passing a byte array, you need a Json object which will contain a URL of the image you want to process.
So here I have created a class called Poco which will host the URL variable.
public class Poco
{
public string url { get; set; }
}
Then I initialized the class and passed the URL then convert that object into a Json object.
Poco p = new Poco();
p.url = "<URL OF YOUR IMAGE>";
string json = JsonConvert.SerializeObject(p);
// Here we are converting the json string to stringcontent which we can pass to httpclient
StringContent data = new StringContent(json, Encoding.UTF8, "application/json");
Now all you have to do is call the Api:
HttpClient client = new HttpClient();
client.DefaultRequestHeaders.Add("Ocp-Apim-Subscription-Key", "<YOURKEY>");
var response = client.PostAsync(url, data);
Console.WriteLine(response.Result.StatusCode);
Console.WriteLine(response.Result);
If you want to use the byte array of image, then I think the content-type header should be application/octet-stream according to this MSDOC
Related
I can create a custom domain using the Azure Management REST API, and I can create an App Service Managed certificate, which is associated with the custom domain (I think). Maybe not. However, under custom domains in my app service, it shows that I need to add a binding.
Here is the certificate:
https://management.azure.com/subscriptions/xxx-xxx-479a-bb9f-4c7e01d9a379/resourceGroups/MyResourceGroup/providers/Microsoft.Web/sites/xxx20211028195113/hostNameBindings/my.site?api-version=2016-08-01
and
https://management.azure.com/subscriptions/xxx-xxx-479a-bb9f-4c7e01d9a379/resourceGroups/MyResourceGroup/providers/Microsoft.Web/certificates/my.site?api-version=2021-02-01
I used the first end-point to create the custom domain, and the second end-point to create the certificate. I'm not sure how to bind the certificate to the custom domain. I expected the call to create certificate to do that for me since I included the serverFarm in the request body, but it didn't work.
I want to use the Azure Management API to bind the certificate to the custom domain. How can I do that? which endpoint should I use and what values need to be set in the request body?
Any help would be appreciated. Thanks.
For my full code reference, see my other post here:
C# .Net Azure Management REST API - Add App Service Managed Certificate - Response = Not Found
EDIT: Showing the Complete Answer
using Microsoft.Extensions.Configuration;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using System;
using System.Net.Http;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace MyShoppingCart.Helpers.ManagementLibrarySample
{
public class ManagementLibrarySample
{
static string _ClientId = Startup.StaticConfig.GetValue<string>("Azure:ClientId");
static string _ClientKey = Startup.StaticConfig.GetValue<string>("Azure:ClientSecret");
static string _TenantId = Startup.StaticConfig.GetValue<string>("Azure:TenantId");
static string _SubscriptionId = Startup.StaticConfig.GetValue<string>("Azure:SubscriptionId");
static string _ResourceGroupName = Startup.StaticConfig.GetValue<string>("Azure:ResourceGroupName");
static string _AlternateResourceGroupName = Startup.StaticConfig.GetValue<string>("Azure:AlternateResourceGroupName");
static string _AppName = Startup.StaticConfig.GetValue<string>("Azure:AppName");
static string _AppServicePlanName = Startup.StaticConfig.GetValue<string>("Azure:AppServicePlanName");
static Uri _baseURI = new Uri($"https://management.azure.com/");
private static string GetAccessToken()
{
var context = new AuthenticationContext("https://login.windows.net/" + _TenantId);
ClientCredential clientCredential = new ClientCredential(_ClientId, _ClientKey);
var tokenResponse = context.AcquireTokenAsync(_baseURI.ToString(), clientCredential).Result;
return tokenResponse.AccessToken;
}
public static async Task<bool> CreateCustomDomainAndCertificate(string sHostName)
{
bool ret = false;
HttpResponseMessage responseMessage = await CreateCustomDomain(sHostName);
if (responseMessage.IsSuccessStatusCode)
{
responseMessage = await CreateAppManagedCertificate(sHostName);
/*
it can take a good 5 minutes to create the certificate
but you get the 202 status code right away.
You cannot bind the certificate to the custom domain
name until after the certificate actually exists.
*/
if ((long)responseMessage.StatusCode == 202)// Accepted
{
DateTime dtStart = DateTime.Now;
while ((long)responseMessage.StatusCode != 200 && DateTime.Now < dtStart.AddMinutes(10))
{//Wait until the certificate has been created, up to 10 minutes
Thread.Sleep(60000);//1 minute
responseMessage = await BindCertificateToCustomDomain(sHostName);
}
if ((long)responseMessage.StatusCode == 200)
ret = true;
}
}
return ret;
}
private static async Task<HttpResponseMessage> CreateCustomDomain(string sHostName)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + GetAccessToken());
string requestURl = _baseURI + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/sites/{_AppName}/hostNameBindings/{sHostName}?api-version=2016-08-01";
string body = $"{{\"properties\": {{\"azureResourceName\": \"{_AppName}\"}}}}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
return await client.PutAsync(requestURl, stringContent);
}
}
private static async Task<HttpResponseMessage> CreateAppManagedCertificate(string sHostName)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + GetAccessToken());
string requestURl = _baseURI + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/certificates/{sHostName}?api-version=2021-02-01";
string serverFarm = $"/subscriptions/{_SubscriptionId}/resourceGroups/{_AlternateResourceGroupName}/providers/Microsoft.Web/serverfarms/{_AppServicePlanName}";
string body = $"{{\"location\": \"West US\", \"properties\": {{\"canonicalName\": \"{sHostName}\", \"hostNames\": [\"{sHostName}\"], \"serverFarmId\": \"{serverFarm}\"}}}}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
return await client.PutAsync(requestURl, stringContent);
}
}
private static async Task<HttpResponseMessage> BindCertificateToCustomDomain(string sHostName)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("Authorization", "Bearer " + GetAccessToken());
string requestURl = _baseURI + $"subscriptions/{_SubscriptionId}/resourceGroups/{_ResourceGroupName}/providers/Microsoft.Web/sites/{_AppName}?api-version=2016-08-01";
string serverFarm = $"/subscriptions/{_SubscriptionId}/resourceGroups/{_AlternateResourceGroupName}/providers/Microsoft.Web/serverfarms/{_AppServicePlanName}";
string body = $"{{\"location\": \"West US\", \"properties\": {{\"HostNameSslStates\": [ {{ \"SslState\" : \"1\", \"ToUpdate\" : \"True\", \"Name\": \"{sHostName}\"}}]}}, \"kind\": \"app\", \"location\": \"West US\", \"tags\" : {{\"hidden-related:{serverFarm}\": \"empty\"}}}}";
var stringContent = new StringContent(body, Encoding.UTF8, "application/json");
return await client.PutAsync(requestURl, stringContent);
}
}
}
}
How can I use the Management API to secure the custom domain with the
app service managed certificate?
Thanks #David.Warwick for the confirmation,
As we have discussed to achieve the above requirement we have to use the below Rest API .
You can try with PUT method for binding SSL certificate with Custom domain.
https://management.azure.com/subscriptions/{subscriptionId}/resourceGroups/{resourceGroup}/providers/Microsoft.Web/sites/{snapshotName}?api-version={api-version}
For more information please refer this SO THREAD
I have an Azure Function App with Azure Active Directory configured but when I call if from my client I keep getting an Unauthorized response.
I have tried a couple different scenarios but nothing worked. Below is a snippet of the last bit of code that I tried.
///
var #params2 = new NameValueCollection
{
{"grant_type", "client_credentials"},
{"client_id", $"{ClientId}"},
{"client_secret", $"{ClientSecret}"},
{"username", userId},
{"resource", "https://management.azure.com/"}
};
var queryString2 = HttpUtility.ParseQueryString(string.Empty);
queryString2.Add(#params2);
var content = new FormUrlEncodedContent(new Dictionary<string, string>
{
{"grant_type", "client_credentials"},
{"client_id", ClientId},
{"client_secret", ClientSecret},
{"username", userId}
});
var authorityUri2 = $"{string.Format(CultureInfo.InvariantCulture, AadInstance, Tenant).TrimEnd('/')}/oauth2/token";
//var authorityUri2 = $"https://login.microsoftonline.com/{Tenant}/v2.0/.well-known/openid-configuration";
var authUri2 = String.Format("{0}?{1}", authorityUri2, queryString2);
var client2 = new HttpClient();
var message = client2.PostAsync(authorityUri2, content).Result;
//var message = client2.GetAsync(authorityUri2).Result;
var response = message.Content.ReadAsStringAsync().Result;
dynamic values=null;
try
{
values = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
}
catch
{
values = response;
}
var AuthToken2 = values["access_token"];
client2.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", AuthToken2);
HttpResponseMessage response2 = await client2.GetAsync(AppBaseAddress.TrimEnd('/') + "/api/AADIntegration");
if (response.IsSuccessStatusCode)
{
// Read the response and data-bind to the GridView to display To Do items.
string s = await response.Content.ReadAsStringAsync();
log.LogInformation($"Success while getting / api / AADIntegration : {s}");
return (ActionResult)new OkObjectResult(s);
}
else
{
string failureDescription = await response.Content.ReadAsStringAsync();
log.LogInformation($"An error occurred while getting / api / AADIntegration : {response.ReasonPhrase}\n {failureDescription}");
return (ActionResult)new OkObjectResult(failureDescription);
}
Data should returned from the Function App.
For client_credentials grant flow your code seems little different. Here I am giving you exact sample for azure function. Just plug and play :))
Example contains:
How would you get token using client_credentials flow
Getting user list From Azure Active Directory tenant using above
token
Access Token Class:
public class AccessTokenClass
{
public string token_type { get; set; }
public string expires_in { get; set; }
public string resource { get; set; }
public string scope { get; set; }
public string access_token { get; set; }
}
Reference To Add:
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using System.Net.Http;
using System.Collections.Generic;
using System.Net.Http.Headers;
Azure Function Body:
public static class FunctionGetUserList
{
[FunctionName("FunctionGetUserList")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
try
{
log.LogInformation("C# HTTP trigger function processed a request.");
//Token Request endpoint Just replace yourTennantId/Name
string tokenUrl = $"https://login.microsoftonline.com/yourTennantId/Name.onmicrosoft.com/oauth2/token";
var tokenRequest = new HttpRequestMessage(HttpMethod.Post, tokenUrl);
tokenRequest.Content = new FormUrlEncodedContent(new Dictionary<string, string>
{
["grant_type"] = "client_credentials",
["client_id"] = "b603c7bead87-Your_client_id-e6921e61f925",
["client_secret"] = "Vxf1SluKbgu4P-Your_client_Secret-F0Nf3wE5oGl/2XDSeZ=",
["resource"] = "https://graph.microsoft.com"
});
dynamic json;
AccessTokenClass results = new AccessTokenClass();
HttpClient client = new HttpClient();
var tokenResponse = await client.SendAsync(tokenRequest);
json = await tokenResponse.Content.ReadAsStringAsync();
results = JsonConvert.DeserializeObject<AccessTokenClass>(json);
var accessToken = results.access_token;
//Create Request To Server
using (HttpClient clientNew = new HttpClient())
{
//Pass Token on header
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken);
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//Get Data from API
var requestToAzureEndpoint = await client.GetAsync("https://graph.microsoft.com/v1.0/users");
if (requestToAzureEndpoint.IsSuccessStatusCode)
{
var result_string = await requestToAzureEndpoint.Content.ReadAsStringAsync();
dynamic responseResults = JsonConvert.DeserializeObject<dynamic>(result_string);
return new OkObjectResult(responseResults);
}
else
{
var result_string = await requestToAzureEndpoint.Content.ReadAsStringAsync();
return new OkObjectResult(result_string);
}
}
}
catch (Exception ex)
{
return new OkObjectResult(ex.Message);
}
}
}
Point To Remember
For Azure Active Directory List users access make sure you have following permission:
User.Read.All
Permission Type: Application
You can check here. See the screen shot for better understanding; make sure you have clicked "Grant admin consent for yourTenant" after adding permission.
Note: This is how you can access Azure Active Directory Token using Azure Function after that how to access resource using that token to a specific API endpoint efficiently.
Are you sure you have properly implemented this properly? It looks like a few of your parameters are wrong for the client credential flow. Please double check that you are properly following the client credential flow.
The client credential grant flow is documented here : https://learn.microsoft.com/en-us/azure/active-directory/develop/v2-oauth2-client-creds-grant-flow
But for more information on getting this properly working in your function app, please refer to the blog below for more information/help on implementing this.
https://blogs.msdn.microsoft.com/ben/2018/11/07/client-app-calling-azure-function-with-aad/
The value of resource is not correct.
Replace {"resource", "https://management.azure.com/"} with {"resource", $"{ClientId}"}
https://learn.microsoft.com/en-us/azure/azure-functions/functions-manually-run-non-http
I am trying to manual trigger my Azure Timer function App created in 2.0 and developed in .net core 2.0.
When I try to hit the url I get 403 error.
apikey I pass is picked from :
As the article you provided, you need to use _master key under Manage and Host key
I use the following class in my integration tests against service bus triggered Azure Functions.
class AzureFunctionCaller
{
private readonly HttpClient _httpClient;
private readonly string _functionUri;
public AzureFunctionCaller(string functionName)
{
_httpClient = new HttpClient();
_httpClient.DefaultRequestHeaders.Add("x-functions-key","<Key>");
_functionUri = $"<FUNCTION_ENDPOINT>/admin/functions/{functionName}";
}
public async Task CallViaAdminEndpoint(string content)
{
var httpContent = new StringContent(content, Encoding.UTF8, "application/json");
var response = await _httpClient.PostAsync(_functionUri, httpContent);
var responseContent = await response.Content.ReadAsStringAsync();
Console.WriteLine($"Response content: {responseContent}");
}
}
Then you must send the data in a format where you place the content in "input" object.
var azureFunctionCaller = new AzureFunctionCaller("<FunctionName>");
var obj = new
{
... // properties you want to send
};
var jsonContent = JsonConvert.SerializeObject(new
{
input = JsonConvert.SerializeObject(obj)
});
await azureFunctionCaller.CallViaAdminEndpoint(jsonContent);`
To explain the input property, here is how the same call looks like in postman:
I want to get data using JIRA REST api with provided JIRA OAuth authentication service.
Basically I'm able to achieve this task using ScribeJava with Groovy. But I want to decoupled all the process as below :-
Request to get request token
Request to get authorized URL
Request to access token
Request to get actual data using HTTPBuilder
So I'm able to achieve above mentioned first three steps using ScribeJava and storing the accessToken into Database for further request for data as below :-
import java.security.KeyFactory
import java.security.PrivateKey
import java.security.spec.PKCS8EncodedKeySpec
import com.github.scribejava.core.builder.api.DefaultApi10a
import com.github.scribejava.core.model.OAuth1RequestToken
import com.github.scribejava.core.services.RSASha1SignatureService
import com.github.scribejava.core.services.SignatureService
class JiraOauthProvider extends DefaultApi10a {
private String authURL
private String requestTokenURL
private String accessTokenURL
private String consumerPrivateKey
private JiraOauthProvider(authURL, requestTokenURL, accessTokenURL, consumerPrivateKey) {
this.authURL = authURL
this.requestTokenURL = requestTokenURL
this.accessTokenURL = accessTokenURL
this.consumerPrivateKey = consumerPrivateKey
}
private static JiraOauthProvider instance = null
public static JiraOauthProvider instance(Map map) {
if(instance == null) {
instance = new JiraOauthProvider(map.authURL,
map.requestTokenURL,
map.accessTokenURL,
map.consumerPrivateKey)
}
return instance
}
#Override
public String getAccessTokenEndpoint() {
return accessTokenURL
}
#Override
public String getRequestTokenEndpoint() {
return requestTokenURL
}
#Override
public String getAuthorizationUrl(OAuth1RequestToken requestToken) {
return String.format(authURL, requestToken.getToken())
}
#Override
public SignatureService getSignatureService() {
return new RSASha1SignatureService(getPrivateKey())
}
private PrivateKey getPrivateKey() {
byte[] key = Base64.getDecoder().decode(consumerPrivateKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
}
Now I'm building OAuthService as :-
private static final String CALLBACK_URI = "callback-url"
protected static final String CONSUMER_KEY = "consumer-key"
protected static final String CONSUMER_PRIVATE_KEY = "private-key"
Map oAuthMap = [
"authURL" :"auth-url=%s",
"requestTokenURL":"request-token-url",
"accessTokenURL":"access-token-url",
"consumerPrivateKey":CONSUMER_PRIVATE_KEY
]
//Buid oauth service to get request token, auth url and access token
OAuth10aService service = ServiceBuilder()
.apiKey(CONSUMER_KEY)
.apiSecret(CONSUMER_PRIVATE_KEY).callback(CALLBACK_URI)
.build(JiraOauthProvider.instance(oAuthMap))
OAuth1RequestToken requestToken = service.getRequestToken()
def authURL = service.getAuthorizationUrl(requestToken)
//Now after redirect to this authURL and providing credential I'm getting oauthVerifier code to get accessToken and secretToken
def oauthVerifier = "oauth verifier code"
//Now calling to get accessToken
OAuth1AccessToken oAuth1AccessToken = service.getAccessToken(requestToken, oauthVerifier);
def accessToken = oAuth1AccessToken.getToken()
def secretToken = oAuth1AccessToken.getTokenSecret()
//now I'm storing this `accessToken`and `secretToken` into DB for further future data request.
So after all above stuff I'm able to achieve above mentioned three steps and storing the access token into db for future request only for data.
So to achieve 4th step to getting actual data using HTTPBuilder I'm doing some thing as below :-
def http = new HTTPBuilder('base-url')
http.auth.oauth CONSUMER_KEY, CONSUMER_PRIVATE_KEY, accessToken, secretToken
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}
But I'm getting response as :-
{oauth_problem=signature_method_rejected}
So, could anyone suggest me how can I get actual data using HTTPBuilder with OAuth authentication using accessToken and secretToken?
Note:- I can get actual data as well using ScribeJava Api with OAuthRequest but requirement is to get actual data using HTTPBuilder
I just want a pointer that how to achieve it.
After lot of search I have got the solution from here. Actually HTTPBuilder internally using Signpost which signing the request using HmacSha Signer while Jira rest api supports RSA-SHA1 Signer to validate the HttpRequest that's why it's giving response as :-
{oauth_problem=signature_method_rejected}
So, basically I have to do custom RSA-SHA1 Signer to get the signature to http request. To achive this I'm using Google Data (GData) APIs to sign the data using RSA-SHA1 Signer before HttprRequest as below :-
private static PrivateKey getPrivateKey(String consumerKey) {
try {
byte[] key = Base64.getDecoder().decode(consumerKey)
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(key)
KeyFactory kf = KeyFactory.getInstance("RSA")
return kf.generatePrivate(keySpec)
} catch (Exception e) {
throw new RuntimeException(e)
}
}
import com.google.gdata.client.authn.oauth.OAuthParameters
import com.google.gdata.client.authn.oauth.OAuthRsaSha1Signer
import com.google.gdata.client.authn.oauth.OAuthUtil
import com.google.gdata.client.authn.oauth.RsaSha1PrivateKeyHelper
OAuthRsaSha1Signer rsaSigner = new OAuthRsaSha1Signer()
rsaSigner.setPrivateKey(getPrivateKey(CONSUMER_PRIVATE_KEY))
OAuthParameters params = new OAuthParameters()
params.setOAuthConsumerKey(CONSUMER_KEY)
params.setOAuthNonce(OAuthUtil.getNonce())
params.setOAuthTimestamp(OAuthUtil.getTimestamp())
params.setOAuthSignatureMethod("RSA-SHA1")
params.setOAuthType(OAuthParameters.OAuthType.TWO_LEGGED_OAUTH)
params.setOAuthToken(accessToken)
String paramString = params.getBaseParameters().sort().collect{it}.join('&')
String baseString = [
OAuthUtil.encode("GET"),
OAuthUtil.encode('base-url' + 'path'),
OAuthUtil.encode(paramString)
].join('&')
String signature = rsaSigner.getSignature(baseString, params);
params.addCustomBaseParameter("oauth_signature", signature);
//Now calling using HTTPBuilder with signed data
def http = new HTTPBuilder('base-url')
http.request(Method.GET, ContentType.JSON) { req ->
uri.path = 'path'
uri.query = params.getBaseParameters()
response.success = { resp, json ->
println json
}
response.failure = { resp, json -> print json }
}
}
I'm writing queue trigger function where I read data from queue, and send them another web service using RESTFul service. Right now, I'm testing a very simple REST api call that I only need to provide token in the header and expect very simple JSON response from the server. The JSON just contains an email address entry and that's about it. My understanding is that if I read response asynchronously, I would need to change function prototype to comply with async call. But that's not possible in Azure function app. So what's the best way to read JSON response object?
This is my attempt so far :
using System;
using System.Net.Http;
using System.Net.Http.Headers;
public static void Run(string myQueueItem, TraceWriter log)
{
string URL = "https://api.spotlightessentials.com/api/v2/user";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("token","<Token value>");
HttpResponseMessage response = client.GetAsync("").Result;
if (response.IsSuccessStatusCode)
{
// How do I read Json response here
}
}
else
{
Console.WriteLine("{0} ({1})", (int)response.StatusCode, response.ReasonPhrase);
}
}
In your
if (response.IsSuccessStatusCode)
you can do this:
var responseData = await response.Content.ReadAsAsync<YourObjectTypeHere>();
Or you could also do something like this depending on your needs:
var responseData = response.Content.ReadAsStringAsync().GetAwaiter().GetResult();
if (!string.IsNullOrWhiteSpace(responseData))
{
var responseDataObject =
JsonConvert.DeserializeObject<YourObjectTypeHere>(responseData);
}
Or a combination of parts of the 2.