Azure Function 404 Error when running in Logic App
Asked Answered
V

3

5

I have built a simple function in Azure that takes in the location of a file from the json body, and reads the first line to get the headers from said file. I am building the function in Visual Studio and publishing it using a packaged deployment.

I am able to test the function on the portal under Azure Functions and have a return result, but when I try and the function in Logic App's, I am getting 404 Not Found Error.

I have created the sample HTTPRequest Function that MS has given, and that works fine under the same Function Name, but I am not sure why the one I have written is not working.

Below is the code that I used for the function

using System;
using System.IO;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Functions
{
    public static class GetTableHeaders
    {
        [FunctionName("GetTableHeaders")]
        public static async Task<IActionResult> Run(
            [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
            IBinder binder,
            ILogger log)
        {
            log.LogInformation("C# HTTP trigger function processed a request.");

            string guid = req.Query["guid"];
            string header = req.Query["header"];
            string location = req.Query["location"];
            string line = null;
            string[] headers = null;
            int size = 0;

            string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
            dynamic data = JsonConvert.DeserializeObject(requestBody);
            guid = guid ?? data?.guid;
            header = header ?? data?.header;
            location = location ?? data?.location;

            if (guid != null)
            {
                location = location.Substring(1);
                using (var reader = binder.Bind<TextReader>(new BlobAttribute(
                    $"{location}", FileAccess.Read)))
                {
                    line = reader.ReadLine();
                    headers = line.Split(',');
                    size = headers.Length;
                    if (!Convert.ToBoolean(header))
                    {
                        List<string> genericheaders = new List<string>();
                        for (int i = 1; i <= size; i++)
                        {
                            genericheaders.Add($"column{i}");
                        }
                        headers = genericheaders.ToArray();
                    }

                };
                return (ActionResult)new OkObjectResult($"{string.Join("|", headers)}");
            }
            else
            {
                return (ActionResult)new BadRequestObjectResult("Please pass a name on the query string or in the request body");
            }
        }
    }
}

Here is the code that is working in the MS Sample Function:

using System;
using System.IO;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;

namespace Functions
{
    public static class HttpFunction
    {
        [FunctionName("HttpFunction")]
        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 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");
        }
    }
}

Here is the result of the code when I am running it in Azure Functions: Azure Function Result from Azure Function

And here is the error that I am getting from Logic Apps once I try and run using the function: Log App Error

Below is the logic app json (replacing subscription ID with xxxx)

{
    "$connections": {
        "value": {
            "azureblob": {
                "connectionId": "/subscriptions/xxxx/resourceGroups/AMCDS/providers/Microsoft.Web/connections/azureblob",
                "connectionName": "azureblob",
                "id": "/subscriptions/xxxx/providers/Microsoft.Web/locations/westeurope/managedApis/azureblob"
            },
            "sql": {
                "connectionId": "/subscriptions/xxxx/resourceGroups/AMCDS/providers/Microsoft.Web/connections/sql-1",
                "connectionName": "sql-1",
                "id": "/subscriptions/xxxx/providers/Microsoft.Web/locations/westeurope/managedApis/sql"
            }
        }
    },
    "definition": {
        "$schema": "https://schema.management.azure.com/providers/Microsoft.Logic/schemas/2016-06-01/workflowdefinition.json#",
        "actions": {
            "Create_GUID": {
                "inputs": "@guid()",
                "runAfter": {},
                "type": "Compose"
            },
            "GetTableHeaders": {
                "inputs": {
                    "body": {
                        "guid": "@{outputs('Create_GUID')}",
                        "header": "@{body('Insert_row_2')?['HasHeaders']}",
                        "location": "@{triggerBody()?['Path']}"
                    },
                    "function": {
                        "id": "/subscriptions/xxxx/resourceGroups/AMCDS/providers/Microsoft.Web/sites/AMCDSFunctionsWindows/functions/GetTableHeaders"
                    },
                    "method": "POST"
                },
                "runAfter": {
                    "Insert_row_2": [
                        "Succeeded"
                    ]
                },
                "type": "Function"
            },
            "HttpFunction": {
                "inputs": {
                    "body": {
                        "name": "Nirmal"
                    },
                    "function": {
                        "id": "/subscriptions/xxxx/resourceGroups/AMCDS/providers/Microsoft.Web/sites/AMCDSFunctionsWindows/functions/HttpFunction"
                    }
                },
                "runAfter": {
                    "Insert_row_2": [
                        "Succeeded"
                    ]
                },
                "type": "Function"
            },
            "Insert_row_2": {
                "inputs": {
                    "body": {
                        "DataType": "@{outputs('Split_FileName')[3]}",
                        "DateLoaded": "@{utcNow()}",
                        "FileDate": "@{outputs('Split_FileName')[1]}",
                        "FileName": "@triggerBody()?['Name']",
                        "FilePath": "@triggerBody()?['Path']",
                        "GUID": "@{outputs('Create_GUID')}",
                        "HasHeaders": "@if(equals(outputs('Split_FileName')[2],'#Y#'),true,false)"
                    },
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['sql']['connectionId']"
                        }
                    },
                    "method": "post",
                    "path": "/datasets/default/tables/@{encodeURIComponent(encodeURIComponent('[meta].[FileMetadata]'))}/items"
                },
                "runAfter": {
                    "Split_FileName": [
                        "Succeeded"
                    ]
                },
                "type": "ApiConnection"
            },
            "Split_FileName": {
                "inputs": "@split(triggerBody()?['Name'],'.')",
                "runAfter": {
                    "Create_GUID": [
                        "Succeeded"
                    ]
                },
                "type": "Compose"
            }
        },
        "contentVersion": "1.0.0.0",
        "outputs": {},
        "parameters": {
            "$connections": {
                "defaultValue": {},
                "type": "Object"
            }
        },
        "triggers": {
            "When_a_blob_is_added_or_modified_(properties_only)": {
                "inputs": {
                    "host": {
                        "connection": {
                            "name": "@parameters('$connections')['azureblob']['connectionId']"
                        }
                    },
                    "method": "get",
                    "path": "/datasets/default/triggers/batch/onupdatedfile",
                    "queries": {
                        "folderId": "JTJmcmVjZWl2ZWQ=",
                        "maxFileCount": 10
                    }
                },
                "metadata": {
                    "JTJmcmVjZWl2ZWQ=": "/received"
                },
                "recurrence": {
                    "frequency": "Minute",
                    "interval": 1
                },
                "splitOn": "@triggerBody()",
                "type": "ApiConnection"
            }
        }
    }
}
Ventage answered 1/1, 2019 at 12:0 Comment(4)
Could you share the logic app code (the json template) please ?Carmina
@Nirmie, have you tried modifying the working HttpFunction to meat your requirement ? try to go step by step and maybe you'll find something, Sorry dont really know whats hapenning hereCarmina
@Thomas, I did what you said and that worked. Code is like for like and it now works fine using the HttpFunction rather than the one I wrote. I have no idea what has happened. Thanks!Ventage
@Ventage good to ear :-)Carmina
D
5

Have you already cleared this?

I was having the same trouble. It was fixed by using "method" parameters in the logic app JSON.

My function accepted only the "GET" method and the logic app JSON has no method param, so I added the "'method':'GET'" param.

Dictaphone answered 29/4, 2020 at 7:44 Comment(1)
This was the case for me, but instead I enabled POST method on my Function.Dejecta
W
2

The NotFound error happens either when the function app and logic app are located on a seperate location and the logicapp trigger is not able to execute the function. This happened to me alot of times. A simple solution is to deploy both of the resources in the same location and it should work.

Willing answered 2/1, 2019 at 4:22 Comment(1)
I am not sure I understand the comment here. Both my LogicApp and Function are in the same location (West Europe), under the same Resource Group. Also, I am not sure why it would work for the HTTPTrigger Function, but not for the custom one.Ventage
S
0

Just to add one other possible solution.

In my case I re-provision the Function (the Azure resource), but not the function code, then the reference to the function itself was still there, but not the actual dlls.

So, just try testing the function itself as well.

runtime unreacheable


Ah yeah, and be sure that you're not restricting Azure Logic Apps in the Networking > Access Restrictions part of the Function as well, or in the Storage Account (that is, where the code is sitting).

Hope this helps someone.

Sajovich answered 20/6, 2023 at 17:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.