How to receive response from Zoho Sign Webhook - webhooks

I am able to hit my call back function from Zoho Sign webhook. But I am not able to figure out how can I receive the response that Zoho Sign sends to my callback URL. Their documentation: https://www.zoho.com/sign/api/#webhook-management
Below is my sample code that I am using to confirm that callback function is hit. It saves a sample data to DB to confirm it is being hit. But the response I am not being able to catch hold of. This is their help documentation that guides on the same, but that misses a working sample. https://help.zoho.com/portal/en/community/topic/webhooks-for-zoho-sign
[HttpPost]
public ActionResult Callback()
{
using (var context = new ZohoApiTestEntities())
{
var rowDetails = new tblWebhook();
rowDetails.PhoneNo = "7978704767";
//rowDetails.Notes1 = jsonObj.ToString();
context.tblWebhooks.Add(rowDetails);
context.SaveChanges();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}

Finally, after a lot of hits and trials, this code worked for me. It's bad that after a lot of follow-up and calls with the Zoho team, I did not receive any help from them for many days.
[HttpPost]
public ActionResult Callback()
{
string rawBody = GetDocumentContents(Request);
dynamic eventObj = JsonConvert.DeserializeObject(rawBody);
using (var context = new ZohoApiTestEntities())
{
var rowDetails = new tblWebhook();
rowDetails.PhoneNo = "*********";
//eventObj comes in JSOn format with two keys, "requests" and "notifications" each containing a JSON object https://www.zoho.com/sign/api/#webhook-management
//you can get your required details like this
string recipientName = eventObj.notifications.performed_by_name.ToString();
rowDetails.Notes1 = recipientName;
context.tblWebhooks.Add(rowDetails);
context.SaveChanges();
}
return new HttpStatusCodeResult(HttpStatusCode.OK);
}
private string GetDocumentContents(HttpRequestBase Request)
{
string documentContents;
using (Stream receiveStream = Request.InputStream)
{
using (StreamReader readStream = new StreamReader(receiveStream, Encoding.UTF8))
{
documentContents = readStream.ReadToEnd();
}
}
return documentContents;
}

Related

facing issues in executing Azure vision api

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

Unable to manual trigger my Azure Timer Trigger using httpclient post request

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:

Why does HttpClient PostAsJsonAsync exit Azure Web Job without running code after it?

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");

C# Parse how to wait until Query returns a value

I'm trying to retrieve user data from Parse (xamarin.ios using c#). I'm using an async method with await. My challenge is,each time I navigate to the tableView in the app, which should populate the user data in question,the table is always empty.
I would like to wait until the results have been returned before proceeding with the other portion of code.I have tried to use the ContinueWith() function but constantly ran into a build error -
Cannot implicitly convert type 'void' to System.Collections.Generic.IEnumerable<Parse.ParseObject>
My Questions:
Is this the best way to wait for the result?
How do I solve the build error?
Here is my current implementation:
public async void retrieveData(string username)
{
try
{
this.requests.ClearRequests();
refreshed = false;
var query = ParseObject.GetQuery("Requests").WhereEqualTo("username", username);
IEnumerable<ParseObject> results = await query.FindAsync().ContinueWith(t =>{
if(results != null)
{
foreach(ParseObject parseObject in results)
{
UserRequest request = new UserRequest();
request.objectId = parseObject.ObjectId;
request.make = parseObject.Get<string> ("item1");
request.model = parseObject.Get<string> ("item2");
request.year = parseObject.Get<string> ("item3");
request.userName = parseObject.Get<string> ("username");
this.requests.addRequest (request);
}
refreshed = true;
}
});
}
catch(ParseException e) {
Console.WriteLine (e.Message + e.StackTrace);
}
}
You shouldn't need a ContinueWith...that's what the await should handle.
await waits on a Task and then brings back the result with the proper return type. ContinueWith returns a Task, so you would have to grab the Result from the task to make it usable.
For more on this type of thing, you may want to check out Difference between await and ContinueWith
You can try something like this.
public async void retrieveData(string username, )
{
try
{
this.requests.ClearRequests();
refreshed = false;
var query = ParseObject.GetQuery("Requests").WhereEqualTo("username", username);
IEnumerable<ParseObject> results = await query.FindAsync();
if(results != null)
{
foreach(ParseObject parseObject in results)
{
UserRequest request = new UserRequest();
request.objectId = parseObject.ObjectId;
request.make = parseObject.Get<string> ("item1");
request.model = parseObject.Get<string> ("item2");
request.year = parseObject.Get<string> ("item3");
request.userName = parseObject.Get<string> ("username");
this.requests.addRequest (request);
}
refreshed = true;
}
//This is your refresh method for your TableView
this.RefreshTableView();
//or, if in iOS
NSNotificationCenter.DefaultCenter.PostNotificationName("resultsRetrieved", null);
}
catch(ParseException e) {
Console.WriteLine (e.Message + e.StackTrace);
}
}
To show the results in the tableView, I would recommend moving the refreshing of the tableView to a separate method that gets triggered synchronously after the results have been retrieved and parsed. This is shown with the this.RefreshTableView() call above.
If in iOS on Xamarin, another option is to post a notification to the NSNotificationCenter (the Xamarin documentation for which is here). Use the PostNotificationName part seen above instead and then add an observer in the ViewControllers that you want to be dependent on the data. This is done as follows:
Make a notificationToken object:
NSObject notificationToken;
Then in your setup method (you could put this inside of your ViewDidLoad):
void Setup ()
{
notificationToken = NSNotificationCenter.DefaultCenter.AddObserver ("resultsRetrieved", RefreshData);
}
Make your RefeshData method:
void RefreshData (NSString notifString)
{
this.tableView.ReloadData();
}
And then, make sure you dispose of the notification observer when you tear down the class
void Teardown ()
{
NSNotificationCenter.DefaultCenter.RemoveObserver (notificationToken);
}
I had a similar issue so started using callbacks. I'm using them in Xamarin.Android, pretty sure they're available in Xamarin.iOS.
Method that starts the task method - Note I am passing in a method of this class as a parameter
private async void updatedData()
{
await Utils.DataTasks.getNewLiveTips(populateTipsList);
}
Method that calls for data from server
public class DataTasks
{
public static async Task getAllData(Action<IEnumerable<ParseObjects>> callback) {
var query = new ParseQuery<ParseObjects>().OrderByDescending("updatedAt").Limit(5);
IEnumerable<ParseObjects> parseTips = await query.FindAsync();
foreach (var tip in parseTips)
{
// Save data to DB if needed
}
callback(parseTips);
}
Method I passed as parameter in the first instance is now called
private void populateTipsList(IEnumerable<ParseObjects> results)
{
mAdapter = new TipAdapter(this.Activity, results);
mRecyclerView.SetAdapter(mAdapter);
refresher.Refreshing = false;
}

cannot creat a domain using Rackspace Cloud DNS with openstack.net

I'm currently trying to create a domain on Rackspace Cloud DNS service using openstack.net sdk, but nothings happening.
i got my rackspace account, its activated and i got my API key as well.
I wrote a console app to test my code but the results are always "WaitingForActivation" and i cant find any documentation for cloudsDNS using openstack.net sdk.
Would anyone be able to take a look at my code and tell me what im doing wrong please.
private static string RackSpaceUserName
{
get { return "username"; }
}
private static string RackSpaceUserApiKey
{
get { return "apikey"; }
}
private UserAccess RackSpaceUser
{
get
{
IIdentityProvider identityProvider = new CloudIdentityProvider();
var userAccess = identityProvider.Authenticate(Cloudidentity);
return userAccess;
}
}
private static CloudIdentity Cloudidentity
{
get
{
var ci = new CloudIdentity
{
APIKey = RackSpaceUserApiKey,
Username = RackSpaceUserName
};
return ci;
}
}
static void Main(string[] args)
{
var ParkedDomain = new CloudDnsProvider(Cloudidentity, null, true, null);
List<DnsDomainRecordConfiguration> dnsrecords = new List<DnsDomainRecordConfiguration>();
dnsrecords.Add(new DnsDomainRecordConfiguration(DnsRecordType.Ns, "testdomain.com", "dns1.stabletransit.com", TimeSpan.FromMinutes(20), null, null));
dnsrecords.Add(new DnsDomainRecordConfiguration(DnsRecordType.Ns, "testdomain.com", "dns2.stabletransit.com", TimeSpan.FromMinutes(20), null, null));
List<DnsSubdomainConfiguration> subdomains = new List<DnsSubdomainConfiguration>();
subdomains.Add(new DnsSubdomainConfiguration("info#testdomain.com", "test", ""));
DnsDomainConfiguration dnsd = new DnsDomainConfiguration("testdomain.com", TimeSpan.FromMinutes(20), "info#testdomain.com", "", dnsrecords, subdomains);
DnsConfiguration dnsconfig = new DnsConfiguration(dnsd);
var result = ParkedDomain.CreateDomainsAsync(dnsconfig, AsyncCompletionOption.RequestCompleted, CancellationToken.None, null);
Console.Write(result.Status);
Console.ReadLine();
}
the value for result.Status always returns "WaitingForActivation", and when i check my rackspace cloud dns dashboard, no domains are created.
Any help would be greatly appreciated.
The DNS service uses asynchronous methods. The object returned by CreateDomainsAsync is a Task which represents the asynchronous operation, but that operation may not complete prior to the call returning. You can wait for the request to be complete in your code by any of the following methods:
Await the result (only allowed in an async method, which Main cannot be).
await result;
Access the Task<TResult>.Result property.
var completedResult = result.Result;
Call the Task.Wait method.
result.Wait();

Resources