Where to place the dependencies for shared assemblies in Azure Functions - azure

I am facing strange issues with privates assemblies in azure functions, I have an Azure Function App with five functions which have a shared bin folder where I place my assemblies, these assemblies in turn depend on Entity Framework and LinqKit for which I have added dependencies in all the project.json files for each function but private assemblies are unable to get reference to these and failing. Please help.
Project.json --
{
"frameworks": {
"net46":{
"dependencies": {
"EntityFramework": "6.1.3",
"Newtonsoft.Json": "9.0.1",
"LinqKit": "1.1.7.2"
}
}
}
}
To clarify further in my Function App I have five different functions which depend on 2 private assemblies and I do not want to keep separate copies (as this might cause different versions of the same dll in different folder causing issues) in each function so I have created a shared bin folder from where the private assemblies are referenced but the issue happens as these private assemblies further depend on some nuget packages which they are not able to find them --
#r "..\bin\Marketware.Domain.dll"
#r "..\bin\Marketware.AzureIntegration.dll"
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Diagnostics.Eventing.Reader;

If you want to use your private assembly (not from nuget) you have to do this:
Connect to Functions App ftp
Create bin folder in folder with your function (where is run.csx)
Upload your custom assembly to newly created bin folder
Update function code and add reference
Unfortunately this dll needs to be in each function folder where needed.
Example
#r "CustomAssembly.dll"
using System.Net;
using CustomAssembly;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
CustomAssemblyClass.MethodName(); // here call your method
return req.CreateResponse(HttpStatusCode.OK, "");
}

Will spend a bit of time trying to repro your scenario as, at a first glance, it should work as expected. In the meantime, a couple of options you have are:
1- When deploying your shared assemblies, copy all the binaries from your project output, including their dependencies. The shared assemblies folder will be in the probing logic and they would be resolved from there. This would also eliminate the need to have a project.json referencing the dependencies on each function.
2- Create a NuGet package for your shared assemblies and, on that package, specify your package dependencies (EF and LinqKit), publish that package to a private feed (which could be something like MyGet or even a folder in your function app). Your functions would only need to reference that package and not its dependencies, as those would be automatically resolved. You can find more information about using custom sources here: How do you use custom NuGet feeds with Azure Functions?
Although it may require a bit more work at first, both options have advantages over your original approach (including eliminating the need for the functions to be aware of indirect dependencies) and should be more reliable.
Hope this helps!

Related

References within an azure functions project not working

So I have some Azure Functions I need to publish, which I want to do via a functions project. However, those functions rely on references to class libraries within my solution, and the references do not work within a functions project, is there a way around this?
Edit: After adding the references to the other projects, when "using" the namespaces in which the classes are kept, the compiler throws an error "cannot resolve symbol", it is as if the reference does not exist. The functions project will not build because it cannot find the namespace in which the classes exist
Verify that each project targets the same version of .NET framework. I had the same problem until I noticed that the referenced project targeted 4.7.1, but my Azure function project targeted 4.6.1. Changing the referenced project to match the Azure function project resolved the issue.
There are a couple more steps to consume assemblies if they're not exposed by default in Azure Functions. If it's a custom assembly you have to make sure it's included in the bin folder. Then you have to make sure you're using the #r directive. Are you doing both of those things? Include your code header and settings if so.
This page has the list of assemblies that are visible to Azure Functions, some still requiring the #r directive:
https://learn.microsoft.com/en-us/azure/azure-functions/functions-reference-csharp#referencing-external-assemblies
The following assemblies are automatically added by the Azure Functions hosting environment:
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
The following assemblies may be referenced by simple-name (for
example, #r "AssemblyName"): Newtonsoft.Json
Microsoft.WindowsAzure.Storage Microsoft.ServiceBus
Microsoft.AspNet.WebHooks.Receivers Microsoft.AspNet.WebHooks.Common
Microsoft.Azure.NotificationHubs

Azure Functions: Can a shared .csx use a nuget package?

A .csx file inside an Azure Function can use a nuget package if it's listed in the function's project.json file. Ex:
{
"frameworks": {
"net46":{
"dependencies": {
"Microsoft.ProjectOxford.Face": "1.1.0"
}
}
}
}
But what happens with shared .csx files that are placed under the Function App's root (i.e. not in a specific function)? Is there a way to introduce a nuget package at the App Function (root) level?
I've found a workaround in uploading the nuget package's dll to a shared bin folder as explained in the Azure Functions C# developer reference:
Shared assemblies are shared across all functions within a function app. To reference a custom assembly, upload the assembly to your function app, such as in a bin folder in the function app root.
Is there a way to do this better so my code depends on the nuget package and not on a dll?
The actual package references are managed in each function (i.e. there's no function app level set of package references), but when brought into your function by using the #load directive, shared CSX files become part of the same compilation unit, and are able to consume assembly/package references defined in your function. But you still need to manage those at the function level.
You can think of the #load behavior as a linked file in a regular C# project, where the file is brought in, but compiled within the context of the project. That applies to functions here.

Azure Functions dll version mismatch

We have an Azure function which references an external assembly via a private Nuget feed.
The problem we're having is that we have two different versions of Microsoft.Azure.WebJobs.dll - one which is a dependency of our nuget package and another which I'm assuming is being provided by the runtime.
error CS1503: Argument 2: cannot convert from 'Microsoft.Azure.WebJobs.ICollector<Microsoft.WindowsAzure.Storage.Table.ITableEntity> [D:\Program Files (x86)\SiteExtensions\Functions\1.0.10635\bin\Microsoft.Azure.WebJobs.dll]' to 'Microsoft.Azure.WebJobs.ICollector<Microsoft.WindowsAzure.Storage.Table.ITableEntity>
I found this question which says that binding redirects are not supported:
Azure Functions binding redirect
We could try to remove our dependency on that library, or we could match the version used by Azure Functions, but I think we're going to have the same problem with using Microsoft.WindowsAzure.Storage anyway.
Please advise!
You are correct that binding redirects are not supported. The runtime has its own dependencies on the WebJobs SDK and Storage libraries so objects passed into your functions will be from those versions. I recommend removing your dependencies on other versions and snapping to ours. Note that for these libraries, you don't have to add your own package reference, you can reference ours in your function code via:
#r "WindowsAzure.Storage"
You don't need to add explicit #r references for WebJobs SDK types (e.g. ICollector<T>) - the runtime adds that assembly implicitly. Of course this only applies for function code we're compiling for you, not code coming from your external packages.
In the future we might improve things in this area, but for now you'll be swimming up stream if you try to use conflicting versions.

Execute pre-compiled .NET code as Azure Function

How do I upload a pre-compiled .NET assembly(-ies) and execute my code as Azure Functions?
I'm looking for a way to run some complex domain logic, which is contained inside custom assemblies and is covered by unit tests etc.
What kind of limitations for this code are there? E.g. access remote data stores, networking etc.
Update: The below answer is still correct (still works), however there is now also first class support for precompiled functions. See the wiki page for more information on that.
The documentation (link here) describes how you can reference external libraries and Nuget packages from a C# Function using the #r syntax, e.g:
#r "System.Web.Http"
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
public static Task<HttpResponseMessage> Run(HttpRequestMessage req)
Additional details on this can be seen in this SO post.
You can also deploy custom executables and call them from your Azure Functions. For example, if you start from the Windows BAT template, you can use that to call out to an exe. Here's a sample of this in our repo, showing an image resize example. In this sample, we have a BAT script that is triggered whenever a new image is uploaded to a blob container, and the script calls out to a Resizer.exe tool to do the resize:
.\Resizer\Resizer.exe %original% %resized% 200
Regarding limitations, all Azure Functions code runs in the App Service sandbox whose limitations are described here.
To run a pre-compiled .NET assembly in an Azure Function, it's possible to upload a custom dll by FTP in the function root folder (within a bin folder) and then use #r to reference it from the azure function code.
Here is an example, a dll named "WorkOnImages.dll" is uploaded in an azure in azure function folder :
Then the dll is referenced in the azure function :
Here is the source blog post
Discouraged by the lack of Azure Function tooling support for VS2017, incompatibility with Azure SDK 3.0, I was about to throw in the towel for Functions and fallback to an approach using VS2017 and WebJobs SDK.
Then announced on March 16th, 2017, the easiest approach is documented here in an excellent blog post by Microsoft's Donna Malayeri.
It does everything I could want - true intellisense, debugging capabilities. It's been great and I wouldn't look back.

How can I include transformed dll to an Azure deployment

For my Worker role I run a custom task to modify the dll. However, when I use VS to publish the project to Azure the original binary is deployed and not the modified dll. Why is this happening? How to include the modified binary in the package from within VS
This is with sdk+tools v1.6
A possible workaround that I see, is to extract all the code/logic that requires assmebly modification in a separate class library project. Do the custom post-build modification on the class library.
In your worker add reference to that class library. If it also does not work when you add the reference as a project reference, then just copy the resulted modified assembly in a common external references folder for the solution, and add the reference from there (just browse to the final assembly).
I don't know the nature of your modification, but I think that if you cave all your "private" code in a separate class library it will be enough. As the worker implementation will just be calling a "Run()" or similar method of your class library, inside the Run() method of the RoleEntryPoint.

Resources