HTTP trigger azure function with blob output binding - c#

I need to save my HTTP message to the blob. I am using the below code. the file is getting created but without content. I need the XML data to be stored in the blob
[FunctionName("Function11")
public static async Task <IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
[Blob("Order/sales_{Datetimenow}.xml", FileAccess.Write, Connection = "AzureWebJobsStorage")] Stream outputStream)
{
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return new OkObjectResult(requestBody);
}

Looking at the code you posted, and explicitly this part
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
return new OkObjectResult(requestBody);
it shows that you are...
reading the body of the POST
putting the body in the requestBody variable
returning an OkObjectResult with requestBody as the content
What you are NOT doing is writing the body to the outputStream. You should either create a StreamWriter and write to the stream, otherwise there's nothing to be written to the stream.

Thank you.
[FunctionName("HTTPTrigger")]
public static async Task RunAsync(
[HttpTrigger(AuthorizationLevel.Function, "post", Route = null)] HttpRequest req,
[Blob("sample/order{DateTime.now}.xml", FileAccess.Write, Connection = "AzureWebJobsStorage")] Stream oStream, ILogger log)
{
var requestBody = await new StreamReader(req.Body).ReadToEndAsync();
oStream.Write(Encoding.UTF8.GetBytes(requestBody));
return new OkObjectResult(requestBody);

Related

Httpclient POST request not working properly

[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var data = new { key = key, id = req.Query["mailid"] };
var result = await myHttpClient.PostAsJsonAsync("https://someapi.com/api/info", data);
return new OkObjectResult(result);
}
Hi.
Im trying to build an azure function, which gets the variable mailid and sends a POST request to an API with the apikey and the mailID in a body, so it can check the status of the mail and give back if its delivered or not. I dont get it to work and "result" returns a json of the httpClient, with the error code 500. Why doesnt the request work? The API expects the key and id in a JSON format in the POST-body.
[FunctionName("Function1")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
string mailid = req.Query["mailid"];
var data = new Dictionary<string, string> {
{ "key", key },
{ "id", mailid },
};
//var data = new { key = key, id = req.Query["mailid"] };
var json = JsonConvert.SerializeObject(data, Formatting.Indented);
var stringContent = new StringContent(json);
myHttpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
var result = await myHttpClient.PostAsync("https://someapi.com/api/info", stringContent);
var responseString = await result.Content.ReadAsStringAsync();
return new OkObjectResult(responseString);
}
I just got it to work without an anonymous type variable, which the senior advised me to use. This gets me the result I wanted. It seems like it didnt get send in the proper post-body, as a proper json.

How to Read & Write to same Blob file in Azure Function (.NET6)

In Azure Function V1 (.NET4) code below worked fine
[FunctionName("run")]
public static HttpResponseMessage run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage request,
[Blob("sample.txt", FileAccess.Read)] Stream readStream,
[Blob("sample.txt", FileAccess.Write)] Stream writeStream)
{
//read & write to sample.txt stream works ok
}
But in Azure Function V4 (.NET 6), throws error that only 1 stream can be accessed
[FunctionName("run")]
public static HttpResponseMessage run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage request,
[Blob("sample.txt", FileAccess.Read)] Stream readStream,
[Blob("sample.txt", FileAccess.Write)] Stream writeStream)
{
//can ONLY use read stream or write stream, can't use both
}
How to Read & Write to same Blob file in Azure Function (.NET6)?
Note: issue only appears in Azure not in local debugging
Final solution that worked in Azure Function V4 (.NET 6) is BlobClient
Code to use BlobClient to read/write files in blob storage
[FunctionName("Function1")]
public static async Task<IActionResult> Function1(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage incomingRequest,
[Blob("container-name/file-name.xml", FileAccess.ReadWrite)] BlobClient fileBlobClient)
{ ... }
After reproducing from our end, This was working even though we have added 2 streams. Make sure your environment is up to date.
[FunctionName("Function1")]
public static void Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = null)] HttpRequestMessage req,
[Blob("samples-workitems/samples.txt", FileAccess.Read)] Stream readStream,
[Blob("samples-workitems/samples.txt", FileAccess.Write)] Stream writeStream)
{
Console.WriteLine("Blob length is "+ readStream.Length);
string sample = "Sample Text";
byte[] bytes = Encoding.ASCII.GetBytes(sample);
writeStream.Write(bytes, 0, bytes.Length);
}
Considering this to be my initial text file
RESULT:
Text file after post-trigger

Error: Cannot convert from Microsoft.AspNetCore.Http.IFormFile to System.IO.Stream

I'm trying to create Azure function which takes image file from html form POST request and saves it to Blob Storage for further usage with another function. Here is my code:
public static class Function2
{
[FunctionName("Function2")]
public static async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
foreach (var file in req.Form.Files)
{
using (var ms = new MemoryStream())
{
var file2 = req.Form.Files[0];
await file2.CopyToAsync(ms);
ms.Seek(0, SeekOrigin.Begin);
var connectionString = "DefaultEndpointsProtocol=https;" +
"AccountName=mystorageaccount;" +
"AccountKey=8Hk5k6j65j5j665j67k==;" +
"EndpointSuffix=core.windows.net";
// intialize BobClient
Azure.Storage.Blobs.BlobClient blobClient = new Azure.Storage.Blobs.BlobClient(
connectionString: connectionString,
blobContainerName: "image-storage",
blobName: "images");
// upload the file
blobClient.Upload(file2);
}
}
return new OkResult("Image uploaded successfully");
}
}
However this raises exception:
Error CS1503 Argument 1: cannot convert from
'Microsoft.AspNetCore.Http.IFormFile' to 'System.IO.Stream'
Any advise would be very highly appreciated.
Edit: I have previously created Blob Container "image-storage" to my storage account using Azure Portal.
BlobCients Upload method expects a Stream instead of an IFormFile.
Passing the MemoryStream you have in the ms variable will resolve the issue.
blobClient.Upload(ms);

Blob binding in httpTrigger not working in VS2017 Azure function template

I want to pass the filename of blob to the httptrigger, through get request as below.
http://localhost:7071/api/CSVDataMigrationHttpTrigger/testdata.csv
Code for the azure function
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "CSVDataMigrationHttpTrigger/{name}")]
HttpRequest req, string name,
[Blob("csvdata-upload/{name}", FileAccess.Read, Connection = "AzureWebJobsStorage")]
Stream inputBlob, ILogger log)
{}
inputBlob parameter is not resolved and it returns null.
But if i give filename as "testData.csv" as below in the Blob parameter, then inputBlob get resolved properly.
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = "CSVDataMigrationHttpTrigger/{name}")]
HttpRequest req, string name,
[Blob("csvdata-upload/testData.csv", FileAccess.Read, Connection = "AzureWebJobsStorage")]
Stream inputBlob, ILogger log){}
I found out finally, the filename was case sensitive, when passed to blob. Hope it helps anyone who has the same issue.
Check whether your blob is actually uploaded in the Storage Container. The stream will be null only if the blob is Not Exist/Unable to find in the container

Azure Function Access CloudBlobContainer from HttpTriggerFunction

Very, very new to Azure Functions and getting very frustrated.
All I want to do is execute on a 'get' request from a HttpTriggerFunction and return stream content from the CloudBlobContainer.
I really don't see why this is so hard. Just trying to host a SPA using Azure Functions.
Something like this
public static class UIHandler
{
[FunctionName("UIHandler")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = null)]HttpRequest req,
TraceWriter log,
CloudBlobContainer container)
{
log.Info("C# HTTP trigger function processed a request.");
var stream = await container.GetBlockBlobReference({Infer file name from request here}).OpenReadAsync();
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(stream)
};
}
}
When I try to run this I get the following error.
Run: Microsoft.Azure.WebJobs.Host: Error indexing method
'UIHandler.Run'. Microsoft.Azure.WebJobs.Host: Cannot bind parameter
'container' to type CloudBlobContainer. Make sure the parameter Type
is supported by the binding. If you're using binding extensions (e.g.
ServiceBus, Timers, etc.) make sure you've called the registration
method for the extension(s) in your startup code (e.g.
config.UseServiceBus(), config.UseTimers(), etc.).
I'm using Azure Functions 2. I can't see from the web how to setup the browsing extensions for this. Iv'e also looked into Input and Output bindings. I don't understand what makes a parameter input or output bound when your using C# that only seems to exist in the JSON.
Do I need to corresponding JSON file ? If so what is it called where does it go.
Thanks in Advance
Have a look at Blob Storage Input Binding. The very first sample there shows how to read blob stream, just replace Queue Trigger with HTTP trigger, e.g.
[FunctionName("UIHandler")]
public static async Task<HttpResponseMessage> Run(
[HttpTrigger(AuthorizationLevel.Function, "get", Route = "{name}")] HttpRequest req,
string name,
TraceWriter log,
[Blob("samples-workitems/{name}", FileAccess.Read)] Stream stream)
{
log.Info($"C# HTTP trigger function processed a request for {name}.");
return new HttpResponseMessage()
{
StatusCode = HttpStatusCode.OK,
Content = new StreamContent(stream)
};
}

Categories

Resources