Response bindings for Functions with ActivityTrigger - c#

I want to create a Durable Function that calls an Activity Function, and then returns a value using dotnet core in a v2 function app. The function will of course validate its input, so may return a successful value or it may return an invalid error: a 200 or a 400 in HTTP terms. My activity function will be something like this:
[FunctionName("MyFunc")]
public static async Task<object> Run(
[ActivityTrigger] string input,
ILogger log)
{
// return something like
return new { Status = "OK", Content = content };
}
What return type should I use for this? Should make my own DTO that would be a valid response, or is there a way of returning HttpResponse objects to the orchestrator?

I think there may be a simpler solution here. Have you considered returning a simple value if your verification passes, and throwing an exception handled by the orchestrator if your verification fails?
The ActivityTrigger binding handles both input and output. Per the docs on error handling, an activity function can return any sort of JSON-serializable object to the orchestrator, and unhandled exceptions thrown by an activity function are marshalled back to the orchestrator, where they can be handled by catch blocks.
Activity-orchestrator communication doesn't use HTTP requests and responses; it uses Azure Storage tables to record history events and Azure Storage queues to trigger activities to perform async work or wake up the orchestrator once some activity's async work has completed, respectively. Unless you specifically need an HttpResponse object somewhere in your orchestration, there's no need to wrap your activity's return value in one.

Related

WebAssembly.JSException: TypeError: Failed to fetch when server does not response

I want to write code for case when server does not response.
I purposely shutdown backend to simulate this situation. HttpClient throws WebAssembly.JSException with message
TypeError: Failed to fetch
Is it OK?
I think it is confusing.
I afraid if I will depend from this behavior, there will be problems.
How can I properly handle this case?
The following code snippet describes how you perform an HTTP GET call to a Web Api endpoint, querying the value of IsSuccessStatusCode which indicates whether the HTTP response was successful or not. If successful, the code retrieves the data stream, deserialize it into a List<Contact>, and returns it to the calling code.
If not successful (else clause), handle failure...here you can place whatever checking you want to make, logging errors, displaying messages, etc.
What I'm trying to show here is the direction how to solve not only that issue of yours, but other exception such as NotFound ( 404 ) exception, etc.
You may also use the response.EnsureSuccessStatusCode(); in a try/catch block and handles exceptions according to your needs.
You can do all this in various manners...
public async Task<List<Contact>> GetContactsAsync()
{
var response = await httpClient.GetAsync("api/contacts");
// response.EnsureSuccessStatusCode();
if (response.IsSuccessStatusCode)
{
// Handle success
var responseContent = await response.Content.ReadAsStreamAsync();
return await JsonSerializer.DeserializeAsync<List<Contact>>(responseContent);
}
else
{
// Handle failure
}
}

How do I acknowledge a Stripe event in C# immediately but still process it?

Under Stripe best practices for webhooks it states:
If your webhook script performs complex logic, or makes network calls, it’s possible that the script would time out before Stripe sees its complete execution. Ideally, your webhook handler code (acknowledging receipt of an event by returning a 2xx status code) is separate of any other logic you do for that event.
In C# how do I return a 200 response immediately and then carry out some other processing?
You can consider to use Task object. In BackendProcessing() write any custom logic you need. HttpStatusCode.OK will return 200.
public IHttpActionResult YouApiMethod()
{
var customLogic = new[]
{
Task.Run(() => BackendProcessing())
};
return new HttpStatusCodeResult(HttpStatusCode.OK);
}

How to set up HTTP outputs in Azure Functions

I've got a simple Azure function for which I set up a DocumentDB output (as an example):
I then added the outputDocument parameter to the function and assigned a value to it in the code (by the way I was surprised that when I set up the output that the runtime didn't automatically modify the function signature):
using System;
public static void Run(string input, out object outputDocument, TraceWriter log)
{
log.Info($"C# manually triggered function called with input: {input}");
outputDocument = new {
text = $"I'm running in a C# function! {input}"
};
}
When I run the function the Azure Functions runtime does it's binding magic and the DocumentDB document gets created.
I then set up an HTTP output:
and defined the res output parameter.
But now what? What's the process of assigning to res? I've of course got to define the destination, request type, parms, etc.
Howiecamp,
The HTTP output binding works in conjunction with the HTTP Trigger to act as the response handler for an HTTP request.
Currently, there isn't an output binding that would send the output payload over HTTP for you, so you'd need to make that HTTP request from your function code (e.g. using the HttpClient and issuing the request). You can see an example in one of our templates here: https://github.com/Azure/azure-webjobs-sdk-templates/blob/10650dbf9c4bad75b0c89b9c355edc53fe913cde/Templates/GitHubCommenter-CSharp/run.csx#L40-L49
I hope this helps!

NancyFX error when doing per-route authentication in async route handler

When I try to handle a route asynchronously and within that route I do the authentication, Nancy throws a RouteExecutionEarlyExitException and then the status code 500 (Internal Server Error) is returned instead of 401 (Unauthorized).
My route handler looks roughly like this:
Get["route/to/private/stuff", true] = async (args, ct) =>
{
this.RequiresAuthentication()
// process request
}
I followed the guidelines here to configure stateless authentication.
It works as expected (throws exception internally, but returns 401) when my route handler looks like this:
Get["route/to/private/stuff"] = args =>
{
this.RequiresAuthentication()
// process request
}
How do I get Nancy to return 401 in an async route handler with per-route authentication?
I'm using Nancy 1.0.0.
Ok, now I got it. Unfortunately I provided too little information.
I wasn't quite honest of how I process the request. Nancy fails with a 500 instead of a 401 when the RouteExecutionEarlyExitException is thrown synchronously, like here:
Get["/", true] = (args, ct) =>
{
this.RequiresAuthentication();
return Task.FromResult((object) "Hello World!");
};
AFAIK that wouldn't happen when Nancy used await when invoking the route handler (i.e. await handler(args, ct)) but it can happen when the handler is invoked synchronously (i.e. handler(args, ct).ContinueWith(...)).
And it seems as Nancy uses the latter approach.
So the solution is to either stick with the async modifier or ensure that exceptions are only thrown asynchronously (e.g. within Task.Run).

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.

Categories