如何在 Azure Functions C# 上以简单的方式获取 GET 查询参数?

Posted

技术标签:

【中文标题】如何在 Azure Functions C# 上以简单的方式获取 GET 查询参数?【英文标题】:How to get the GET Query Parameters in a simple way on Azure Functions C#? 【发布时间】:2018-09-24 18:16:33 【问题描述】:

我尝试了以下方法:

/// <summary>
/// Request the Facebook Token
/// </summary>
[FunctionName("SolicitaFacebookToken")]
[Route("SolicitaToken/?fbAppID=fbAppID&fbCode=fbCode&fbAppSecret=fbAppSecret")]
public static async Task<HttpResponseMessage> SolicitaFacebookToken(
    [HttpTrigger(AuthorizationLevel.Function, methods: new string[]  "get"  )]
    HttpRequestMessage req,
    TraceWriter log,
    string fbAppID,
    string fbCode,
    string fbAppSecret
)
 

当我访问 URL 时:

http://localhost:7071/api/SolicitaFacebookToken/?fbAppID=ABC&fbCode=DEF&fbAppSecret=GHI

但它给出了这些错误:

'SolicitaFacebookToken' can't be invoked from Azure WebJobs SDK. Is it missing Azure WebJobs SDK attributes?
System.InvalidOperationException : 'SolicitaFacebookToken' can't be invoked from Azure WebJobs SDK. Is it missing Azure WebJobs SDK
attributes?
 at Microsoft.Azure.WebJobs.JobHost.Validate(IFunctionDefinition function,Object key)
 at async Microsoft.Azure.WebJobs.JobHost.CallAsync(??)
 at async Microsoft.Azure.WebJobs.Script.ScriptHost.CallAsync(String method,Dictionary\`2 arguments,CancellationToken cancellationToken)
 at async Microsoft.Azure.WebJobs.Script.WebHost.WebScriptHostManager.HandleRequestAsync(FunctionDescriptor function,HttpRequestMessage request,CancellationToken cancellationToken)
 at async Microsoft.Azure.WebJobs.Script.Host.FunctionRequestInvoker.ProcessRequestAsync(HttpRequestMessage request,CancellationToken cancellationToken,WebScriptHostManager scriptHostManager,WebHookReceiverManager webHookReceiverManager)
 at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.<>c__DisplayClass3_0.<ExecuteAsync>b__0(??)
 at async Microsoft.Azure.WebJobs.Extensions.Http.HttpRequestManager.ProcessRequestAsync(HttpRequestMessage request,Func`3 processRequestHandler,CancellationToken cancellationToken)
 at async Microsoft.Azure.WebJobs.Script.WebHost.Controllers.FunctionsController.ExecuteAsync(HttpControllerContext controllerContext,CancellationToken cancellationToken)
 at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
 at async System.Web.Http.Dispatcher.HttpControllerDispatcher.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
 at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.WebScriptHostHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
 at async Microsoft.Azure.WebJobs.Script.WebHost.Handlers.SystemTraceHandler.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)
 at async System.Web.Http.HttpServer.SendAsync(HttpRequestMessage request,CancellationToken cancellationToken)

如果我改成这样:


HttpRequestMessage req,
string fbAppID,
string fbCode,
string fbAppSecret,
TraceWriter log

以下1个函数有误:

SolicitaFacebookToken:Microsoft.Azure.WebJobs.Host:索引方法“Function1.SolicitaFacebookToken”出错。 Microsoft.Azure.WebJobs.Host:无法将参数“fbAppID”绑定到字符串类型。确保绑定支持参数类型。如果您正在使用绑定扩展(例如 ServiceBus、Timers 等),请确保您已在启动代码中调用了扩展的注册方法(例如 config.UseServiceBus()、config.UseTimers() 等.).

在 Azure Functions 模板代码中,有

string name = req.GetQueryNameValuePairs()
                 .FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
                 .Value;

我想要一种更简单的方法来获取 GET 查询参数。

我想要这样的网址:

http://localhost:7071/api/SolicitaFacebookToken/?fbAppID=123&fbCode=456&fbAppSecret=789

:如何轻松获取参数及其值?

【问题讨论】:

【参考方案1】:

对于 v2/beta/.NET Core 运行时,您可以具体执行:

string fbAppID = req.Query["fbAppID"];

或更多通用

using System.Collections.Generic;
...
IDictionary<string, string> queryParams = req.GetQueryParameterDictionary();
// Use queryParams["fbAppID"] to read keys from the dictionary.

对于 v1 函数应用(.NET 完整框架):

using System.Collections.Generic;
...
IDictionary<string, string> queryParams = req.GetQueryNameValuePairs()
    .ToDictionary(x => x.Key, x => x.Value);
// Use queryParams["fbAppID"] to read keys from the dictionary.

【讨论】:

我试过 req.Query["fbAppID"];得到这个编译错误:CS1061'HttpRequestMessage'不包含'Query'的定义,并且找不到接受'HttpRequestMessage'类型的第一个参数的扩展方法'Query'(您是否缺少使用指令或程序集引用?) 很可能您使用的是 v1 运行时,请使用 req.GetQueryNameValuePairs(),见上文。 你是对的!我以为我在v2上,当我现在再次检查时,它在v1上。我将在 v2 中重新创建项目,谢谢!【参考方案2】:

过去,当我有多个参数时,我会将它们添加到路由中。所以不要这样:

[Route("SolicitaToken/?fbAppID=fbAppID&fbCode=fbCode&fbAppSecret=fbAppSecret")]

我做过这样的事情:

[Route("SolicitaToken/fbAppID/fbCode/fbAppSecret")]

那么你根本不需要访问查询字符串,可以直接使用函数参数。

[FunctionName("Function1")]
public static HttpResponseMessage Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "HttpTriggerCSharp/name/fbAppID/fbCode/fbAppSecret")]HttpRequestMessage req, string fbAppID, string fbCode, string fbAppSecret, TraceWriter log)

  log.Info("C# HTTP trigger function processed a request.");
  var msg = $"App ID: fbAppID, Code: fbCode, Secret: fbAppSecret";
  // Fetching the name from the path parameter in the request URL
  return req.CreateResponse(HttpStatusCode.OK, msg);

【讨论】:

这行得通。但我想要 SolicitaToken/?fbAppID=fbAppID&fbCode=fbCode&fbAppSecret=fbAppSecret ... 不能有 name=value 形式的 GET 参数吗? 参数值包含 ´/´ 存在问题,即使编码为 %2F 也无法正确解析,生成 404 而不是调用路由函数。 请注意,将查询参数放在路由中被认为是不好的做法。最佳实践是路径参数标识资源as mentioned here。【参考方案3】:

在 v2 运行时,另一种获取查询参数的方法:

var query = System.Web.HttpUtility.ParseQueryString(req.RequestUri.Query);
string result = query.Get("result");

希望这会有所帮助。

【讨论】:

【参考方案4】:

您可以获取所有查询参数,例如:

   foreach (var q in req.Query)
   
     log.LogWarning($"Query param Key q.Key has value q.Value"); 
   

【讨论】:

【参考方案5】:

Azure Functions 运行时 v3:

 var query = System.Web.HttpUtility.ParseQueryString(req.Url.Query);

【讨论】:

【参考方案6】:

在您的函数中,您可以使用HttpRequestMessage requestMessageHttpRequest request。我看到上面使用了第一个,但后者支持request.Query["myParameter"] 语法。

【讨论】:

【参考方案7】:

对我来说,在 get 方法中处理查询参数的最简单方法是定义一个 PoCo 对象并使用 [FromQuery] 属性,就像我在 .Net Web API 中使用的那样。

不幸的是,我最初使用 HTTP 触发的 Azure 函数执行此操作的方法导致原始问题中描述的相同的异常

经过一番谷歌搜索后,我几乎失去了所有希望,因为所有参考资料(至少是我找到的那些参考资料)都表明这是不可能的,或者他们只是希望您使用路由配置或从请求中获取查询参数对象或不使用 GET 而是使用 POST 请求并传递您想要作为请求正文的一部分传递的内容...

由于所有这些都不是很令人满意,我正准备为我想在对函数的 GET 请求中使用的 POCO 对象实现我自己的自定义 BindingProvider...

然后我仔细查看了 azure-webjobs-sdk-extensions 的来源,发现:HttpDirectRequestBindingProvider

来自对该课程的评论:

// support allowing binding any non-attributed HttpRequest parameter to the incoming http request. 
//    Foo([HttpTrigger] Poco x, HttpRequest y); 

事实证明,以下内容实际上受支持并按预期工作:

Tl;博士;

确保你要携带查询参数信息的PoCo是你函数的第一个参数!把它放在别的地方会再次出现原来的异常!

public async Task<IActionResult> Foo([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = null)]
    PaginationFilter paginationFilter, HttpRequest req, ClaimsPrincipal principal, CancellationToken cancellationToken)

在我的例子中,PaginationFilter 类型是这样指定的:

请注意,这只是一个示例。您可以在函数签名中使用任何类似 PoCo 的类型,只要它是 JSON 可序列化的并且具有默认构造函数。

public record PaginationFilter

    public PaginationFilter()
        : this(Constants.DefaultPageSize, 1)
     

    public PaginationFilter(Int32 limit, Int32 page)
    
        Limit = limit;
        Page = page;
    

    public Int32 Limit  get; init; 

    public Int32 Page  get; init; 

使用此签名支持的查询:

http://localhost:7071/api/Foo?Limit=50&Page=1
or
http://localhost:7071/api/Foo?Limit=50
or
http://localhost:7071/api/Foo?Page=1
or
http://localhost:7071/api/Foo

另请参阅我在 Azure-Functions GitHub Issues 上对相关问题的原始回答

【讨论】:

以上是关于如何在 Azure Functions C# 上以简单的方式获取 GET 查询参数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Visual Studio 中使用 .NET 5(独立进程)调试 Azure Functions?

Azure Functions - Blob 流动态输入绑定

AZURE_FUNCTIONS_ENVIRONMENT 与 ASPNETCORE_ENVIRONMENT

如何在 azure 上以编程方式托管 wcf 服务

C# Azure Function - CosmosDB 触发和解析文档数据

如何在 .NET 5 隔离进程中使用 Azure Functions v3 时添加以前在 Startup.cs 中的代码->配置方法