Referencia para desarrolladores de F# de Azure FunctionsAzure Functions F# Developer Reference

F# para Azure Functions es una solución para ejecutar fácilmente pequeños fragmentos de código, o "funciones", en la nube.F# for Azure Functions is a solution for easily running small pieces of code, or "functions," in the cloud. Los datos fluyen en la función de F# a través de los argumentos de función.Data flows into your F# function via function arguments. Los nombres de los argumentos se especifican en function.json, y hay nombres predefinidos para acceder a cosas como el registrador de funciones y los tokens de cancelación.Argument names are specified in function.json, and there are predefined names for accessing things like the function logger and cancellation tokens.

Importante

El script de F# (.fsx) solo es compatible con la versión 1.x del tiempo de ejecución de Azure Functions.F# script (.fsx) is only supported by version 1.x of the Azure Functions runtime. Si desea usar F# con el tiempo de ejecución de la versión 2.x, debe usar un proyecto de la biblioteca de clases (.fs) de F# precompilado.If you want to use F# with the version 2.x runtime, you must use a precompiled F# class library project (.fs). Cree, administre y publique un proyecto de la biblioteca de clases de F# con Visual Studio como lo haría con un proyecto de la biblioteca de clases de C#.You create, manage, and publish an F# class library project using Visual Studio as you would a C# class library project. Para más información sobre las versiones de Functions, vea Introducción a las versiones de tiempo de ejecución de Azure Functions.For more information about Functions versions, see Azure Functions runtime versions overview.

En este artículo se supone que ya ha leído Referencia para desarrolladores de Azure Functions.This article assumes that you've already read the Azure Functions developer reference.

Cómo funciona .fsxHow .fsx works

Un archivo .fsx es un script de F#.An .fsx file is an F# script. Se puede considerar como un proyecto de F# que se encuentra en un único archivo.It can be thought of as an F# project that's contained in a single file. El archivo contiene el código de programa (en este caso, Azure Function) y las directivas para la administración de dependencias.The file contains both the code for your program (in this case, your Azure Function) and directives for managing dependencies.

Cuando se usa un .fsx para Azure Function, normalmente se incluyen automáticamente los ensamblados necesarios, esto le permite a usted centrarse en la función en lugar de en códigos "reutilizables".When you use an .fsx for an Azure Function, commonly required assemblies are automatically included for you, allowing you to focus on the function rather than "boilerplate" code.

Estructura de carpetasFolder structure

La estructura de carpetas para un proyecto de script F# tiene el siguiente aspecto:The folder structure for an F# script project looks like the following:

FunctionsProject
 | - MyFirstFunction
 | | - run.fsx
 | | - function.json
 | | - function.proj
 | - MySecondFunction
 | | - run.fsx
 | | - function.json
 | | - function.proj
 | - host.json
 | - extensions.csproj
 | - bin

Hay un archivo host.json compartido que se puede usar para configurar la aplicación de función.There's a shared host.json file that can be used to configure the function app. Cada función tiene su propio archivo de código (.fsx) y archivo de configuración de enlace (function.json).Each function has its own code file (.fsx) and binding configuration file (function.json).

Las extensiones de enlace necesarias en la versión 2.x del tiempo de ejecución de Functions se definen en el archivo extensions.csproj, con los archivos de biblioteca de la carpeta bin.The binding extensions required in version 2.x of the Functions runtime are defined in the extensions.csproj file, with the actual library files in the bin folder. Al desarrollar de forma local, debe registrar las extensiones de enlace.When developing locally, you must register binding extensions. Al desarrollar funciones en Azure Portal, este registro se realiza automáticamente.When developing functions in the Azure portal, this registration is done for you.

Enlace a argumentosBinding to arguments

Cada enlace admite un conjunto de argumentos, como se detalla en Referencias para desarrolladores de desencadenadores y enlaces de Azure Functions.Each binding supports some set of arguments, as detailed in the Azure Functions triggers and bindings developer reference. Por ejemplo, uno de los enlaces de argumento que un desencadenador de blob admite es un POCO, que se puede expresar utilizando un registro de F#.For example, one of the argument bindings a blob trigger supports is a POCO, which can be expressed using an F# record. Por ejemplo:For example:

type Item = { Id: string }

let Run(blob: string, output: byref<Item>) =
    let item = { Id = "Some ID" }
    output <- item

La F# de Azure Functions tendrá uno o más argumentos.Your F# Azure Function will take one or more arguments. Al hablar de los argumentos de Azure Functions, se hace referencia a argumentos de entrada y argumentos de salida.When we talk about Azure Functions arguments, we refer to input arguments and output arguments. Un argumento de entrada es exactamente eso: una entrada a la F# de Azure Functions.An input argument is exactly what it sounds like: input to your F# Azure Function. Un argumento de salida es una serie de datos mutables o un argumento byref<> que sirve para volver a pasar datos de salida de la función.An output argument is mutable data or a byref<> argument that serves as a way to pass data back out of your function.

En el ejemplo anterior, blob es un argumento de entrada, y output es un argumento de salida.In the example above, blob is an input argument, and output is an output argument. Observe que hemos usado byref<> para output (no es necesario agregar la anotación [<Out>]).Notice that we used byref<> for output (there's no need to add the [<Out>] annotation). El uso de un tipo byref<> permite a la función cambiar el registro u objeto al que hace referencia el argumento.Using a byref<> type allows your function to change which record or object the argument refers to.

Cuando se utiliza un registro de F# como un tipo de entrada, la definición de registro tiene que marcarse con [<CLIMutable>] para permitir que el marco de Azure Functions establezca los campos de forma adecuada antes de pasar el registro a la función.When an F# record is used as an input type, the record definition must be marked with [<CLIMutable>] in order to allow the Azure Functions framework to set the fields appropriately before passing the record to your function. Internamente, [<CLIMutable>] genera métodos establecedores para las propiedades de registro.Under the hood, [<CLIMutable>] generates setters for the record properties. Por ejemplo:For example:

[<CLIMutable>]
type TestObject =
    { SenderName : string
      Greeting : string }

let Run(req: TestObject, log: ILogger) =
    { req with Greeting = sprintf "Hello, %s" req.SenderName }

También puede utilizarse una clase F# tanto para argumentos de entrada como de salida.An F# class can also be used for both in and out arguments. Para una clase, las propiedades normalmente necesitan captadores y establecedores.For a class, properties will usually need getters and setters. Por ejemplo:For example:

type Item() =
    member val Id = "" with get,set
    member val Text = "" with get,set

let Run(input: string, item: byref<Item>) =
    let result = Item(Id = input, Text = "Hello from F#!")
    item <- result

RegistroLogging

Para grabar la salida en los registros de streaming de F#, la función debe adoptar un argumento de tipo ILogger.To log output to your streaming logs in F#, your function should take an argument of type ILogger. Por coherencia, se recomienda que se le dé el nombre loga este argumento.For consistency, we recommend this argument is named log. Por ejemplo:For example:

let Run(blob: string, output: byref<string>, log: ILogger) =
    log.LogInformation(sprintf "F# Azure Function processed a blob: %s" blob)
    output <- input

AsyncAsync

Se puede usar el flujo de trabajo async, pero el resultado tiene que devolver una Task.The async workflow can be used, but the result needs to return a Task. Esto puede hacerse con Async.StartAsTask, por ejemplo:This can be done with Async.StartAsTask, for example:

let Run(req: HttpRequestMessage) =
    async {
        return new HttpResponseMessage(HttpStatusCode.OK)
    } |> Async.StartAsTask

Token de cancelaciónCancellation Token

Si la función tiene que controlar el apagado correctamente, puede darle un argumento CancellationToken .If your function needs to handle shutdown gracefully, you can give it a CancellationToken argument. Esto se puede combinar con async, por ejemplo:This can be combined with async, for example:

let Run(req: HttpRequestMessage, token: CancellationToken)
    let f = async {
        do! Async.Sleep(10)
        return new HttpResponseMessage(HttpStatusCode.OK)
    }
    Async.StartAsTask(f, token)

Importación de espacios de nombresImporting namespaces

Los espacios de nombres se pueden abrir en la manera habitual:Namespaces can be opened in the usual way:

open System.Net
open System.Threading.Tasks
open Microsoft.Extensions.Logging

let Run(req: HttpRequestMessage, log: ILogger) =
    ...

Los siguientes espacios de nombres se abren automáticamente:The following namespaces are automatically opened:

  • System
  • System.Collections.Generic
  • System.IO
  • System.Linq
  • System.Net.Http
  • System.Threading.Tasks
  • Microsoft.Azure.WebJobs
  • Microsoft.Azure.WebJobs.Host.Microsoft.Azure.WebJobs.Host.

Referencia a ensamblados externosReferencing External Assemblies

De forma similar, las referencias del ensamblado de Framework se pueden agregar con la directiva #r "AssemblyName".Similarly, framework assembly references can be added with the #r "AssemblyName" directive.

#r "System.Web.Http"

open System.Net
open System.Net.Http
open System.Threading.Tasks
open Microsoft.Extensions.Logging

let Run(req: HttpRequestMessage, log: ILogger) =
    ...

El entorno de hospedaje de Azure Functions agrega automáticamente los siguientes ensamblados:The following assemblies are automatically added by the Azure Functions hosting environment:

  • mscorlib,mscorlib,
  • System
  • System.Core
  • System.Xml
  • System.Net.Http
  • Microsoft.Azure.WebJobs
  • Microsoft.Azure.WebJobs.Host
  • Microsoft.Azure.WebJobs.Extensions
  • System.Web.Http
  • System.Net.Http.Formatting.System.Net.Http.Formatting.

Además, en los siguientes ensamblados se hace un uso especial de las mayúsculas y minúsculas y se puede hacer referencia a ellos con SimpleName (por ejemplo, #r "AssemblyName"):In addition, the following assemblies are special cased and may be referenced by simplename (e.g. #r "AssemblyName"):

  • Newtonsoft.Json
  • Microsoft.WindowsAzure.Storage
  • Microsoft.ServiceBus
  • Microsoft.AspNet.WebHooks.Receivers
  • Microsoft.AspNEt.WebHooks.Common.Microsoft.AspNEt.WebHooks.Common.

Si necesita hacer referencia a un ensamblado privado, puede cargar el archivo de ensamblado en una carpeta bin relacionada con la función y hacer referencia a él mediante el nombre de archivo (por ejemplo, #r "MyAssembly.dll").If you need to reference a private assembly, you can upload the assembly file into a bin folder relative to your function and reference it by using the file name (e.g. #r "MyAssembly.dll"). Para más información acerca de cómo cargar archivos en su carpeta de función, consulte la sección siguiente sobre administración de paquetes.For information on how to upload files to your function folder, see the following section on package management.

Preludio del editorEditor Prelude

Un editor que admita F# Compiler Services no será consciente de los espacios de nombres y ensamblados que Azure Functions incluye automáticamente.An editor that supports F# Compiler Services will not be aware of the namespaces and assemblies that Azure Functions automatically includes. Por lo tanto, puede resultar útil incluir un preludio que ayude al editor a encontrar los ensamblados que esté utilizando y a abrir explícitamente los espacios de nombre.As such, it can be useful to include a prelude that helps the editor find the assemblies you are using, and to explicitly open namespaces. Por ejemplo:For example:

#if !COMPILED
#I "../../bin/Binaries/WebJobs.Script.Host"
#r "Microsoft.Azure.WebJobs.Host.dll"
#endif

open System
open Microsoft.Azure.WebJobs.Host
open Microsoft.Extensions.Logging

let Run(blob: string, output: byref<string>, log: ILogger) =
    ...

Cuando Azure Functions ejecuta el código, procesa el origen con COMPILED definido, por lo que se omitirá el preludio del editor.When Azure Functions executes your code, it processes the source with COMPILED defined, so the editor prelude will be ignored.

Administración de paquetesPackage management

Para usar paquetes de NuGet en una función de F#, agregue un archivo project.json a la carpeta de la función en el sistema de archivos de la aplicación de función.To use NuGet packages in an F# function, add a project.json file to the function's folder in the function app's file system. Este es un ejemplo de archivo project.json que agrega una referencia de paquetes de NuGet a Microsoft.ProjectOxford.Face versión 1.1.0:Here is an example project.json file that adds a NuGet package reference to Microsoft.ProjectOxford.Face version 1.1.0:

{
  "frameworks": {
    "net46":{
      "dependencies": {
        "Microsoft.ProjectOxford.Face": "1.1.0"
      }
    }
   }
}

Solo se admite .NET Framework 4.6, así que asegúrese de que su archivo project.json especifique net46 como se muestra aquí.Only the .NET Framework 4.6 is supported, so make sure that your project.json file specifies net46 as shown here.

Al cargar un archivo project.json , el sistema en tiempo de ejecución obtiene los paquetes y agrega automáticamente las referencias a sus ensamblados.When you upload a project.json file, the runtime gets the packages and automatically adds references to the package assemblies. No es necesario agregar directivas #r "AssemblyName" .You don't need to add #r "AssemblyName" directives. Simplemente agregue las instrucciones open al archivo .fsx.Just add the required open statements to your .fsx file.

Puede que desee colocar automáticamente ensamblados de referencias en el preludio del editor, para mejorar la interacción de su editor con F# Compiler Services.You may wish to put automatically references assemblies in your editor prelude, to improve your editor's interaction with F# Compile Services.

Cómo agregar un archivo project.json a Azure FunctionsHow to add a project.json file to your Azure Function

  1. En primer lugar, asegúrese de que la aplicación de la función se está ejecutando, lo que puede hacer abriéndola en el Portal de Azure.Begin by making sure your function app is running, which you can do by opening your function in the Azure portal. Esto también proporciona acceso a los registros de streaming donde se mostrará la salida de la instalación del paquete.This also gives access to the streaming logs where package installation output will be displayed.
  2. Para cargar un archivo project.json , utilice uno de los métodos descritos en Actualización de los archivos de aplicación de función.To upload a project.json file, use one of the methods described in how to update function app files. Si se usa Implementación continua para Azure Functions, se puede agregar un archivo project.json a la rama de ensayo para experimentar con él antes de agregarlo a la rama de implementación.If you are using Continuous Deployment for Azure Functions, you can add a project.json file to your staging branch in order to experiment with it before adding it to your deployment branch.
  3. Una vez cargado el archivo project.json , verá un resultado similar al del ejemplo siguiente en el registro de streaming de la función:After the project.json file is added, you will see output similar to the following example in your function's streaming log:
2016-04-04T19:02:48.745 Restoring packages.
2016-04-04T19:02:48.745 Starting NuGet restore
2016-04-04T19:02:50.183 MSBuild auto-detection: using msbuild version '14.0' from 'D:\Program Files (x86)\MSBuild\14.0\bin'.
2016-04-04T19:02:50.261 Feeds used:
2016-04-04T19:02:50.261 C:\DWASFiles\Sites\facavalfunctest\LocalAppData\NuGet\Cache
2016-04-04T19:02:50.261 https://api.nuget.org/v3/index.json
2016-04-04T19:02:50.261
2016-04-04T19:02:50.511 Restoring packages for D:\home\site\wwwroot\HttpTriggerCSharp1\Project.json...
2016-04-04T19:02:52.800 Installing Newtonsoft.Json 6.0.8.
2016-04-04T19:02:52.800 Installing Microsoft.ProjectOxford.Face 1.1.0.
2016-04-04T19:02:57.095 All packages are compatible with .NETFramework,Version=v4.6.
2016-04-04T19:02:57.189
2016-04-04T19:02:57.189
2016-04-04T19:02:57.455 Packages restored.

Variables de entornoEnvironment variables

Para obtener una variable de entorno o un valor de configuración de aplicación, use System.Environment.GetEnvironmentVariable, por ejemplo:To get an environment variable or an app setting value, use System.Environment.GetEnvironmentVariable, for example:

open System.Environment
open Microsoft.Extensions.Logging

let Run(timer: TimerInfo, log: ILogger) =
    log.LogInformation("Storage = " + GetEnvironmentVariable("AzureWebJobsStorage"))
    log.LogInformation("Site = " + GetEnvironmentVariable("WEBSITE_SITE_NAME"))

Reutilización del código .fsxReusing .fsx code

Puede utilizar el código de otros archivos .fsx mediante una directiva #load.You can use code from other .fsx files by using a #load directive. Por ejemplo:For example:

run.fsx

#load "logger.fsx"

let Run(timer: TimerInfo, log: ILogger) =
    mylog log (sprintf "Timer: %s" DateTime.Now.ToString())

logger.fsx

let mylog(log: ILogger, text: string) =
    log.LogInformation(text);

Las rutas de acceso a la directiva #load son relativas a la ubicación del archivo .fsx.Paths provides to the #load directive are relative to the location of your .fsx file.

  • #load "logger.fsx" carga un archivo que se encuentra en la carpeta de la función.#load "logger.fsx" loads a file located in the function folder.
  • #load "package\logger.fsx" carga un archivo que se encuentra en la carpeta package dentro de la carpeta de la función.#load "package\logger.fsx" loads a file located in the package folder in the function folder.
  • #load "..\shared\mylogger.fsx" carga un archivo ubicado en la carpeta shared al mismo nivel que la carpeta de la función, es decir, directamente en wwwroot.#load "..\shared\mylogger.fsx" loads a file located in the shared folder at the same level as the function folder, that is, directly under wwwroot.

La directiva #load solo funciona con archivos .fsx (script de F#) y no con archivos .fs.The #load directive only works with .fsx (F# script) files, and not with .fs files.

Pasos siguientesNext steps

Para obtener más información, consulte los siguientes recursos:For more information, see the following resources: