How to use System.Runtime.Caching in an Azure Function App - azure

I want to use simple in-memory caching of some values between function calls in a serverless function in an Azure Function App. I am developing directly in the Azure portal using C# script files. Following the suggestion 2) from this blog post by Mark Heath I have the following lines in my function's csx file:
#r "System.Runtime.Caching"
using System.Runtime.Caching;
using System;
static MemoryCache memoryCache = MemoryCache.Default;
//.....
This should be the System.Runtime.Caching assembly from this doc.
But on complilation (save in Azure Portal), I get:
2021-01-05T07:25:39.687 [Information] Script for function 'Intake' changed. Reloading.
2021-01-05T07:25:39.807 [Error] run.csx(1,1): error CS0006: Metadata file 'System.Runtime.Caching' could not be found
2021-01-05T07:25:39.865 [Error] run.csx(2,22): error CS0234: The type or namespace name 'Caching' does not exist in the namespace 'System.Runtime' (are you missing an assembly reference?)
2021-01-05T07:25:39.938 [Error] run.csx(4,8): error CS0246: The type or namespace name 'MemoryCache' could not be found (are you missing a using directive or an assembly reference?)
2021-01-05T07:25:40.008 [Error] run.csx(4,34): error CS0103: The name 'MemoryCache' does not exist in the current context
2021-01-05T07:25:40.041 [Information] Compilation failed.
This is my host.json, for reference:
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[1.*, 2.0.0)"
}
}
Do I need to add something here? I would have expected, adding a #r reference to the assembly would be sufficient.

Upon inspecting the documentation, apart from the well-known assemblies mentioned in the document which can be referenced with #r, other nuget packages, may have to be uploaded by using a .proj file I suspect.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp#using-nuget-packages
I crafted a function.proj file with its contents as follows
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Runtime.Caching" Version="5.0.0" />
</ItemGroup>
Then I uploaded function.proj using App Service Editor in the portal
Once that was complete, I was able to compile csx successfully

Related

Error in Azure Function App VS 2019 .NET 3.0 - Method not found: 'IFunctionsHostBuilder.get_Services()'

Issue with Azure Functions/EFSQLSERVER .NET CORE 3.0:
To reproduce:
Use Visual Studio 2019 16.2.1
Use Azure Function template to create a project.
Changed Target Framework to .NET Core 3.0
Add Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0"
reference via Nuget Package Manager.
Excecut Function App using F5
Results in an error as showing in the following snippets. Anyone came across this issue?
Azure Functions Core Tools (2.7.1633 Commit hash: 45c7d86a3bbc9ed0a80a8f4199aa7ea80ccfb24e)
Function Runtime Version: 2.0.12673.0
[10/4/2019 6:13:14 PM] Building host: startup suppressed:False, configuration suppressed: False
[10/4/2019 6:13:14 PM] Loading startup extension 'Startup'
[10/4/2019 6:13:14 PM] Loaded extension 'Startup' (1.0.0.0)
[10/4/2019 6:13:14 PM] Loading startup extension 'DurableTask'
[10/4/2019 6:13:14 PM] Loaded extension 'DurableTask' (1.0.0.0)
[10/4/2019 6:13:14 PM] A host error has occurred
[10/4/2019 6:13:14 PM] FunctionApp5: Method not found: 'Microsoft.Extensions.DependencyInjection.IServiceCollection Microsoft.Azure.Functions.Extensions.DependencyInjection.IFunctionsHostBuilder.get_Services()'.
Value cannot be null.
Parameter name: provider
My nuget packages from csproj file.
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.0.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.DurableTask" Version="1.8.2" />
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="3.0.0" />
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="1.0.29" />
</ItemGroup>
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(FunctionApp5.Startup))]
namespace FunctionApp5
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
**var x = builder.Services;**
}
}
}
For now,ASP.NET Core 3.0 not currently available for Azure App Service, check this Microsoft doc.
Azure Functions 3.0, which will be fully compatible with Core 3.0, will be available in October, check here. However it's not released now.
From this issue, you could find Azure Function 2.0 right now does not work with any Microsoft.Extensions.* 3.* packages and cannot share code with .Net Core 3.0 services.
Further more information about Azure Fuction 3.0 check this discussion.
You can now use .net core 3.0 to create azure functions. Update Microsoft.NET.Sdk.Functions to 1.0.30-beta2 and set AzureFunctionsVersion to v3-preview.
Read more about Develop Azure Functions using .NET Core 3.0 here
You can now use DI using IFunctionsHostBuilder
using Microsoft.Azure.Functions.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection;
[assembly: FunctionsStartup(typeof(BI_Geo.AzureFunctions.Startup))]
namespace BI_Geo.AzureFunctions
{
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddScoped<IProcess, Process>();
}
}
}
This saved my day
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<AzureFunctionsVersion>v3</AzureFunctionsVersion>
</PropertyGroup>
To add something else to look out for, the following was our issue:
Our functions app referenced a Domain project
Our Domain project referenced "Microsoft.Extensions.Localization version 5.0.1, which in turn referenced a 5.x version of Microsoft.Extensions.DependencyInjection, which was incompatible with our 3.x runtime. Once we downgraded to reference Microsoft.Extensions.Localization version 3.1.10, the Microsoft.Extensions.DependencyInjection reference downgraded with it and everything worked.
Until Azure Functions 3.0 is available as a stable release, the easiest seems to be to downgrade the Microsoft.Extensions.Http package to 2.2.0:
It helped me with the same problem as there seems to be no other workaround in place for now. Even the available beta packages aren't working on a build server.
More details here: Azure functions dependency injection - error when referencing class library (Github).

Cannot run PowerShell scripts in Azure Functions v2

I'm trying to write a Function App using .NET Core in Azure Functions v2. When using the Microsoft.Powershell.SDK package from Nuget (required for .NET Core PowerShell runtime) I cannot get Visual Studio to copy the System.Management.Automation library to the bin with my Function App.
This results in the following error:
System.Private.CoreLib: Exception while executing function: Function1. TestPowershellInFunction: Could not load file or assembly 'System.Management.Automation, Version=6.1.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35'. The system cannot find the file specified. System.Private.CoreLib: Could not load the specified file.
I've reproduced this in an existing Azure Function and a new Solution by simply creating a Timer function and adding the following snippet:
PowerShell shell = PowerShell.Create();
IEnumerable<PSObject> result = shell.AddScript("Write-Output 'Hello, World!'").Invoke();
foreach(PSObject line in result)
{
log.LogInformation(line.ToString());
}
This works on a new Console App with the PowerShell Nuget installed, but when added to the Function App I get the error. I do notice that System.Management.Automation doesn't get put in the bin directory with a regular Console App but I'm not sure how to interpret this. I know it's a System library but I can't use it unless the Nuget is installed, so I don't know if this is a special case. In both scenarios I'm using v6.1.1 of the PowerShell Nuget.
Is this a known bug with Functions v2? Or am I missing something?
It's a known issue that Function can't load runtime assemblies([FunctionProject]\bin\Debug\netcoreapp2.1\bin\runtimes) correctly.
The workaround is to move assemblies to output dir bin manually. Right click on your function project and Edit <FunctionProject>.csproj. Add following items to achieve our goal.
<PropertyGroup>
<SDKVersion>6.1.1</SDKVersion>
<SDKPlatform>win-x86</SDKPlatform>
</PropertyGroup>
<ItemGroup>
<None Include="
$(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
$(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
$(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
$(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Target Name="CopyRuntimeToBin" AfterTargets="Build">
<Copy SourceFiles="
$(USERPROFILE)\.nuget\packages\system.directoryservices\4.5.0\runtimes\win\lib\netcoreapp2.0\System.DirectoryServices.dll;
$(USERPROFILE)\.nuget\packages\system.management\4.5.0\runtimes\win\lib\netcoreapp2.0\System.Management.dll;
$(USERPROFILE)\.nuget\packages\system.management.automation\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\System.Management.Automation.dll;
$(USERPROFILE)\.nuget\packages\microsoft.management.infrastructure\1.0.0\runtimes\win10-x86\lib\netstandard1.6\Microsoft.Management.Infrastructure.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Management.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.utility\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Utility.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.commands.diagnostics\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Commands.Diagnostics.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.sdk\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.SDK.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.security\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.Security.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.coreclr.eventing\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.CoreCLR.Eventing.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.consolehost\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.ConsoleHost.dll;
$(USERPROFILE)\.nuget\packages\microsoft.powershell.markdownrender\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.PowerShell.MarkdownRender.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.runtime\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Runtime.dll;
$(USERPROFILE)\.nuget\packages\microsoft.wsman.management\$(SDKVersion)\runtimes\$(SDKPlatform)\lib\netstandard2.0\Microsoft.WSMan.Management.dll;
" DestinationFolder="$(OutputPath)\bin" />
</Target>
Note that microsoft.management.infrastructure is set to win10-x86 on my side(Win10), you may need to change according to your pc platform. Assemblies are x86 as VS uses x86 Function CLi by default, we don't need to worry about it unless we need to work with x64.

WebJobsStartup in Azure Functions v2 not working when targeting netcoreapp2.1

I have an Azure Function v2 app, that I originally targeted netcoreapp2.1.
I then have a Startup.cs class, annotated with [assembly: WebJobsStartup(typeof(Startup))] to set up dependency injection, but it did not register Startup in the extensions.json file.
This is happening during build. Publish has another issue at the moment.
When I change the TargetFramework in the project file to netstandard2.0 it successfully adds Startup to extensions.json:
{
"extensions":[
{ "name": "AzureStorage", "typeName":"Microsoft.Azure.WebJobs.Extensions.Storage.AzureStorageWebJobsStartup, Microsoft.Azure.WebJobs.Extensions.Storage, Version=3.0.1.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35"},
{ "name": "Startup", "typeName":"MyApp.Functions.Startup, MyApp.Functions, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"}
]
}
While I do not have exact reasons to target netcoreapp2.1, I am curious to figure out why it doesn't work, as v2 was changed to target .Net Core by default.
I have upgraded the Microsoft.NET.SDK.Functions to version 1.0.26 from manage nuget packages and it worked.
This looks fixed now just upgrade Microsoft.NET.SDK.Functions to version 1.0.25 +
In my case, I had simply missed to explicitly set host.json to be copied. Adding these rows to the csproj file did the works:
<ItemGroup>
<None Update="host.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>

Azure function error: Could not load file or assembly 'Microsoft.Xrm.Sdk, Version=7.0.0.0'?

I m doing a azure function and testing it locally where it will add some data to Dyanmcis CRM. When I run function it throw this error:
Could not load file or assembly 'Microsoft.Xrm.Sdk, Version=7.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
Please note my code uses Microsoft.Xrm.Client(version 7) and it has Microsoft.Xrm.Sdk (version 8.1.0.235).
Please help.
The problem is due to the missing assembly redirect. You can see exactly which assembly redirect is needed by adding the Microsoft.CrmSdk.CoreAssemblies NuGet package to a normal .Net project and looking at the generated binding redirect statements added to app.config.
Currently Azure Functions do not support setting assembly redirects, so it has to be done in code. I solved this problem by using the code from this blog post: How to fix the assembly binding redirect problem in Azure Functions
With that code, local.settings.json looks like this:
"Values": {
"AzureWebJobsStorage": "",
"AzureWebJobsDashboard": "",
"BindingRedirects": "[ { \"ShortName\": \"Microsoft.Xrm.Sdk\", \"RedirectToVersion\": \"8.0.0.0\", \"PublicKeyToken\": \"31bf3856ad364e35\" } ]"
}
and in Application settings in the Azure portal:
[ { "ShortName": "Microsoft.Xrm.Sdk", "RedirectToVersion": "8.0.0.0", "PublicKeyToken": "31bf3856ad364e35" } ]

Error using Box SDK on Azure Functions

I am getting a "Could not load file or assembly 'Box.V2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ddda8fe64dde1ac3' or one of its dependencies. The system cannot find the file specified" error in Azure Functions. Any ideas on what the problem might be?
I am using the package.json file to have Azure Functions pull in the references and hook them all up as described in the docs.
When you upload a project.json file, the runtime gets the packages and automatically adds references to the package assemblies. You don't need to add #r "AssemblyName" directives. Just add the required using statements to your run.csx file to use the types defined in the NuGet packages.
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp
My package.json file:
{
"frameworks": {
"net46":{
"dependencies": {
"BouncyCastle": "1.8.1",
"BouncyCastle-PCL": "1.0.0.6",
"Box.V2": "2.14.0",
"Box.V2.JWTAuth": "1.2.0",
"Microsoft.Bcl": "1.1.10",
"Microsoft.Bcl.Async": "1.0.168",
"Microsoft.Bcl.Build": "1.0.14",
"Microsoft.Net.Http": "2.2.29",
"Newtonsoft.Json": "6.0.2",
"Nito.AsyncEx": "2.1.3",
"System.IdentityModel.Tokens.Jwt": "4.0.2.206221351"
}
}
}
}
run.csx using statements:
using global::Box.V2;
using global::Box.V2.Config;
using global::Box.V2.Exceptions;
using global::Box.V2.JWTAuth;
using global::Box.V2.Models;
Full Exception:
Microsoft.Azure.WebJobs.Host.FunctionInvocationException : Exception while executing function: Functions.GetTelogisFormInstancePdf ---> System.Reflection.TargetInvocationException : Exception has been thrown by the target of an invocation. ---> System.IO.FileNotFoundException : Could not load file or assembly 'Box.V2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ddda8fe64dde1ac3' or one of its dependencies. The system cannot find the file specified.
at Submission#0.Run(HttpRequestMessage req,TraceWriter log) at : 84
End of inner exception
at System.RuntimeMethodHandle.InvokeMethod(Object target,Object[] arguments,Signature sig,Boolean constructor)
at System.Reflection.RuntimeMethodInfo.UnsafeInvokeInternal(Object obj,Object[] parameters,Object[] arguments)
at System.Reflection.RuntimeMethodInfo.Invoke(Object obj,BindingFlags invokeAttr,Binder binder,Object[] parameters,CultureInfo culture)
at async Microsoft.Azure.WebJobs.Script.Description.DotNetFunctionInvoker.InvokeCore(Object[] parameters,FunctionInvocationContext context)
at async Microsoft.Azure.WebJobs.Script.Description.FunctionInvokerBase.Invoke(Object[] parameters)
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionInvoker`1.InvokeAsync[TReflected](Object[] arguments)
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.InvokeAsync(IFunctionInvoker invoker,Object[] invokeParameters,CancellationTokenSource timeoutTokenSource,CancellationTokenSource functionCancellationTokenSource,Boolean throwOnTimeout,TimeSpan timerInterval,IFunctionInstance instance)
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithWatchersAsync(IFunctionInstance instance,IReadOnlyDictionary`2 parameters,TraceWriter traceWriter,CancellationTokenSource functionCancellationTokenSource)
at async Microsoft.Azure.WebJobs.Host.Executors.FunctionExecutor.ExecuteWithLoggingAsync(??…
The error is clearly stating that it can't find the assembly:
System.IO.FileNotFoundException : Could not load file or assembly 'Box.V2, Version=1.0.0.0, Culture=neutral, PublicKeyToken=ddda8fe64dde1ac3' or one of its dependencies. The system cannot find the file specified.
And while you show in your .csx that you have using statements to include the namespaces, no where do you show that you actually reference the external assemblies
As described in the above linked documentation:
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").
Make sure you get the path correct; I had to ensure the bin folder was within my path where the function was - the shared assembly approach didn't work for me.
I also suggest that perhaps an easier approach than dealing with csx and referencing assemblies is to ditch csx all together and use pre compiled functions as described in this blog post. Then you get full compile time resolution of assemblies and proper intellisense that you just don't get with the CSX files.
This error is misleading and I had to end up overriding BoxJWTAuth in order to make it work. The details of this error can be found here: https://github.com/box/box-windows-sdk-v2/issues/297

Resources