Trigger a flow using c# - c#

I have Microsoft flow which triggers When an HTTP Request is Received. I want to trigger this flow from the C# code. I tried the following code to trigger the flow but it is not working. The flow didn't get triggered and the code remains in the running state.
private static async System.Threading.Tasks.Task NewMethod()
{
var url = "https://prod-06.australiasoutheast.logic.azure.com:443/workflows/15702797187b4ffcbe386f714f532a8a/triggers/manual/paths/invoke?api-version=2016-06-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=pOBhhzWW9cUel9v2jfyCUIY5wt4c1o84ezvMBNoLGm4";
var client = new HttpClient();
var response = await client.GetAsync(url);
string result = response.Content.ReadAsStringAsync().Result;
}
I also need to pass the parameter to flow from code. What is wrong with the code or do I need to do anything in flow to trigger from outside application?

Consider verifying that the Flow id 15702797187b4ffcbe386f714f532a8a is a valid flow. You may have transposed the id or are using the incorrect API version number associated with that id.

Related

Windows store app HttpClient issue

i'm testing some code here and came across a really weird issue. The HttpClient class works like a charm if my tablet is on but whenever the battery safe state kicks in and the screen is locked the HttpClient class throw an exception and the app suddendly exits giving me small chances to log the exception. If i'm not mistaken the error seems to be a send request error but that's weird since i have full access to the internet while the tablet is on.
Here the code i'm using and the one that crash on that state(System.Net.Http namespace ):
private static async Task<string> HttpGet(string uri)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", BotUserAgent);
var response = await client.GetAsync(uri);
return await response.Content.ReadAsStringAsync();
}
}
Alternatively i've used the client of the web.http namespace with the same result:
using(var client = new Windows.Web.Http.HttpClient())
{
client.DefaultRequestHeaders.Add("User-Agent", BotUserAgent);
var response = await client.GetAsync(new Uri(uri));
return await response.Content.ReadAsStringAsync();
}
This is the error i get(after adding an exception logger):
An error occurred while sending the request.
Any ideas?
The problem is that your WinRT-device sends your app to the background when the battery safe state kiks in.
whenever the user moves your app into the background, your app can be suspended or frozen, essentially stopping any downloads dead in their tracks. In some scenarios, the app might
even be terminated, forcing you to create a new instance of the class in an attempt to start the download again. Fortunately, WinRT provides a way to handle this specific scenario using a background task.
This is a quote from http://www.informit.com/articles/article.aspx?p=2229233&seqNum=6
On this site is an easy tutorial to follow on how to use BackgroundTransfers in the Windows.Networking.BackgroundTransfer-Namespace.

Web API allow only single async task

What is a proper scenario for handling only single async action? For example I need to import large file and while it being imported I need to disable that option to ensure that second import not triggered.
What comes in mind that:
[HttpPost]
public async Task<HttpResponseMessage> ImportConfigurationData()
{
if (HttpContext.Current.Application["ImportConfigurationDataInProcess"] as bool? ?? false)
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, "Task still running");
HttpContext.Current.Application["ImportConfigurationDataInProcess"] = true;
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
await Request.Content.ReadAsMultipartAsync(provider);
//actual import
HttpContext.Current.Application["ImportConfigurationDataInProcess"] = false;
Request.CreateResponse(HttpStatusCode.OK, true)
}
But it seems like very hard-coded solution. What is a proper way of handling that?
Another thing it is not properly works on client side at it still waits for a response. So is it possible for user just to send that file to server and not wait unlit it will finishes but reload page after file sent to server without waiting while await stuff will finish.
async does not change the HTTP protocol (as I explain on my blog). So you still just get one response per request.
The proper solution is to save a "token" (and import data) for the work in some reliable storage (e.g., Azure table/queue), and have a separate processing backend that does the actual import.
The ImportConfigurationData action would then check whether a token already exists for that data, and fault the request if found.

Is this fire and forget approach correct?

I've implemented instagram api realtime updates. Basically they fire a POST request to a url I provide when there are new images added based on my subscription.
They said:
" you should acknowledge the POST within a 2 second timeout--if you need to do more processing of the received information, you can do so in an asynchronous task."
so I built something like:
[HttpPost]
[ActionName("realtime")]
public async Task<ActionResult> IndexPost()
{
var form = Request.Form;
Request.InputStream.Position = 0;
System.IO.StreamReader str = new System.IO.StreamReader(Request.InputStream);
string sBuf = str.ReadToEnd();
// deserialize this from json
var serializer = new JavaScriptSerializer();
var updates = serializer.Deserialize<IEnumerable<RealtimeUpdate>>(sBuf).ToList();
ProcessNewTaggedImages(updates);
return new ContentResult { Content = "Ok" };
}
where ProcessNewTaggedImages is running async.
public async void ProcessNewTaggedImages(List<RealtimeUpdate> updates)
{
Task.Run(() =>
{
// query Instagram api for new images
}
}
so basically when Instagram POSTs to www.mysite.com/realtime it does not wait for ProcessNewTaggedImages.
I just wanted to make sure this approach is correct for fire and forget approach because under Task.Run I receive a warning saying:
Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the await operator to the result of the call.
but I don't want await here because
the result of my processing does not matter for instagram call
timeout for POST is 2 seconds so I don't want to wait for this processing.
Can you confirm I am on the right track?
Ps: POST is working fine and all works good just wanted to confirm I've not done any mystake because I am mostly beginner to this async approach in C#.
If you need fire and forget functionality you don't need to add async keywords to your methods as your are not doing any awaits. So remove the async keywords from your code and the compiler will not complain about your code.
I think you might need to read though this first.
And I quote: "If an async method doesn’t use an await operator to mark a suspension point, the method executes as a synchronous method does, despite the async modifier."

Getting the call response from the menu with Twilio

I am using C# to send a phone message with option(Twimlet) for the user to press 1 to confirm. How do I get the response from the call?
The code terminates prior to the call being placed, I assume I need to query the twilio server with the call sid?
static void Main(string[] args)
{
var twilio = new TwilioRestClient(AccountSid, AuthToken);
var options = new CallOptions();
options.Url = "http://twimlets.com/menu?Message=Please%20press%201%20to%20confirm%20or%20Press%202%20to%20cancel&Options%5B1%5D=http%3A%2F%2Ftwimlets.com%2Fmessage%3FMessage%255B0%255D%3DYou%2520have%2520confirmed%252C%2520Thank%2520you%2520good%2520bye.%26&Options%5B2%5D=http%3A%2F%2Ftwimlets.com%2Fmessage%3FMessage%255B0%255D%3DYou%2520have%2520selected%2520to%2520cancel.%2520Thank%2520you.%2520Good%2520bye%26&";
options.To = "+13105551212";
options.From = "+13105551213";
var call = twilio.InitiateOutboundCall(options);
Console.WriteLine(call.Sid);
In order to respond to any input from the call, you need to use URLs under your control. Twimlets are pre-defined "apps" that don't give you control of the call flow outside of what you can specify in URL parameters.
The code you have now terminates because all it is doing is making an HTTP call to Twilio's servers telling it to start the call, with the options.Url endpoint responsible for handling that call's flow. To write a custom flow, you would need to create a public URL that returns TwiML for the desired flow.
Once you've got that going, you'll use the url attribute of the <Gather> verb to indicate where the key press data should be sent.

Web Api + HttpClient: An asynchronous module or handler completed while an asynchronous operation was still pending

I'm writing an application that proxies some HTTP requests using the ASP.NET Web API and I am struggling to identify the source of an intermittent error.
It seems like a race condition... but I'm not entirely sure.
Before I go into detail here is the general communication flow of the application:
Client makes a HTTP request to Proxy 1.
Proxy 1 relays the contents of the HTTP request to Proxy 2
Proxy 2 relays the contents of the HTTP request to the Target Web Application
Target Web App responds to the HTTP request and the response is streamed (chunked transfer) to Proxy 2
Proxy 2 returns the response to Proxy 1 which in turn responds to the original calling Client.
The Proxy applications are written in ASP.NET Web API RTM using .NET 4.5.
The code to perform the relay looks like so:
//Controller entry point.
public HttpResponseMessage Post()
{
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(this.Request);
//HttpCompletionOption.ResponseHeadersRead - so that I can start streaming the response as soon
//As it begins to filter in.
var relayResult = client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead).Result;
var returnMessage = BuildResponse(relayResult);
return returnMessage;
}
}
private static HttpRequestMessage BuildRelayHttpRequest(HttpRequestMessage incomingRequest)
{
var requestUri = BuildRequestUri();
var relayRequest = new HttpRequestMessage(incomingRequest.Method, requestUri);
if (incomingRequest.Method != HttpMethod.Get && incomingRequest.Content != null)
{
relayRequest.Content = incomingRequest.Content;
}
//Copies all safe HTTP headers (mainly content) to the relay request
CopyHeaders(relayRequest, incomingRequest);
return relayRequest;
}
private static HttpRequestMessage BuildResponse(HttpResponseMessage responseMessage)
{
var returnMessage = Request.CreateResponse(responseMessage.StatusCode);
returnMessage.ReasonPhrase = responseMessage.ReasonPhrase;
returnMessage.Content = CopyContentStream(responseMessage);
//Copies all safe HTTP headers (mainly content) to the response
CopyHeaders(returnMessage, responseMessage);
}
private static PushStreamContent CopyContentStream(HttpResponseMessage sourceContent)
{
var content = new PushStreamContent(async (stream, context, transport) =>
await sourceContent.Content.ReadAsStreamAsync()
.ContinueWith(t1 => t1.Result.CopyToAsync(stream)
.ContinueWith(t2 => stream.Dispose())));
return content;
}
The error that occurs intermittently is:
An asynchronous module or handler completed while an asynchronous operation was still pending.
This error usually occurs on the first few requests to the proxy applications after which the error is not seen again.
Visual Studio never catches the Exception when thrown.
But the error can be caught in the Global.asax Application_Error event.
Unfortunately the Exception has no Stack Trace.
The proxy applications are hosted in Azure Web Roles.
Any help identifying the culprit would be appreciated.
Your problem is a subtle one: the async lambda you're passing to PushStreamContent is being interpreted as an async void (because the PushStreamContent constructor only takes Actions as parameters). So there's a race condition between your module/handler completing and the completion of that async void lambda.
PostStreamContent detects the stream closing and treats that as the end of its Task (completing the module/handler), so you just need to be sure there's no async void methods that could still run after the stream is closed. async Task methods are OK, so this should fix it:
private static PushStreamContent CopyContentStream(HttpResponseMessage sourceContent)
{
Func<Stream, Task> copyStreamAsync = async stream =>
{
using (stream)
using (var sourceStream = await sourceContent.Content.ReadAsStreamAsync())
{
await sourceStream.CopyToAsync(stream);
}
};
var content = new PushStreamContent(stream => { var _ = copyStreamAsync(stream); });
return content;
}
If you want your proxies to scale a bit better, I also recommend getting rid of all the Result calls:
//Controller entry point.
public async Task<HttpResponseMessage> PostAsync()
{
using (var client = new HttpClient())
{
var request = BuildRelayHttpRequest(this.Request);
//HttpCompletionOption.ResponseHeadersRead - so that I can start streaming the response as soon
//As it begins to filter in.
var relayResult = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
var returnMessage = BuildResponse(relayResult);
return returnMessage;
}
}
Your former code would block one thread for each request (until the headers are received); by using async all the way up to your controller level, you won't block a thread during that time.
I would like to add some wisdom for anyone else who landed here with the same error, but all of your code seems fine. Look for any lambda expressions passed into functions across the call-tree from where this occurs.
I was getting this error on a JavaScript JSON call to an MVC 5.x controller action. Everything I was doing up and down the stack was defined async Task and called using await.
However, using Visual Studio's "Set next statement" feature I systematically skipped over lines to determine which one caused it. I kept drilling down into local methods until I got to a call into an external NuGet package. The called method took an Action as a parameter and the lambda expression passed in for this Action was preceded by the async keyword. As Stephen Cleary points out above in his answer, this is treated as an async void, which MVC does not like. Luckily said package had *Async versions of the same methods. Switching to using those, along with some downstream calls to the same package fixed the problem.
I realize this is not a novel solution to the problem, but I passed over this thread a few times in my searches trying to resolve the issue because I thought I didn't have any async void or async <Action> calls, and I wanted to help someone else avoid that.
A slightly simpler model is that you can actually just use the HttpContents directly and pass them around inside the relay. I just uploaded a sample illustrating how you can rely both requests and responses asynchronously and without buffering the content in a relatively simple manner:
http://aspnet.codeplex.com/SourceControl/changeset/view/7ce67a547fd0#Samples/WebApi/RelaySample/ReadMe.txt
It is also beneficial to reuse the same HttpClient instance as this allows you to reuse connections where appropriate.

Categories