Azure V4 function - unable to get multi-response output binding to work for async function

183 views Asked by At

I am working on an azure v4 function running in dotnet-isolated mode using a multiple response (HttpResponseData and Cosmos DB Output binding)

The code worked when it was called synchronously, recently I started getting an error saying synchronous calls are not allowed.

The issue I have is when I change the return type to be async task, it returns the HttpResponseData to the client as expected but does not write out to the CosmosDB.

In the log I can see the following error:

System.ObjectDisposedException: IFeatureCollection has been disposed

Updated Error info. It is returning status 500 with the following (abbreviated) detail:

System.ObjectDisposedException: IFeatureCollection has been disposed.

Object Name 'Collection'

at Microsoft.Azure.Function.Worker.RPC.RpcExtensions.ToRpcHttpSync (.NetWorker.Grpc\RpcExtensions.cs)

Microsoft.Azure.Functions.Worker.Handlers.InvocationHandler.InvokeAsync(InvocationRequest request)

My MultiReponse class is defined as:

public class MultiResponse {
    [CosmosDBOutput(databaseName:.....]  // Response 1 gets written out to cosmosdb
    public MyDBRecord item {get;set;}    // A class with three public string properties

    public HttpResponseData httpResponse {get;set;}  // Response2 goes back to the client
}

My Azure function had the following definition.

public MultiResponse Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequestData req) 

I basically changed the MultiResponse to async Task< MultiResponse >. The routine that prepares the response is.

MultiResponse resp = new MultiResponse
{
    HttpResponse = req.CreateResponse(statusCode),
    Item = myDbRecord  // Basically a class with 3 public string properties.
};

 resp.HttpResponse.Headers.Add("Content-Type", "text/plain; charset=utf-8");
 await resp.HttpResponse.WriteStringAsync(JsonConvert.SerializeObject(myDbRecord));

 return resp;

I am wondering if I need to change the output binding or something to handle the change to being async.

2

There are 2 answers

0
AndyW On BEST ANSWER

Just an update.

To get it working I needed to remove the async keyword and also any await methods. I still needed to keep the Task as the return type.

Also, any awaitable calls in the method body needed to be changed to use the Task<Response> functionAsync() calling style.

1
akseli On

The issue seems to be that you're attempting to access your Request or Response from outside its scope, which is causing it to get disposed. You might want to try this, to see if it resolves the issue:

var response = req.CreateResponse(statusCode);
response.Headers.Add("Content-Type", "text/plain; charset=utf-8");
    await response.WriteStringAsync(JsonConvert.SerializeObject(myDbRecord));

return new MultiResponse() 
{
    Item = myDbRecord,
    HttpResponse = response
}

This should make sure that you're not attempting to modify your response after it has been committed.