如何将function.json添加到现有的.NET函数2.0

时间:2019-01-31 18:02:13

标签: c# azure azure-functions serverless

当我使用func new --name MyHttpTrigger --template "HttpTrigger"添加新功能时,此函数中没有创建function.json,并且当我尝试将其添加到当前目录并运行func start --build时,出现此错误:

找不到作业功能。尝试公开您的工作类别和方法。如果您使用绑定扩展(例如Azure存储,ServiceBus,Timer等),请确保已在启动代码中调用了扩展的注册方法(例如builder.AddAzureStorage(),builder.AddServiceBus( ),builder.AddTimers()等)。

您可以在这里找到我的function.json内容:

{
  "disabled": false,
  "bindings": [
    {
      "authLevel": "anonymous",
      "name": "req",
      "type": "httpTrigger",
      "direction": "in"
    },
    {
      "name": "res",
      "type": "http",
      "direction": "out"
    }
  ]
}

以前的httpTrigger函数

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

新的httpTrigger函数

namespace final
{
    public static class httpTrigger
    {
        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");
        }
    }
}

1 个答案:

答案 0 :(得分:2)

简短答案 生成过程将根据为方法附加的属性,为.cs文件中定义的功能生成function.json文件。例如,Functions文档中有几个示例。 a BlobTrigger function in C#.您不需要添加自己的function.json

请参阅“长答案”部分,以详细了解其在后台的工作方式。如果您看到描述了已编译的C#函数的所有预期构建输出,并且函数运行时仍未找到任何函数,请检查您是否在函数应用程序结构的顶级目录上运行func start --build。 / p>

详细回答 您描述的行为是设计使然。听起来您已经习惯了脚本语言(例如.csx(C#脚本)文件)所使用的Function的文件夹结构。这是一个定义两个函数MyFunctionMySecondFunction的示例:

FunctionApp
| - bin
| - MyFunction
| | - function.json
| | - run.csx
| - MySecondFunction
| | - function.json
| | - run.csx
| ...
| host.json
| local.settings.json

最初,Functions运行时仅识别此文件夹结构,并且C#函数只能用C#脚本编写。 (original blog announcement | MSDN magazine article)后来,添加了常规C#支持。我将把常规C#称为编译的C#,以强调它与C#脚本之间的区别。

与已编译的C#函数应用程序相同的示例具有这样的文件夹结构:

FunctionApp
| - bin
| - obj
| - host.json
| - local.settings.json
| - FunctionApp.csproj
| - MyFunction.cs
| - MySecondFunction.cs

如果您构建此项目并展开FunctionApp/bin文件夹,则会看到类似以下内容:

FunctionApp
| - bin
| | - Debug
| | | - net461
| | | | - bin
| | | | - MyFunction
| | | | | - function.json
| | | | - MySecondFunction
| | | | | - function.json
| | | - host.json
| | | - local.settings.json
| | | - netstandard2.0
| | | | - …
| - obj
| - host.json
| - local.settings.json
| - FunctionApp.csproj
| - MyFunction.cs
| - MySecondFunction.cs

netstandard2.0文件夹将包含与net461文件夹类似的内容;它们只是不同的框架构建目标。)

请注意之间的相似FunctionApp/bin/Debug/net461 in the compiled C# function app's folder structure and {FunctionApp {1}} HttpTrigger`),以确定哪些功能已被定义并创建原始文件夹结构作为其生成输出。

启动Azure Functions运行时(例如,由in the C# script app's folder structure. This is because the build process for C# (not C# script) function apps uses the attributes of the methods in the .cs files (ex.启动)时,它不会查看func host start来确定存在哪些函数并绑定绑定。它看起来是FunctionApp

在每个功能的文件夹中找到唯一的区别。在已编译的C#函数应用程序中,每个函数的文件夹在C#脚本函数应用程序中都没有.csx文件。仔细查看已编译的C#函数应用程序的FunctionApp/bin/Debug/net461/MyFunction文件夹中的function.json,您会看到类似以下内容:

FunctionApp/bin/Debug/net461/MyFunction

与为C#脚本函数创建的{ "generatedBy": "Microsoft.NET.Sdk.Functions-1.0.13", "configurationSource": "attributes", "bindings": [ { "type": "httpTrigger", "methods": [ "post" ], "authLevel": "function", "name": "req" } ], "disabled": false, "scriptFile": "../bin/VSSample.dll", "entryPoint": "VSSample.HttpStart.Run" } 相比,已编译的C#函数的function.json具有一些额外的字段。这是每个函数运行时的指示:

  • function.json:此generatedBy是在编译期间生成的,不是手工编写的
  • function.json:此configurationSource是从C#属性生成的
  • function.json:包含与此函数相对应的已编译代码的DLL的位置,相对于此scriptFile文件的位置
  • function.json:已编译DLL中函数的方法签名

长话短说,已编译的C#函数应用程序在运行时依赖于与C#脚本函数应用程序相同的文件夹结构,但是它是由构建过程生成的,而不是由开发人员构建的。用已编译的C#编写功能应用程序的开发人员通过C#属性定义其绑定,而将entryPoint的生成留给构建过程。