Mastronardi.Utils.Azure.Functions 1.2.20

Prefix Reserved
dotnet add package Mastronardi.Utils.Azure.Functions --version 1.2.20                
NuGet\Install-Package Mastronardi.Utils.Azure.Functions -Version 1.2.20                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Mastronardi.Utils.Azure.Functions" Version="1.2.20" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Mastronardi.Utils.Azure.Functions --version 1.2.20                
#r "nuget: Mastronardi.Utils.Azure.Functions, 1.2.20"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Mastronardi.Utils.Azure.Functions as a Cake Addin
#addin nuget:?package=Mastronardi.Utils.Azure.Functions&version=1.2.20

// Install Mastronardi.Utils.Azure.Functions as a Cake Tool
#tool nuget:?package=Mastronardi.Utils.Azure.Functions&version=1.2.20                

Azure functions Utilities

Bindings

In Mvc we can use FromBody and FromQuery in our controllers but in Azure Functions we lack this functionality. Hence there are these bindings you can use to enable it for Azure Functions.

In addition it also provides Data Annotation validation out ouf the box.

It uses the Utf8Json serializer and MessageBack by nuecc.

How to enable:

in Startup.cs add this on top

using Mastronardi.Utils

Then add this to enable these bindings

builder.AddFunctionRequestBindings();

How to use:

You cannot use the normal FromBody and FromQuery attribute, instead you must use the one from this utility library. Mastronardi.Utils.Azure.Functions.Bindings.FromBody and Mastronardi.Utils.Azure.Functions.Bindings.FromQuery You can do it like this:

public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log,
    [Mastronardi.Utils.Azure.Functions.Bindings.FromBody] CustomObject dataBody)
    {
    ...
    }

It will serialize what it can to your CustomObject and you can just access the properties directly in your function. It will fail if its not a correctly formatted request, but missing parameters will just be empty or default. The other option is to do it like this:

public async Task<IActionResult> Run(
    [HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)] HttpRequest req,
    ILogger log,
    [Mastronardi.Utils.Azure.Functions.Bindings.FromBody(false)] IValidated<CustomObject> dataBody)
    {
    ...
    }

It will validate your object and you can use .IsValid and .IsEmpty to check if it is valid or empty. You can also request the validation errors in the .ValidationResults property. In the example the recursive validation is disabled on the attribute. This is usefull if you don't want to validate subobjects.

The same can be done by replacing FromBody with FromQuery and it will fill your object from the QueryString. It also supports validation, so you can make certain querystring parameters mandatory easily. Just display the errors in case its not valid and you're good.

This binding is very performant due to its use of Utf8Json (and also for MessagePack) and that many optimizations have been done to do the validation, instantiating, etc.

Healthchecks

When you do this in your startup: serviceCollection.AddFunctionHealthChecks().Add....( (use using Mastronardi.Utils;) you can use healthcheck in your function app.

You can use the pre-existing health checks just like you are used to do.

If you make a function like this:

using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Extensions.Diagnostics.HealthChecks;
using Microsoft.Extensions.Logging;

namespace MyApp.Functions {

    public  class HealthCheckFunctions{

        private readonly HealthCheckService _healthCheckService;

        public HealthCheckFunctions(HealthCheckService healthCheckService)
        {
            _healthCheckService = healthCheckService;
        }

        [FunctionName(nameof(HeartBeat))]
        public  async Task<IActionResult> HeartBeat(
            [HttpTrigger(AuthorizationLevel.Anonymous, "get", Route = "healthcheck")] 
            HttpRequest req,
            ILogger log)
        {
            var report = await _healthCheckService.CheckHealthAsync();

            if (report.Status == HealthStatus.Unhealthy) return new BadRequestObjectResult(report);

            return new OkObjectResult(report);
        }
    }
}

You can poll this endpoint to see the health status.

Generic extensions

By using HttpRequestMessage.SetCultureInfo() you can easily set the Culture of the current request to the correct one as specified in the Accept-Language header... this allows you to make your functions language aware. You still have to do something with the culture info ofcourse... it may change your text responses etc, if you do something with it.

Multipart Form File Stream

You can instantiate the Multipart Provider like this:

var provider = new MultipartFormDataIFileSystemStreamProvider(fileSystem, blobPath);

where fileSystem is of type Mastronardi.Utils.IO.IFilesystem and blobPath is the path where to save your files

You can then detect multipart and upload the file like this:

if (req.Content.IsMimeMultipartContent("form-data"))
{
    // When multipart, files are streamed to storage
    var result = await req.Content.ReadAsMultipartAsync(provider);

    ...
}

result.FileData contains the uploaded file meta information

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 was computed.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp3.1 is compatible. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last updated
1.2.20 175 8/28/2023
1.2.16 256 10/10/2022