How to get Azure Functions's framework generated request id? - c#

Every time i am debugging my Azure Functions (locally) then invoking a function, the CLI (func.exe) always shows requestId as one of the incoming request's parameters which i am highly sure it is not from my side that generate it.
My question is, is it possible to extract the value of requestId value from our code and how ? is this feature only specific for development/local debugging only ? since i can't find any documentation, article nor blog regarding this.
thank you

I believe you will find the request information in the HttpContext
req.HttpContext.Items["MS_AzureFunctionsRequestID"]
c# code example assuming you have the following signature
public static async Task<IActionResult> Run([HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = null)] HttpRequest req, ILogger log) {}

Related

The host has not yet started on startup of HttpTrigger using OpenAPI

I have an Azure Function App ver4 (net6) with HttpTrigger using OpenAPI and it raises exception 'The host has not yet started'.
Does the following error let me know to remove the character '/' that precedes my Route string value /blog/{blogId}/post/{postId}:
A host error has occurred during startup operation '2397a6d1-fa1c-4895-b062-f7e4faf57970'.
[2022-12-31T08:12:29.716Z] Microsoft.AspNetCore.Routing: An error occurred while creating the route with name 'GetBlogPost' and template 'api//blog/{blogId}/post/{postId}'. Microsoft.AspNetCore.Routing: The route template separator character '/' cannot appear consecutively. It must be separated by either a parameter or a literal value. (Parameter 'routeTemplate'). Microsoft.AspNetCore.Routing: The route template separator character '/' cannot appear consecutively. It must be separated by either a parameter or a literal value.
Yes / No ?
Thanks!
I tried to reproduce this scenario in my environment and was able to resolve the error:-
The route template separator character ‘/’ cannot appear consecutively. It must be separated by either a parameter or a literal value
Yes / No ?
Yes,
When I tried to remove the appending first “/” in my azure function Open API Http trigger route
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "blog/{blogId}/post/{postId}")] HttpRequest req)
My function app ran successfully like below :-
And when I tried to append the “/” before blog in the
route> I was able to get the same error code as yours while running the function app :-
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "/blog/{blogId}/post/{postId}")] HttpRequest req)
Error :-
Kindly, Remove the appending “/” while routing your api with the function app.
Reference :-
Azure Function app down due to wrong routing template in http
trigger binding of a functions - Stack
Overflow
c# - The route template separator character ‘/’ cannot appear
consecutively - Attribute routing issue - Stack
Overflow
I resolved this by removing the preceding / in the Route parameter value string. Therefore, this
/blog/{blogId}/post/{postId}
change to
blog/{blogId}/post/{postId}

Azure Function With Parameter Name Containing Hyphen In Route

I have the following function in an Azure Functions application:
[FunctionName("MyFunction")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "x/{my-guid}/y")] HttpRequest httpRequest,
Guid myGuid,
ILogger logger
)
The problem is that I can't use the string "my-guid" as a parameter name because it contains a hyphen, and when I use "myGuid" instead I get a "cannot bind parameter" error message.
Is there a way to do this, perhaps by somehow explicitly stating the mapping from "my-guid" to "myGuid"?
I have tried using attributes such as [FromRoute(Name = "my-guid")] to decorate the myGuid parameter, but this didn't work.
So you have basically two issues:
Dashes in route
The first one is "mapping" my-guid to myGuid which I am unfortunately not being able to help with - I can not recall anything that could achieve that, besides "hiding" your functions behind some sort of API Gateway (like API Management).
Parameter binding
The second one though is your "cannot bind parameter" error, which I assume you would get even if the first issue would be resolved. Apparently functions are unable cast parameter to Guid type, change it to string and then convert to Guid inside the body of your function method:
[FunctionName("MyFunction")]
public async Task<IActionResult> Run(
[HttpTrigger(AuthorizationLevel.Anonymous, "post", Route = "x/{myGuid}/y")]
HttpRequest httpRequest,
string myGuid,
ILogger logger
)
{
if (Guid.TryParse(myGuid, out var guid))
{
return new OkObjectResult(guid.ToString());
}
return new BadRequestResult();
}
Side note:
It's a bit painful with this additional logic, but I think it might be simplified with use of Azure Functions in isolated process rather than in-process and benefiting from middleware that handles that logic. It would make it a bit more future-proof as well:
Source of the image

Add Custom Properties for RequestTelemetry of the Azure Function (v3) binding to BlobTrigger

I want to add Custom Properties to the RequestTelemetry generated for the Azure function(V3) written in C#.
Thanks to this StackOverflow post, I managed to achieve this for the function with HttpTrigger binding.
var requestTelemetry = req.HttpContext?.Features.Get<RequestTelemetry>();
requestTelemetry.Properties.Add("MyProp", "Some value");
However, when I try to do same thing for another function with BlobTrigger binding, it became confusing. The first challenge is:
How to get current RequestTelemetry in a function that is using
BlobTrigger binding?
In a function with HttpTrigger binding, the function is injected with HttpRequest parameter
public async Task<IActionResult> Upload(
[HttpTrigger(AuthorizationLevel.Anonymous, "get", "post", Route = "upload/{name}")] HttpRequest req,
string name,
ILogger log,
ExecutionContext context)
{
...
}
So we can get current RequestTelemetry using HttpRequest. However, what about a function with BlobTrigger:
[FunctionName("Create-Thumbnail")]
public async Task CreateThumbnail([BlobTrigger("input/{name}", Source = BlobTriggerSource.EventGrid, Connection = "AzureWebJobsStorage")] Stream image,
IDictionary<string,string> metadata,
string name,
ExecutionContext context)
{
...
}
I have tried injecting HttpRequest and using same way as HttpTrigger function. But it didn't work.
After hours extensive research, I couldn't find any documentation or posts that are related to this question.
Can anyone provide some tips for this?
AFAIK there is no http request when using a blob trigger. You can still add custom properties to the telemetry generated during the execution by setting properties like this:
// The current telemetry item gets a property.
// Useful if the function is not triggered by an http request
Activity.Current.AddTag("setUsingTag", "setUsingTag");
// Subsequent telemetry gets this property attached
Activity.Current.AddBaggage("setUsingActivityBaggage", "setUsingActivityBaggage");
When using Baggage instead of a Tag the custom property is added to all telemetry generated during the execution, like dependency calls etc.
See also this github thread. It also mentions there might be a bug introduced in a later version of AI that might force you to downgrade AI for this to work.
Thanks to this GitHub issue, this is finally working after downgrading System.Diagnostics.DiagnosticSource to version 4.6
<PackageReference Include="System.Diagnostics.DiagnosticSource" Version="4.6.0" />

c# webapi - The requested resource does not support http method 'GET'

I have two simple routing methods:
main routing directive:
[RoutePrefix("api/accounts")]
first one
[Route("user/{id:guid}", Name = "GetUserById")]
public async Task<IHttpActionResult> GetUser(string Id)
second one
[Route("user/del/{id:guid}")]
public async Task<IHttpActionResult> DeleteUser(string id)
I wonder why if I test the first method with direct ulr ( GET ) it works:
http://localhost/ReportApp_WebApi/api/accounts/user/1533882b-e1fd-4b52-aeed-4799edbbcda6
And if I try the second link that is just a little different:
http://localhost/ReportApp_WebApi/api/accounts/user/del/1533882b-e1fd-4b52-aeed-4799edbbcda6
I get: The requested resource does not support http method 'GET'.
Can you help me?
The second link is not just a little different. In fact it is pointing to the route that you have defined for your delete method. This method expects DELETE Http verb.
When you write the url directly on the browser it performs a GET request. If you want your delete method to work with a GET verb you have to put the attribte
[HttpGet]
before or just after your Route atttribute. Although this I would not recommend to do it. You can have a HTTP client like Fiddler or Postman to test this
Web Api uses conventions when naming methods in your controllers. Because you named your method DeleteUser, Web Api expects Delete verb.
EDIT>>>Please follow recommendations listed in comments. I have also make bold the part where I do not recommend this

Why do POST requests map to this Web API action method?

I've been following along with a tutorial here to get my head around authentication in Web API with OAuth.
I have worked on Web API before, where I named the methods to start with Get, Put, Post etc. in order that they were routed to depending on the http verb. I also know that actions can be decorated with attributes ([HttpGet] etc) to denote the verb that maps to them.
In the tutorial, there is an action on a controller that looks like this:
// POST api/Account/Register
[AllowAnonymous]
[Route("Register")]
public async Task<IHttpActionResult> Register(UserModel userModel)
{
if (!ModelState.IsValid)
return BadRequest(ModelState);
IdentityResult result = await _repo.RegisterUser(userModel);
IHttpActionResult errorResult = GetErrorResult(result);
if(errorResult != null)
return errorResult;
return Ok();
}
This method, as the comment suggests, responds to POST requests. I cannot see how the Web API knows that this action is for POST. Can anyone enlighten me?
If you look at the documentation for Web API Routing and Action Selection:
...
HTTP Methods. The framework only chooses actions that match the HTTP method of the request, determined as follows:
You can specify the HTTP method with an attribute: AcceptVerbs, HttpDelete, HttpGet, HttpHead, HttpOptions, HttpPatch, HttpPost, or HttpPut.
Otherwise, if the name of the controller method starts with "Get", "Post", "Put", "Delete", "Head", "Options", or "Patch", then by convention the action supports that HTTP method.
If none of the above, the method supports POST.
...
and the source for ReflectedHttpActionDescriptor.cs (line number 294-300):
...
if (supportedHttpMethods.Count == 0)
{
// Use POST as the default HttpMethod
supportedHttpMethods.Add(HttpMethod.Post);
}
return supportedHttpMethods;
...
You'll find your answer:
POST is the default HTTP Verb for action method in Web API.
Also, if you search a bit more on SO, You'll find the following question:
Is there a default verb applied to a Web API ApiController method?
Although it's a different question, but the problem is basically the same as yours.

Categories

Resources