Use Elastic Scale package within Azure function - azure

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.

Related

Assembly could not be find in azure function

I am new to Azure Functions and facing the issue related to assembly.
Problem :
I want to read a PPT file which is being uploaded in Sharepoint.
Using Power Automate to start a flow which sends the file content to Azure function.
Azure function should read the content of PPT file.
I have added DocumentFormat.OpenXml (version - 2.13.0) and System.IO.Packaging (version 6.0.0) to bin folder
the code I have written is compiled without errors but when I run the code to test it gives assembly error, please refer to the images.
I have read that it is a known issue that Azure function removes assembly during runtime and this property _FunctionsSkipCleanOutput can be updated but if this is a solution then how to do this via portal?
I am using Azure Portal only.
#r "Newtonsoft.Json"
#r "System.IO.Packaging.dll"
#r "DocumentFormat.OpenXml.dll"
using System.Net;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Primitives;
using Newtonsoft.Json;
using System.Text;
using System;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using System.IO.Packaging;
using DocumentFormat.OpenXml.Presentation;
public static async Task<IActionResult> Run(HttpRequest req, ILogger log)
{
log.LogInformation("C# HTTP trigger function processed a request.");
//string name = req.Query["name"];
string requestBody = await new StreamReader(req.Body).ReadToEndAsync();
dynamic data = JsonConvert.DeserializeObject(requestBody);
string file=data?.file;
byte[] filarray=Convert.FromBase64String(file);
MemoryStream m=new MemoryStream();
m.Write(filarray,0,filarray.Length);
int count=0;
using (PresentationDocument presnt=PresentationDocument.Open(m,true))
{
PresentationPart p=presnt.PresentationPart;
if(p!=null)
{
count=p.SlideParts.Count();
}
}
//name = name ?? data?.name;
string responseMessage = string.IsNullOrEmpty("jogi")
? "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response."
: Convert.ToString(count);
//:file;
return new OkObjectResult(responseMessage);
}
I couldn't get the above working rather I tried to make the azure function using visual studio code and I could read the PPT file by adding reference to OpenXml.

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.

Query CosmosDB from Azure Function .csx

I want to query a CosmosDB collection to see if a document already exists from within a Azure Function using csx.
As well as the following code I have an implicit binding towards the cosmosDB collection to be able to create new documents. This is done using
binder.BindAsync<IAsyncCollector<string>>(new CosmosDBAttribute("test", "collection")
This a simple version of my function.
#r "System"
#r "Microsoft.Azure.WebJobs.Extensions.CosmosDB"
using System;
using Microsoft.Azure.Documents;
using Microsoft.Azure.Documents.Client;
public static async Task<string> Run(string localityId, Binder binder, TraceWriter log)
{
...
string EndpointUrl = "<your endpoint URL>";
string PrimaryKey = "<your primary key>";
DocumentClient client = new DocumentClient(new Uri(EndpointUrl), PrimaryKey);
...
}
This results in the following error message:
error CS0246: The type or namespace name 'DocumentClient' could not be found (are you missing a using directive or an assembly reference?)
I have installed the extension Microsoft.Azure.WebJobs.Extensions.CosmosDB
I am running on MacOS using the func host start command to test locally.
error CS0246: The type or namespace name 'DocumentClient' could not be found (are you missing a using directive or an assembly reference?)
It seems that you need to reference #r "Microsoft.Azure.Documents.Client". You also could get demo code from Azure Cosmos DB bindings for Azure Functions
#r "Microsoft.Azure.Documents.Client"
using System;
using Microsoft.Azure.Documents;
using System.Collections.Generic;
public static void Run(IReadOnlyList<Document> documents, TraceWriter log)
{
log.Verbose("Documents modified " + documents.Count);
log.Verbose("First document Id " + documents[0].Id);
}
Update:
To use NuGet packages in a C# function, upload a project.json file to the function's folder in the function app's file system. Here is an example project.json file that adds a reference

Azure function throwing exceptions when called even with default template

I'm baffled by how to just make a simple Azure function. In Visual Studio 2017 (I'm on version 15.5.6) I create a simple project following the instructions here: https://learn.microsoft.com/en-us/azure/azure-functions/functions-develop-vs
My steps:
Make new Azure Functions project and leave the framework at the default of .Net Framework 4.6.1
On the next screen I choose HttpTrigger and the drop down says "Azure Functions v1 (.NET Framework)"
I set the storage to be my azure storage that I already created in the portal and set the authorization to "admin"
Everything compiles fine. I call the function via PostMan and get this error:
"A ScriptHost error has occurred
Exception while executing function: Functions.Function1. Microsoft.Azure.WebJobs.Host: Exception binding parameter 'log'. Microsoft.Azure.WebJobs.Host: No value was provided for parameter 'log'."
For reference, here is the template function they created that I haven't modified at all:
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.Azure.WebJobs;
using Microsoft.Azure.WebJobs.Extensions.Http;
using Microsoft.Azure.WebJobs.Host;
namespace TestFunc
{
public static class Function1
{
[FunctionName("Function1")]
public static async Task<HttpResponseMessage> Run([HttpTrigger(AuthorizationLevel.Admin, "get", "post", Route = null)]HttpRequestMessage req, TraceWriter log)
{
log.Info("C# HTTP trigger function processed a request.");
// parse query parameter
string name = req.GetQueryNameValuePairs()
.FirstOrDefault(q => string.Compare(q.Key, "name", true) == 0)
.Value;
// Get request body
dynamic data = await req.Content.ReadAsAsync<object>();
// Set name to query string or body data
name = name ?? data?.name;
return name == null
? req.CreateResponse(HttpStatusCode.BadRequest, "Please pass a name on the query string or in the request body")
: req.CreateResponse(HttpStatusCode.OK, "Hello " + name);
}
}
}
If I remove the "TraceWriter log" and the call to "log.Info(...." and then try again, I instead get this error:
"A ScriptHost error has occurred
Exception while executing function: Functions.Function1. mscorlib: Exception has been thrown by the target of an invocation. TestFunc: Method not found: 'System.Net.Http.HttpResponseMessage System.Net.Http.HttpRequestMessageExtensions.CreateResponse(System.Net.Http.HttpRequestMessage, System.Net.HttpStatusCode, !!0)'."
I've tried changing the .Net version to 4.7 but nothing changed. I tried changing the function version to v2 instead of v1 (even though it's in beta at the moment) but nothing happened either. The only NuGet package that's added by the template is Microsoft.NET.Sdk.Functions version 1.0.6. There's an update to 1.0.7 available but that doesn't help either.
I have no idea what to try. This is the default template. I have another function project that works fine but that was done a while ago when VS2015 was the latest, and was during the time when you had to have those function.json files to make your precompiled DLL. I was hoping to be able to use the current system as it seems to be the best way going forward but if I can't get this to work I may just go back to the old way of doing things. Thanks.

Missing dll error from Azure function when updating pipeline

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": []
}
}

Resources