9

I have an Azure Function and I want to set a custom HTTP endpoint. Following the answer to this SO question, I ended up with something like this:

[FunctionName("DoSomething")]
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "v1/tenants/{tenantId}/locations/{locationId}/products?manufacturer={manufacturer}")]
                HttpRequest request, ILogger logger, string tenantId, string locationId, string manufacturer)
{
        // 
}

However, the route is not accepted by the Webjob:

"v1/tenants/{tenantId}/locations/{locationId}/products?manufacturer={manufacturer}"

The reason is because of the question mark '?':

An error occurred while creating the route with name 'DoSomething' and template 'api/v1/tenants/{tenantId}/locations/{locationId}/products?manufacturer={manufacturer}'. The literal section 'products?manufacturer=' is invalid. Literal sections cannot contain the '?' character. Parameter name: routeTemplate The literal section 'products?manufacturer=' is invalid. Literal sections cannot contain the '?' character.

Question

How can I specify a query parameter in a custom HTTP endpoint of my Azure Function?

Kzryzstof
  • 7,688
  • 10
  • 61
  • 108
  • 2
    Shouldn't it be: `v1/tenants/{tenantId}/location/{locationId}/products/{productId}` ? – Crowcoder Feb 11 '19 at 18:52
  • This was not a typo :) `/products?product={productId}`. I wanted to query a potential product ID at the specified location and I want to make it look like a filter in the query. I will update the question to make it less confusing... – Kzryzstof Feb 11 '19 at 18:55
  • 1
    No, I mean shouldn't you make it that way? That is the conventional method. – Crowcoder Feb 11 '19 at 18:57
  • Oh... Are you saying that I should never use a query parameter in a custom HTTP endpoint and that it should always part of the URL? – Kzryzstof Feb 11 '19 at 19:00
  • no, you can go both ways, query parameter or specify it – 4c74356b41 Feb 11 '19 at 19:10
  • I wanted to use a query parameter because **Swagger / OpenAPI does NOT support optional route/url parameters** (unlike Azure Functions which does). – Peter L Aug 16 '19 at 17:28
  • **See Also**: [How to get the GET Query Parameters in a simple way on Azure Functions C#?](https://stackoverflow.com/q/49833056/1366033) – KyleMit May 17 '21 at 20:40

2 Answers2

8

I am afraid it's not possible to put query parameter in Route.

Microsoft.AspNetCore.Routing: The literal section 'products?manufacturer=' is invalid. Literal sections cannot contain the '?' character.

It's a built-in restriction of ASP.NET Routing, which is used by Azure Function to build route for Http trigger.

allow me to get the value as one of the Run's method parameters instead of poking at the HttpRequest instance

If it's the reason why you want to put query parameter in route, I would suggest you add IDictionary<string, string> query in method signature and use query["manufacturer"] to access the parameter in function code. But honestly it's almost the same as request.Query["manufacturer"].

Or you may have to follow the recommendation, transform the query parameter to route like products/{productId}.

Jerry Liu
  • 17,282
  • 4
  • 40
  • 61
  • In Version 2 it seems to be supported https://learn.microsoft.com/en-us/azure/azure-functions/functions-bindings-http-webhook-trigger?tabs=in-process%2Cfunctionsv2&pivots=programming-language-csharp#customize-the-http-endpoint – Ravinder8198 Apr 23 '22 at 07:15
0

Here's an example of my function that uses query parameters:

public static async Task<HttpResponseMessage> Run( HttpRequestMessage req, TraceWriter log, ExecutionContext context )
{
    string data = await req.Content.ReadAsStringAsync();
    dynamic parsed = JsonConvert.DeserializeObject(data);
    if (parsed == null)
    {
        parsed = req.GetQueryNameValuePairs().ToDictionary(kv => kv.Key, kv=> kv.Value, StringComparer.OrdinalIgnoreCase);
    }

    xxx
}

and then you only have to specify request parameter name to be req, i think. if you want to go the route crowcoder proposed you just specify your path in settings (integrate tag):

enter image description here

As you can see I dont have a route defined and it just works. I suspect you dont need to define query parameters in your route.

4c74356b41
  • 69,186
  • 6
  • 100
  • 141
  • I was looking for a solution that would allow me to get the value as one of the Run's method parameters instead of poking at the HttpRequest instance. – Kzryzstof Feb 11 '19 at 23:36
  • not sure about that, but i dont think you can define query parameters, you can always do `products/{productId}` which makes a lot of sense, tbh – 4c74356b41 Feb 12 '19 at 05:42