azure-functions-templates
azure-functions-templates copied to clipboard
Update Visual Studio templates to use "nameof" instead of hardcoded function name
Original issue posted by @Andrew-MSFT at https://github.com/Azure/Azure-Functions/issues/763
Currently the function templates hardcode the string to match the name of the class. The suggestion is to change the hardcoded string in the FunctionName attribute to be a nameof the class. This makes refactoring much cleaner since by default the function name will always match the class name.
So
public static class Function1 { [FunctionName("Function1")] public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", ...
would become
public static class Function1 { [FunctionName(nameof(Function1))] public static IActionResult Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", ...
@fabiocav thinks we started doing this at some point and stopped (can we remember why?)
It drives me crazy that it doesn't use nameof
by default. It's the first thing I change. Every. Time.
This will be especially useful for the Durable Function template. Note that I think we should do the name of the method and not the name of the class? Specifically for durable template you have multiple functions in same class:
using System.Collections.Generic;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.Extensions.Logging;
namespace durabledemorunthrough
{
public static class Function1
{
[FunctionName(nameof(RunOrchestrator))]
public static async Task<List<string>> RunOrchestrator(
[OrchestrationTrigger] DurableOrchestrationContext context)
{
var outputs = new List<string>();
// Replace "hello" with the name of your Durable Activity Function.
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Tokyo"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "Seattle"));
outputs.Add(await context.CallActivityAsync<string>(nameof(SayHello), "London"));
// returns ["Hello Tokyo!", "Hello Seattle!", "Hello London!"]
return outputs;
}
[FunctionName(nameof(SayHello))]
public static string SayHello([ActivityTrigger] string name, ILogger log)
{
log.LogInformation($"Saying hello to {name}.");
return $"Hello {name}!";
}
[FunctionName(nameof(HttpStart))]
public static async Task<HttpResponseMessage> HttpStart(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post")]HttpRequestMessage req,
[OrchestrationClient]DurableOrchestrationClient starter,
ILogger log)
{
// Function input comes from the request content.
string instanceId = await starter.StartNewAsync(nameof(RunOrchestrator), null);
log.LogInformation($"Started orchestration with ID = '{instanceId}'.");
return starter.CreateCheckStatusResponse(req, instanceId);
}
}
}
@cgillum as FYI - I think I'm quite partial to switching docs and samples for durable to use nameof()
instead. Makes renaming a bit easier and clear relationship at a compile-time level for things like CallActivityAsync
and the function.
I still can't remember why we didn't do this the first time it came up. Is it possible that there are valid C# method names that are invalid function names? That might be a reason.
I recall either Mike saying this or reading a comment in the WebJobs code that function names must be valid C# identifiers. If that's the case, it seems like it would be safe to do this. But even so, if we control the templates, it seems it would be safe for us to use nameof
.
I considered that maybe there was a reason related to name conflicts (e.g. if two functions had the same method name - like method overloads) but even then I think WebJobs explicitly blocks that.
Seems like everyone is for this change, and I am here in 2023 and still changing from magic strings to nameof
in Azure Functions 😛