This is my first crack at creating an Azure App Function. I've got it working when running on my local dev machine. Now I've deployed it into Azure, and I'm attaching the debugger to it (very cool, btw!).
When running on my localhost, I can use the local.settngs.json file for all of the app settings. That works fine. But I seem to be hitting a roadblock on the simple process of accessing application settings when running the function remotely in Azure.
First (and this is a battle I will fight later) I'm sure there is a way to auto-populate the settings in the Azure Function based on what's in local.settngs.json, but for now, I added them all manually.
For now, let's just take a look at the setting StorageConnectionString who's value looks like this:
DefaultEndpointsProtocol=https; AccountName=[redacted]; AccountKey=[redacted]; EndpointSuffix=core.windows.net
All three of these attempts to get the value work on my localhost, but all three also fail when debugging in the remote Azure function:
string storageConString = ConfigurationManager.AppSettings["StorageConnectionString"];
string storageConString = CloudConfigurationManager.GetSetting("StorageConnectionString");
string storageConString = Environment.GetEnvironmentVariable("StorageConnectionString");
In all cases, I get this this error:
Error message:
Value cannot be null. Parameter name: itemName
Stack Trace:
at Microsoft.WindowsAzure.Storage.Core.Util.CommonUtility.AssertNotNullOrEmpty(String paramName, String value) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Common\Core\Util\CommonUtility.cs:line 143 at Microsoft.WindowsAzure.Storage.File.CloudFileDirectory.GetDirectoryReference(String itemName) in c:\Program Files (x86)\Jenkins\workspace\release_dotnet_master\Lib\Common\File\CloudFileDirectory.Common.cs:line 224 at XXXXXXX.Common.AzureFunctions.ProcessInbound.DoBooksExist(BookSource bookSource) at XXXXXXX.Common.AzureFunctions.ProcessInbound.Run(TimerInfo myTimer, TraceWriter log)
The error has me kind of stumped, as it doesn't even seem to apply. Why, for example, is it calling GetDirectoryReference(String itemName)?
To get an environment variable or an app setting value, use System.Environment.GetEnvironmentVariable, as shown in the following code example:
public static string GetEnvironmentVariable(string name)
{
return System.Environment.GetEnvironmentVariable(name, EnvironmentVariableTarget.Process);
}
App settings can be read from environment variables both when developing locally and when running in Azure. When developing locally, app settings come from the Values collection in the local.settings.json file. In both environments, local and Azure, GetEnvironmentVariable("<app setting name>") retrieves the value of the named app setting. For instance, when you're running locally, "My Site Name" would be returned if your local.settings.json file contains { "Values": { "WEBSITE_SITE_NAME": "My Site Name" } }.
Or you can use System.Environment.GetEnvironmentVariable:
Taken from Azure Functions C# developer reference - Environment variables
Ok, finally got this figured out. The core of the issue is some strange behavior on how the debugger works when attached remotely. I finally figured out the real issue by setting the Publish Configuration to Debug before publishing:
The problem had been that when I had it set to "Release", the debugger would break on the first line of the method that had the error in it, and NOT on the actual line with the error. This lead me to think I was getting the error on a line that was not, actually, throwing the error.
Once I knew the true line that was throwing the error, solving it was a snap.
Related
i am trying to connect to the google firestore. i was able to connect, giving me key.json file as param:
FirestoreDb db = new FirestoreDbBuilder { ProjectId = "interiorcircle", CredentialsPath = "/Users/juliustolksdorf/Projects/Interior_Circle/keys/interiorcircle-4f70f209e160.json" }.Build()
But i heard its more common to do this via env variable. I tried setting it up wth terminal in .zshenv and also in .bash_profile (both).
Then i also went into terminal and set the variable.
Now, when I set "env" into terminal I am getting this line:
So it does look like the file is set correctly. But when I try to run my application with:
var credential = GoogleCredential.GetApplicationDefault();
(which is the recommended way)
my debugger hangs for about 5 minutes until it thorws an exception:
One or more errors occurred. (The Application Default Credentials are not available. They are available if running in Google Compute Engine. Otherwise, the environment variable GOOGLE_APPLICATION_CREDENTIALS must be defined pointing to a file defining the credentials. See https://developers.google.com/accounts/docs/application-default-credentials for more information.)
So what am I doing wrong here? Im stuck at this for hours now.
EDIT:
I am working with xamarin.forms application. I set the variable in terminal from mac OS, not in console of xamarin.
I tried:
var x = Environment.GetEnvironmentVariable("GOOGLE_APPLICATION_CREDENTIALS");
But im being returned "null"
I have been using c# code to get blob items for the past few days, however, with no changes to the way the program gets the blob data, it stopped working. I run into the same error every time I run now:
"EnvironmentCredential authentication unavailable. Environment variables are not fully configured"
Here is the code I am using to connect to Azure:
Uri accountUri = new Uri(mystorageurl);
BlobServiceClient client = new BlobServiceClient(accountUri, new DefaultAzureCredential(true));
BlobContainerClient container = client.GetBlobContainerClient(blobname);
BlobClient bundle = container.GetBlobClient(itemname);
What I've been confused by is that if I run this same code in a separate vs solution, I get no error getting the files from Azure. I've also tried sending the same solution that's getting the error to another person and they were able to run it without issue. I know it isn't an issue with environment variables, since it used to work up until now and they haven't been modified in any way.
This unresolved issue on github is most similar to what I've encountered:
https://github.com/Azure/azure-sdk-for-net/issues/16079
It worked fine when you never set Environment variables, it means that you didn't use EnvironmentCredential. The DefaultAzureCredential will attempt to authenticate via the following mechanisms in order, and Environment is the first one.
If you just use Environment to authenticate, it's better to use EnvironmentCredential instead of DefaultAzureCredential. And it's necessary to set the following variables.
AZURE_CLIENT_ID: id of an Azure Active Directory application
AZURE_TENANT_ID: id of the application's Azure Active Directory tenant
AZURE_CLIENT_SECRET: one of the application's client secrets
I've created an Azure function and tested it locally in Visual Studio without issue. I just published the function to Azure and now when I run it I get this error:
2019-11-26T20:41:11.822 [Error] Executed 'PullAffiliationsFunction' (Failed, Id=13a5b787-db22-4b04-96ba-f5718c36aa75)
Value cannot be null.
Parameter name: value
I don't have any parameters named value in my function. I see no stack trace to give me more information about what is causing this error. Did I miss a configuration setting somewhere? I published directly from Visual Studio so I would expect it would publish everything. How would you debug this?
If you get this exception as part of the Executed message, it's most likely thrown by your function code. Do you have the full log entry for that? It may include a stack trace as well.
The local settings and environment variables (from local.settings.json) actually do not automatically get pushed to Azure on publish.
I have seen this exception commonly when one may have forgotten to set an environment variable as an App Setting or a connection string. Did you set all the environment variables you used locally in your Azure function app through Application Settings or configuration in your app?
I created an Azure function app locally in Visual Studio 2017(Not Azure portal) by following the steps at the following URL.
https://blogs.msdn.microsoft.com/appserviceteam/2017/03/16/publishing-a-net-class-library-as-a-function-app
I followed the steps exactly to create a function that has a “ServiceBusTopicTrigger”. I added the following to my function.json
{
“disabled”: false,
“bindings”: [
{
“name”: “mySbMsg”,
“type”: “serviceBusTrigger”,
“direction”: “in”,
“topicName”: “negotiatedaddcharge_test”,
“subscriptionName”: “clientdispatches”,
“connection”: “servicebusnac”,
“accessRights”: “manage”
}
]
}
My appsenttings.json has the following
{
“IsEncrypted”: true,
“Values”: {
“servicebusnac”: “Endpoint=MyCompanyEndPointPlaceHolder”
}
}
When I run the function in Visual Studio I keep getting an error message “Microsoft.Azure.WebJobs.ServiceBus: Microsoft Azure WebJobs SDK ServiceBus connection string ‘AzureWebJobsservicebusnac’ is missing or empty.”
Just for the heck of it I added another entry to the values collection with the name “AzureWebJobsservicebusnac” but still the same message shows up. Is there something that I am doing wrong?
Also how do you unit test this function? I cannot Access any function in the csx file in my unit test project.
Thanks.
Edited:
I added information to make it clear that I am creating the function in Visual Studio rather than the Azure portal.
Function App will search for your Service Bus connection strings in Environment variables. You can set those from Azure portal:
Go to your Function App.
Select Platform features tab above the editor.
Click Application settings.
Under App settings section add an entry with connection name and string.
The appsettings.json file is used to support local development only, and settings defined there are not published to Azure.
The solution is simple; I actually ran into this myself and it had me completely stumped for a while.
In your appsettings.json, change "IsEncrypted" from true to false. This should fix the issue you're seeing.
The error messages are less than ideal for this scenario; the Azure Functions team already has a bugfix in for it.
Hope this helps anyone who runs into this issue. (I swear, it was a week before I figured this out, and not without help.)
I have a C# console application that reads app settings from its app.config. The console application is targeted as the action of a Windows Scheduler Task. It runs once a day.
Since adding the code to read from the configuration file the app crashes only when run by the Task Scheduler. When run manually (from command prompt or by clicking on it in it's folder)), the application runs with no issues and it works exactly as expected.
Here's the code that reads from the app settings section:
int someValue = 1;
try
{
if (ConfigurationManager.AppSettings["someValue"] != null)
someValue = int.Parse(ConfigurationManager.AppSettings["someValue"].ToString());
}
catch(Exception exception)
{
// Write to error log
}
This is the exception I'm getting in my error log:
Exception: The type initializer for '<my application name>' threw an exception.
System.Configuration.ConfigurationErrorsException: An error occurred loading a configuration file: The parameter 'exePath' is invalid.
Parameter name: exePath ---> System.ArgumentException: The parameter 'exePath' is invalid.
Parameter name: exePath
I have tried allowing the task to run with highest privileges. I have tried accessing the configuration file in different ways (Configuration.OpenConfigurationExe(...)), etc... I get the same problem every time. I have tried putting my .exe in various locations on disk. This one is in C:\Program Files. I have looked around on S.O. and this post suggests that it might be a read permissions issue, but if the task runs under my domain's account and has the highest privileges, is that still possible? Note that it runs just fine if I run it manually from a command prompt or by clicking on it.
How can I reliably get a console application to read its app.config if it has been configured to run under Windows Task Scheduler?
Solved it. Turns out I had some legacy bits running code like this:
Configuration config = ConfigurationManager.OpenExeConfiguration("<app exe name>");
This where the exception was being thrown, not in the code in my question. Shame on me. Should have debugged that more thoroughly. I removed it all and replaced the local config object usage above with calls to:
ConfigurationManager.AppSettings["someValue"];
It could definitely be a permission issue, and maybe more than just read permissions. Things to check:
IS the task running under YOUR account, or another account? If this app is stored under a directory in your local profile then even other administrator accounts don't have permissions by default (they have to manually set permissions). Try moving the application to a local folder on the hard drive and set permissions as needed.
Try setting audit settings for the directory your app is stored in. If it is a permission issue then the security log will tell you more about what and why it is getting denied.