Azure functions post issue - azure

Hi Iam new to Azure functions i am using VS 2017 15.4 and running helloworld function app on local. i was able to do get request on this function but when i perform post on same uri it gives.
mscorlib: Exception while executing function: HelloWorld. System.Net.Http.Formatting: No MediaTypeFormatter is available to read an object of type 'Object' from content with media type 'application/octet-stream'.
can you tell me what i forgot bold line is giving problem in post request, i tried with contentType and without ContentType; with body and without body.
How can i parse Json object in request body in azure function. one way i could was to parse it in string then deserialized using jsonconvert. is their any better way of doing it like valueproviders modelbinders etc.
[FunctionName("HelloWorld")]
public static async Task Run([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
// Get request body
*dynamic data = await req.Content.ReadAsAsync<object>();*
// Set name to query string or body data
name = name ?? data?.name;
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}.

This should work assuming the Content-Type header on your HTTP request is set to application/json.
Note that if the header's value is multipart/form-data, then this is a known bug documented here.

As Connor said as long as the Content-Type header is set to application/json in your request this code will work fine. An issue I have run into though is that the add header functionality when testing azure functions in azure portal doesn't seem to work in this case.
If you can send a request to your function from outside of the test section of azure functions this should work fine.

Related

Passing email content into an Azure Function App

I want to pass the contents of an email into my Function App in order to remove HTML.
I'm following this tutorial but I'm puzzled at how the incoming email is passed in. I know that it is a http request but not sure which line is dealing with this email that we can then do work on.
We have our req which is our http request so I'm guessing that once we create the trigger in Azure, req is passed straight in?
This the example code that is provided:
#r "Newtonsoft.Json"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Text.RegularExpressions;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log) {
log.LogInformation("HttpWebhook triggered");
// Parse query parameter
string emailBodyContent = await new StreamReader(req.Body).ReadToEndAsync();
// Replace HTML with other characters
string updatedBody = Regex.Replace(emailBodyContent, "<.*?>", string.Empty);
updatedBody = updatedBody.Replace("\\r\\n", " ");
updatedBody = updatedBody.Replace(#" ", " ");
// Return cleaned text
return (ActionResult)new OkObjectResult(new { updatedBody });
}
req.Body is the body of your HTTP message when you send a POST request to your Function. So the body of your request should contain your entire email content, then you should be good to go.
Actually your comment // Parse query parameter is wrong. It is not parsing a query parameter but reading the HTTP message body.
btw: I would advise you to do yourself a favor and not write C# Script Functions in the Azure Portal but write and test them locally, e.g. in VS Code, then compile them and deploy them properly to Azure Functions.

Azure functions http trigger Unity3d 2019.3

I've created a test HTTP Trigger azure function. I can trigger it correctly on azure portal and browser. However trigger from Unity editor gives "Error HTTP/1.1 500 Internal Server Error".
starting Azure function:
public static async Task<IActionResult> Run(HttpRequest req, ILogger log){
log.LogInformation("C# HTTP trigger function processed a request.");
string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
name = name ?? data?.name;
return name != null
? (ActionResult)new OkObjectResult($"Hello, {name}")
: new BadRequestObjectResult("Please pass a name on the query string or in the request body");}
My Unity code:
formData.Add(new MultipartFormDataSection("name", "SampleName", "text/plain"));
UnityWebRequest www = UnityWebRequest.Post("https://samplefunction.azurewebsites.net/api/HttpTriggerTest?herelongblob", formData);
yield return www.SendWebRequest();
Azure CORS configuration: Request Credentials ON: Enable Access-Control-Allow-Credentials.
Function is setup always on. Integrate-Trigger: selected methods GET, POST. Authorisation level:Function.
function's host.json: "version": "2.0", "extensionBundle": { "id": "Microsoft.Azure.Functions.ExtensionBundle", "version": "[1.*, 2.0.0)"
App Service authentication:Anonymous
Unity-Azure sdk and google setup search results seems all outdated/not supported :(
What route should I take to get this to work please? happy to try any sdk / unity asset store to reach azure you may suggest! Cheers!
The error occurs in the two lines below in your code:
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
Since you set text/plain in your code. So when you do the www.SendWebRequest(), it will send a form data but not a json format data. So it will show the error message.
Below I provide the code for your reference:
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
var arr = req.Form.Keys;
foreach (var key in arr) {
log.LogInformation(key);
log.LogInformation(req.Form[key]);
}
return (ActionResult)new OkObjectResult("success");
}
You can get the key and the value of the form data in the code above and then compose them to json format and then do DeserializeObject. Or if you want to use the data to create a object, you can even do not do DeserializeObject and just set the value into your object directly.
By the way, you can also try to change the text/plain to application/json in your code new MultipartFormDataSection("name", "SampleName", "text/plain"). But, as I don't know much about MultipartFormDataSection, so I'm not sure if this solution can work.
Hope it helps.

Azure Function response null when returning to Logic App

Can't seem to get my c# Azure Function to return data to my logic app correctly. Within the local Function testing I get the data correctly. When I call it from the Logic App I can see the content length returns as 0 when returned as a string. If I pass it as a json with number=foo, I can get the "number" key entry, but the value from foo is still blank.
Local run within the Function gives the results
Data returned to the logic app shows Content length is 0
output binding is default
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(foo, Encoding.UTF8, "application/json")
};
As I have tested, it works fine in my site.
Within the local Function testing I get the data correctly.
You mean you use azure portal to run the function and you could get the data.
I am not sure if you make some logical judgments on foo. If the foo value it null it would get the second picture you provided.
Here are my working steps and you could refer to:
1.Test with azure function on portal
public static HttpResponseMessage Run(HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
string foo="123456789";
return new HttpResponseMessage(HttpStatusCode.OK)
{
Content = new StringContent(foo, Encoding.UTF8, "application/json")
};
}
2.Logic app design: use queue trigger
3.Add message in queue.

How to troubleshoot Flaky Azure function app behaviour?

I am trying out Azure Function Apps.
The first one following the example in a tutorial with Open Weather map, stopped working after I used log.WriteLine(), which correctly threw a compiler error. I changed to log.Info() and it kept complaining about TraceWriter not containing a definition for WriteLine.
After a lengthy troubleshooting session, I created a new function, copying all the content of the broken one, and it worked immediately.
Created a new function, as before, and began making changes to the Run() method, and running this function yields:
"The resource you are looking for has been removed, had its name
changed, or is temporarily unavailable."
Bearing in mind, the function URL is based on the default key Azure generates when the function is created: https://.azurewebsites.net/api/WeatherWhereYouAre?code=my1really2RAndom3defauLT4Key5from6Azure==
Created yet another function, with no changes from the default "Hello Azure" sample, and it yields a 500 error with:
"Exception while executing function: Functions.HttpTriggerCSharp2 ->
One or more errors occurred. -> Exception binding parameter 'req' ->
Input string was not in a correct format."
This is the content of the project.json file:
{
"frameworks": {
"net46": {
"dependencies": {
"Microsoft.IdentityModel.Clients.ActiveDirectory": "3.16.0",
"Microsoft.Azure.KeyVault": "2.3.2",
"Microsoft.AspNet.WebApi.Client": "5.2.3"
}
}
}
}
And the run.csx:
using System.Net;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
// Set name to query string or body data
name = name ?? data?.name;
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}
EDIT
In the above image, note that this is httpTriggerFSharp1, but the exception is HttpTriggerCSharp2 (which is the only one that works!)
Is there a way I can properly troubleshoot these?
For the default HttpTrigger template for C#, you could call it as follows:
Get https://brucefunapp.azurewebsites.net/api/HttpTriggerCSharp3?name=bruce&code=ItDhLMxwDYmTvMTYzVbbALtL5GEcmaL5DlzSaD4FRIuFdh17ZkY71g==
Or
Post https://brucefunapp.azurewebsites.net/api/HttpTriggerCSharp3?code=ItDhLMxwDYmTvMTYzVbbALtL5GEcmaL5DlzSaD4FRIuFdh17ZkY71g==
Content-type: application/json
{"name": "bruce"}
For more details about Azure Functions C# script, you could refer to here.
Is there a way I can properly troubleshoot these?
Per my understanding, you could leverage Precompiled functions and use Visual Studio 2017 Tools for Azure Functions for creating, local debugging, and publishing to Azure.

Error sending request from Azure Function

I have an Azure Function that I have configured that listens for incoming messages to an Azure Service Bus. I can receive the messages without a problem. But when I try to route the request onto another service for processing, I am getting an error stating that the POST data is empty.
public static void Run(BrokeredMessage message, TraceWriter log)
{
log.Info($"C# ServiceBus queue trigger function processed message: {message.MessageId}");
if (message != null)
{
//MessageObjectEntity is a custom object
Common.Entities.MessageObjectEntity messageObject = message?.GetBody<Common.Entities.MessageObjectEntity>();
string msgType = messageObject?.MessageType;
var msgContent = messageObject?.MessageContent; // MessageContent is of type object to allow any object to be sent
using (var client = new HttpClient())
{
string url = $"http://mycompany.azurewebsites.net/api/routingtasks?formname={msgType}";
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(subscriber, token);
HttpContent content = new StringContent((string)msgContent, Encoding.UTF8, "application/json");
var response = client.PostAsync(new Uri(url), content); // at this point content is valid
// I am getting a BadRequest returned here as the target service has not received the POST data
// that was sent in via the content variable
}
log.Info("Completing message.");
}
It appears that the POST data sent in the variable content is not received despite it being sent.
UPDATE
When I inspect the JSON sent to my Azure Function in the logger it looks like this.
{"FormName":"UpdateMileage","FormData":[{"Key":"enteredmileage","Value":100},{"Key":"todaysdate","Value":"01/01/2017"}],"Profile":{"EmailAddress":"unittest#mycompany.co.uk","ID":9999999}}
Which doesn't work.
But if I hard code the following JSON from my Azure Function it works correctly (the double quotes are needed to escape the back-slashes).
"\"{\\\"FormName\\\":\\\"UpdateMileage\\\","\\\"FormData\\\":"[{\\\"Key\\\":\\\"enteredmileage\\\",\\\"Value\\\":100},"{\\\"Key\\\":\\\"todaysdate\\\",\\\"Value\\\":\\\"01/01/2017\\\"}],"\\\"Profile\\\":"{\\\"EmailAddress\\\":\\\"unittest#mycompany.co.uk\\\","\\\"ID\\\":9999999}}\""
The problem therefore appears to be the formatting of the JSON that is being sent from my Azure Function, but I don't how I would convert my JSON into this format.
The problem was caused by the fact that I was sending JSON to my ASP.NET Web API service, but sending it as a string type. This is wrong.
The following article explains the correct approach when sending JSON data as a POST request.

Resources