Missing dll error from Azure function when updating pipeline - azure

I have an Azure function which triggers when I copy a blob into a container. The function successfully copies the blob into a subfolder for processing but I then want to change the pipeline schedule to trigger the pipeline to run. However, when I try and change the pipeline schedule in code, I get the following error:
Could not load file or assembly 'Microsoft.Threading.Tasks, Version=1.0.12.0, Culture=neutral, ... or one of its dependencies. The system cannot find the file specified.
I've been through the list of nuget packages to remove those that aren't being used and ensure I'm using the latest versions. I've also commented out come of the unnecessary usings in my csx file but I'm still getting the error. If I comment out the pipeline update call, the error disappears and the function runs to the end.
My project.json file looks like this (not that I've included commented out packages to show what other packages I've tried previously):
{
"frameworks": {
"net46": {
"dependencies": {
////"Hyak.Common": "1.1.0",
"Microsoft.Azure.Common": "2.1.0",
"Microsoft.Azure.Common.Dependencies": "1.0.0",
"Microsoft.Azure.Management.DataFactories": "4.11.0",
////"Microsoft.Bcl": "1.1.10",
////"Microsoft.Bcl.Async": "1.0.168",
////"Microsoft.Bcl.Build": "1.0.21",
"Microsoft.IdentityModel.Clients.ActiveDirectory": "3.13.8"
////"Microsoft.Net.Http": "2.2.29"
}
}
}
}
Finally, in the csx file, my usings are as follows (again including commented out lines)
#r "System.Runtime"
#r "System.Threading.Tasks"
#r "Microsoft.WindowsAzure.Storage"
using System;
using System.Net;
using System.Threading.Tasks;
using System.Configuration;
//using Newtonsoft.Json;
using Microsoft.Azure;
//using Microsoft.Azure.Common;
using Microsoft.Azure.Management.DataFactories;
using Microsoft.Azure.Management.DataFactories.Models;
using Microsoft.IdentityModel.Clients.ActiveDirectory;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Blob;
The code to update the pipeline is as follows:
client.Pipelines.CreateOrUpdate(resourceGroupName, dataFactoryName, new PipelineCreateOrUpdateParameters()
{
Pipeline = pl.Pipeline
});
log.Info($"Pipeline rescheduled for {slice}");
If I run this as a console application/web app (which includes several references including Microsoft.Threading.Tasks), the pipeline update works correctly but the same code doesn't work from my Azure function.
Does anyone know what nuget packages/versions or references I might be missing?

It turns out this problem was caused by the project.lock.json file referencing an old version of .Net (i.e. 4.5, rather than 4.6). Updating it to 4.6 resolved the issue.
For completeness, the project.lock.json file now reads as follows:
{
"locked": false,
"version": 2,
"targets": {
".NETFramework,Version=v4.6": {}
},
"libraries": {},
"projectFileDependencyGroups": {
"": [],
".NETFramework,Version=v4.6": []
}
}

Related

Azure Function for Cosmos DB change feed feed won't run: No job functions found

I'm writing an Azure Function app that'll subscribe to a Cosmos DB change feed. When I use Visual Studio 2019 to run the app locally (F5), I get the following error on the CLI:
Azure Function Core Tools reports "No job functions found."
The entire code snippet is below:
using Microsoft.Azure.Functions.Worker;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
namespace ZZZ.ChangeFeedSubscriber
{
public static class ChangeFeedSubscriber
{
[FunctionName("ChangeFeedSubscriber")]
public static void Run([CosmosDBTrigger(
databaseName: "XXX",
collectionName: "YYY",
ConnectionStringSetting = "XXX",
LeaseCollectionName = "leases")] IReadOnlyList<Doc> docs, FunctionContext context)
{
var logger = context.GetLogger("ChangeFeedSubscriber");
if (docs != null && docs.Count > 0)
{
logger.LogInformation("Documents modified: " + docs.Count);
foreach (var doc in docs)
{
logger.LogInformation("ID: " + doc.id);
}
}
}
}
}
I tried to set "--verbose" on the application arguments to see log output but it threw an error.
Adding "--verbose" throws an error.
Result of adding "--verbose" to application arguments.
I also tried setting "start --verbose" but it threw an error, too.
Adding "start --verbose" also throws an error.
Result of adding "start --verbose" to application arguments.
I don't know what else I can check at this point. The application won't start up and I cannot see log output based on the searching I've done.
Any help would be appreciated. TIA!
Looks like you have mixed the in-proc and out-of-process model here, which caused the issue.
From the code, I am assuming you have an out of process (isolated worker) function app. But your second line is a using statement to import the Microsoft.Azure.WebJobs namespace. I also see you are using the FunctionName attribute which is coming from the Microsoft.Azure.WebJobs package.
For out of process function apps, you should not use the webjobs package. Instead, you should use the equivalent pacakge from Microsoft.Azure.Functions.Worker.Extensions
To fix, open your .csproj file and remove the Microsoft.Azure.WebJobs.Extensions.CosmosDB package. Add a new entry for Microsoft.Azure.Functions.Worker.Extensions.CosmosDB (the out of process worker version). You may do the same using nuget package manager UI as well.
After the change, your csproj file will look something like this
<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.CosmosDB" Version="3.0.9" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Sdk" Version="1.0.3" OutputItemType="Analyzer" />
<PackageReference Include="Microsoft.Azure.Functions.Worker" Version="1.1.0" />
</ItemGroup>
Also make sure that now you are using the Function attribute instead of FunctionName and removed the using statement to import Microsoft.Azure.WebJobs namespace.
[Function("Function1")]
public static void Run([CosmosDBTrigger(
With this change, your functions will be discovered.

NuGet Packages do not compile Azure CSX

I have included a NuGet Package in an Azure Function app that I downloaded to work on in Visual Studio. I have added it to the project.json and I still get "error CS0246: The type or namespace name 'NetTopologySuite' could not be found (are you missing a using directive or an assembly reference?)". I've read through microsoft's documentation and cannot find what I could be doing wrong.
Here is a sample of what my csx looks like:
#r "System.Data"
using System;
using System.Data;
using System.Data.SqlClient;
using System.Net;
using NetTopologySuite;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
\\ Code to retrieve data from database and turn it into an array
\\ of GeoJSON features called DataFromDatabase not shown
NetTopologySuite.Features.Feature[] TrailSegments = DataFromDatabase;
HttpResponseMessage resp = req.CreateResponse(HttpStatusCode.OK);
resp.Content = new StringContent(Newtonsoft.Json.JsonConvert.SerializeObject(DataFromDatabase), System.Text.Encoding.UTF8, "application/json");
return resp;
}
Here is my project.json:
{
"frameworks": {
"net46": {
"dependencies": {
"NetTopologySuite.IO.GeoJSON": "1.14.0"
}
}
}
}
Does anyone have more experience with this that could offer a little more than what's in the documentation?
"FUNCTIONS_EXTENSION_VERSION": "~1"
"WEBSITE_NODE_DEFAULT_VERSION": "6.5.0"
If you do upload the project.json file to your function folder(not function app folder), what you have done is exactly right. I have followed your steps and things work fine on my side.
Nuget restoring for function editable online is not so sensitive, so you may wait for a while(you can do some edit in function code and click save or directly restart whole function app).
After that, you can see a project.lock.json under the function folder. It means the package has been installed successfully. Then everything goes well.
Update for multiple functions sharing reference.
One function package restore can't be used by others. So we have to upload dlls manually if you don't want to add project.json to every function. See shared assemblies.
Download NetTopologySuite.IO.GeoJSON.
Find four dlls(NetTopologySuite.dll/NetTopologySuite.IO.GeoJSON.dll/GeoAPI.dll/PowerCollections.dll) in package and upload them to a bin folder under function app folder.
Add four assemblies in code like #r "..\bin\NetTopologySuite.IO.GeoJSON.dll". You may also need add #r "Newtonsoft.Json" as it's one dependency in that package.
If you use the dll with namespace like NetTopologySuite.Features.Feature[], you don't have to import namespaces. And vice versa.
If you know those dependencies clearly, you can only upload and reference dlls you need.
I see that you are using 3rd party library which is widely available in Nuget official repository. In such cases, you need to let Azure know which Nuget repository your package, 'NetTopologySuite' resides in..
Github: https://github.com/NetTopologySuite/NetTopologySuite
NuGet v3: https://www.myget.org/F/nettopologysuite/api/v3/index.json
NuGet v2: https://www.myget.org/F/nettopologysuite/api/v2
Create Nuget.config file
Add the following contents in that file and re-configure it for your environment.
Nuget.config content - you can find exhaustive file online.

Debugging Azure function as a C# Web Application

I have a simple trigger based Azure function which connects to an Azure event hub and writes out a message each time one is received on the event hub.
I created this as a C# Web Application based on the below post and am trying to debug this function locally:-
https://blogs.msdn.microsoft.com/appserviceteam/2017/03/16/publishing-a-net-class-library-as-a-function-app/
Here is my function code:-
using Microsoft.Azure.WebJobs.Host;
using System;
using System.Threading.Tasks;
namespace FunctionLibrary
{
public class EventHubProcessorFunction
{
public static void Run(string myEventHubMessage, TraceWriter log)
{
log.Info($"C# Event Hub trigger function processed a Vineet message: {myEventHubMessage}");
}
}
}
Here is my function.json
{
"disabled": false,
"scriptFile": ".\\bin\\FunctionAsWebApp.dll",
"entryPoint": "FunctionLibrary.EventHubProcessorFunction.Run",
"bindings": [
{
"type": "eventHubTrigger",
"name": "myEventHubMessage",
"direction": "in",
"path": "edpvineethub",
"connection": "AzureWebJobsServiceBus"
}
]
}
My folder structure is as below:-I have included the following files in the web application project:-
bin\FunctionAsWebApp.dll
NameOfYourFunction\function.json
AnotherFunctionIfYouHaveOne\function.json
appsettings.json
host.json
However I am getting the below error message when trying to run locally;-
No job functions found. Try making your job classes and methods public. If you'r
e using binding extensions (e.g. ServiceBus, Timers, etc.) make sure you've call
ed the registration method for the extension(s) in your startup code (e.g. confi
g.UseServiceBus(), config.UseTimers(), etc.).
Any help would be appreciated.
Check that your folder structure looks like this:
bin\FunctionAsWebApp.dll
NameOfYourFunction\function.json
AnotherFunctionIfYouHaveOne\function.json
appsettings.json
host.json
And function.json should of course reference the binary accordingly
"scriptFile": "..\\bin\\FunctionAsWebApp.dll"
Your initialization is likely failing to perform a lookup on the SB connection string, as it expects an App Setting/Environment variable name and you have the actual connection string there.
Please update your function.json to use an App Setting name, defined in your appsettings.json locally and the Function App settings when hosted, with the connection string set as its value.
Important: Since you have your connection string pasted above, I strongly recommend resetting your credentials.

Use Elastic Scale package within Azure function

I would like to use the Microsoft.Azure.SqlDatabase.ElasticScale.Client package from within my Azure function.
I've added a project.json as follows:
{
"frameworks": {
"net452":{
"dependencies": {
"Microsoft.Azure.SqlDatabase.ElasticScale.Client": "1.3.3"
}
}
}
}
Function:
#r "System.Data"
#r "Newtonsoft.Json"
using System.Net;
using Newtonsoft.Json;
using System.Data.SqlClient;
using Microsoft.Azure.SqlDatabase.ElasticScale.ShardManagement;
public static async Task<HttpResponseMessage> Run(HttpRequestMessage req, TraceWriter log)
{
ShardMapManager shardMapManager;
return req.CreateResponse(HttpStatusCode.OK);
}
I get the following errors:
error CS0234: The type or namespace name 'SqlDatabase' does not exist in the namespace 'Microsoft.Azure' (are you missing an assembly reference?)
error CS0246: The type or namespace name 'ShardMapManager' could not be found (are you missing a using directive or an assembly reference?)
You are missing the #r statement to reference external assembly
The Microsoft.Azure.SqlDatabase.ElasticScale.Client package installs a Microsoft.Azure.SqlDatabase.ElasticScale.Client.dll, so then try:
#r "Microsoft.Azure.SqlDatabase.ElasticScale.Client.dll" or
#r "bin\Microsoft.Azure.SqlDatabase.ElasticScale.Client.dll"
(I've always has issues with the path).
Still, I would recommend not using the CSX scripting approach and instead use precompiled binaries using the technique described here. Then you get the full benefit of C# and you won't have to deal with adding #r statement to include the assembly.

How to bind to ICloudBlob or some other (not string) type

I've been trying to create a Azure function being triggered when I add a image to a container on my blob storage account.
The only thing that seems to work, is when I have a string parameter, but the files are images, so I have no use for a string containing the image data.
So I've been trying each and every example I can find online (not that many), and now I've tried the samples from the azure webjobs sdk - this isn't wokring either. So either I'm stupid, which I feel right now, I'm missing something obvious?
There are some of the errors I get:
Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.thumbnailgenerator'. Microsoft.Azure.WebJobs.Host: Can't bind BlobTrigger to type 'Microsoft.WindowsAzure.Storage.Blob.ICloudBlob'.
Microsoft.Azure.WebJobs.Host: Error indexing method 'Functions.thumbnailgenerator'. Microsoft.Azure.WebJobs.Host: Can't bind BlobTrigger to type 'Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob'.
Right now the function I'm trying out, is the one given in the sample above, and like so many others I've tried, it's not working with anything but strings.
So how should I create the function (with C#) and the function.json file, to make it work with a blob in and preferable a string in with the name of the blob. Either that or blob in and one out, where the name of the out blob is in a different container and the name is prefixed with a hardcoded string.
This is what I got now, and it's not running:
function.json
{
"bindings": [
{
"type": "blobTrigger",
"name": "blob",
"direction": "in",
"path": "kitimages/{name}.{ext}"
},
{
"type": "blob",
"name": "output",
"direction": "inout",
"path": "thumbnails/{name}_300_200.{ext}"
} ],
"disabled": false
}
run.csx
#r "Microsoft.WindowsAzure.Storage"
using System;
using Microsoft.Azure.WebJobs.Host;
using Microsoft.WindowsAzure.Storage.Blob;
public static void Run(CloudBlockBlob blob, CloudBlockBlob output, TraceWriter log)
{
log.Info($"C# Blob trigger function processed a blob. Blob={blob.Name}");
}
EDIT: Take a look here for the final solution to my question: Getting work done in the cloud
We need to improve the template here, this is a common pitfall you've run into (sorry about that!). We're fixing, see the GitHub issue: Make it easier for users to get started with binary blob triggers.
There's a built-in template that binds to streams. Go to New Function and select C# for language and Samples for Scenario.
For a more advanced sample that uses CloudBlockBlob bindings (which requires the InOut binding direction that is not yet documented), see the Functions sample in ContosoMoments: DeleteImages Function.
Note that you can browse all the templates in the GitHub repo: https://github.com/Azure/azure-webjobs-sdk-templates.
For anyone else stumbling upon this while seemingly having a correct setup as per above:
I got this message because I had a reference to WindowsAzure.Storage in my project.json file. Perhaps because it was referring to an older version (8.1.1) of the library.. I don't know. Removing it made my function work. Since it's a supported DLL you should just import it using #r..
I found my solution here (the last reply by Baudine).
I had a project that referenced WindowsAzure.Storage nuget directly and a function project that that project but also referenced WindowsAzure.Storage indirectly (through Microsoft.Azure.WebJobs.Extensions.Storage nuget). After reading Baudine's answer, I saw that the versions off (v9.3.3 vs v9.3.1).
So my fix was as Baudine suggested: I removed the WindowsAzure.Storage nuget from the project and added Microsoft.Azure.WebJobs.Extensions.Storage. My trigger looks like this:
public async Task Run([BlobTrigger("/files/{fileName}", Connection = "StorageConnectionString")]ICloudBlob blob, string fileName)

Resources