I have an OwinMiddleware with an Invoke method looking kind of like this:
public override async Task Invoke(IOwinContext context)
{
...
//The next line launches the execution of the Get method of a controller
await Next.Invoke(context);
//Now context.Response should contain "myvalue" right?
...
}
The Invoke method invokes a Get method, located inside a controller, which looks kind of like this:
[HttpGet]
public IHttpActionResult Get(some params...)
{
...
return "myvalue";
...
}
After the execution of the Get method, the program goes back to the Invoke method of my middleware. I think that the response of the Get method, namely myvalue, should be contained inside context.Response, but I don't know where precisely, because it's full of things.
Actualy response is a stream and You need to do this to get response back in orignal form
try{
var stream = context.Response.Body;
var buffer = new MemoryStream();
context.Response.Body = buffer;
await _next.Invoke(environment);
buffer.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(buffer);
// Here you will get you response body like this
string responseBody = reader.ReadToEndAsync().Result;
// Then you again need to set the position to 0 for other layers
context.Response.Body.Position = 0;
buffer.Seek(0, SeekOrigin.Begin);
await buffer.CopyToAsync(stream);
}
catch(Exception ex)
{
}
Related
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;
}
I have tree layer of classes to get data from database and serve it within an Action. I get data from database old way, using SqlParameter classes.
I need to/want to reconstruct this methods to asynchronous methods. What truly I want is to learn how to make these synchronous methods to Asynchronous. And make them work different threads and use them across entire app.
What I don't want to do is to Use Ado.Net or using ready methods like HttpClient.GetAsync
I read this question: Calling async methods from non-async code but couldn't apply to my structure and couldn't be sure if it is work properly, avoids deadlocks.
My old structure is like that:
My Action in My BlockController:
public ActionResult Index()
{
return View(new BlockDb().Select());
}
The Select Method in BlockDb class:
public List<Block> Select()
{
SqlDataReader dr = DbJobs.ExecuteReader("BlockSelect");
List<Block> list = new List<Block>();
Block cs;
while (dr.Read())
{
cs = new Block();
cs.ID = Convert.ToInt32(dr["ID"]);
cs.Name= Convert.ToString(dr["Name"]);
cs.Dt = Convert.ToDateTime(dr["Dt"]);
cs.Ok = Convert.ToBoolean(dr["Ok"]);
list.Add(cs);
}
dr.Close();
dr.Dispose();
return list;
}
And the last one ExecuteReader Method in DbJobs static class:
public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
{
SqlDataReader Result = null;
SqlConnection connect = new SqlConnection(cnn);
try
{
SqlCommand command = new SqlCommand(ProcName, connect);
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter item in prmtr)
command.Parameters.Add(item);
if (connect.State == ConnectionState.Closed)
connect.Open();
Result = command.ExecuteReader(CommandBehavior.CloseConnection);
//connect.Close();
//connect.Dispose();
}
catch { }
return Result;
}
I can't be sure bu the result of an Action could be like that:
public async Task<ActionResult> Index()
{
return View(await new BlockDb().SelectAsync());
}
How can I achive that?
To convert code to async, it's best to start at the lowest level and work your way up. So, starting with DbJobs, change every method to its asynchronous equivalent and await the result:
public static SqlDataReader ExecuteReader(string ProcName, params SqlParameter[] prmtr)
{
SqlDataReader Result = null;
SqlConnection connect = new SqlConnection(cnn);
try
{
SqlCommand command = new SqlCommand(ProcName, connect);
command.CommandType = CommandType.StoredProcedure;
foreach (SqlParameter item in prmtr)
command.Parameters.Add(item);
if (connect.State == ConnectionState.Closed)
await connect.OpenAsync(CancellationToken.None);
Result = await command.ExecuteReaderAsync(CommandBehavior.CloseConnection);
}
catch { }
return Result;
}
This will give you a compiler error telling you to change your DbJobs.ExecuteReader signature. So, if you do what the compiler error tells you to do, you'll end up with:
public static async Task<SqlDataReader> ExecuteReaderAsync(string ProcName, params SqlParameter[] prmtr)
Now you'll get compiler errors for all the old code that called DbJobs.ExecuteReader, e.g., BlockDb.Select. So, change those to use asynchronous methods, too:
public List<Block> Select()
{
SqlDataReader dr = await DbJobs.ExecuteReaderAsync("BlockSelect");
List<Block> list = new List<Block>();
Block cs;
while (await dr.ReadAsync(CancellationToken.None))
{
cs = new Block();
cs.ID = Convert.ToInt32(dr["ID"]);
cs.Name= Convert.ToString(dr["Name"]);
cs.Dt = Convert.ToDateTime(dr["Dt"]);
cs.Ok = Convert.ToBoolean(dr["Ok"]);
list.Add(cs);
}
dr.Close();
dr.Dispose();
return list;
}
Again, you'll get a compiler error telling you how to change BlockDb.Select:
public async Task<List<Block>> SelectAsync()
And finally, you'll do the same for Index:
public async Task<ActionResult> Index()
{
return View(await new BlockDb().SelectAsync());
}
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'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;
}
I have a function which opens a file from storage and returns back a Boolean specified that the file opened just fine.
private async Task<bool> SaveImage()
{
try
{
await filesave.openAsync(FileAccessMode.ReadWrite)
}
catch()
{
return false;
}
return true;
}
I want to call the await SaveImage() function, but somehow want a listener/event handler which tells me when this has completed.. upon completion I want to update my layout with new data. How is this possible using the new WINRT async/ await async methodology for windows 8? is there a work around/substitute.
How can I setup a event handler type scenario? (on complete)
You just await a call to your method, and follow it with the code that should run when it's completed. You don't need to manually register an event handler.
var succeeded = await SaveImage();
// Because of the "await" keyword in the above line, the current method
// will not continue until "SaveImage" has completed its async work and
// signaled its Task
if (succeeded) { ... }
Of course, since the above code uses the await keyword, it needs to be placed inside a method that's also marked async. If that method needs to signal its completion to its caller, then it should also return a Task or Task<T>; for example:
private async Task<string> MyHelperMethod() {
var succeeded = await SaveImage();
if (succeeded)
return "Success";
else
return "Failure";
}
// then, in some other method:
var message = await MyHelperMethod();
Or, if the method calling SaveImage is the end of the line -- say it's the handler for a Button's Click event -- then it can be async void:
private async void ButtonClick(object sender, EventArgs args) {
var succeeded = await SaveImage();
if (succeeded) { ... }
}
Joe's answer looks great, though if you insist on using an event - for example if your SaveImage() calls are in various areas of code unrelated to updating the layout - you can just raise an event when your operation completes. You can use the plain old CLR events or use a pub-sub pattern implementation like the EventAggregator from Prism or Messenger from MVVM Light. The POCE version could look like this
public event EventHandler<Tuple<StorageFile,bool>> SaveImageCompleted;
private async Task<bool> SaveImage(StorageFile file)
{
try
{
await file.OpenAsync(FileAccessMode.ReadWrite);
}
catch
{
if (SaveImageCompleted != null)
SaveImageCompleted(this, new Tuple<StorageFile, bool>(file, false));
return false;
}
if (SaveImageCompleted != null)
SaveImageCompleted(this, new Tuple<StorageFile, bool>(file, true));
return true;
}
This takes a little more code but is a VERY cool and useful way to deal with async operations, progress, cancellations and complete status in general. This was compiled in a VS2012 Winrt Store App and I ran it off a button click as you see here.
private void Save_File_Click(object sender, RoutedEventArgs e)
{
// create your op, bool = return type, string = progress report
IAsyncOperationWithProgress<bool, string> op;
// Call our async operation with progress sending the file name
op = OpenFileWithProgress("test.txt");
// not implemented here
//op.Cancel();
// when we get a progress update...
op.Progress = (info, progress) =>
{
// I'm just giving text feed back to user here
Debug.WriteLine(progress);
};
op.Completed = (info, status) =>
{
// check status for completion or cancellation...
switch (status)
{
case AsyncStatus.Completed:
// Do your completed work here
Debug.WriteLine("Completed");
break;
case AsyncStatus.Canceled:
// Operation canceled - not implemented...
Debug.WriteLine("Canceled");
break;
default:
// default stuff here
break;
}
};
}
public IAsyncOperationWithProgress<bool, string> OpenFileWithProgress(string fileName)
{
return System.Runtime.InteropServices.WindowsRuntime.AsyncInfo.Run<bool, string>((token, progress) =>
Task.Run<bool>(async () =>
{
progress.Report("Starting");
try
{
StorageFile file = await ApplicationData.Current.LocalFolder.CreateFileAsync(fileName);
}
catch (Exception ex)
{
return false;
}
progress.Report("Finished");
return true;
}, token));
}