AWS Lambda - C# - Environment Variables only load null - c#

-Using Visual Studio 2017-
I am having trouble reading any configuration for a database connection string for my function to consume.
Most information I come across says to use Environment Variables, but I seem to be doing that wrong, or there is missing information.
If I hard-code the connection string in it works without trouble.
Both
var value = Environment.GetEnvironmentVariable("ConStr");
and any variation of
var value = Environment.GetEnvironmentVariable("ConStr",EnvironmentVariableTarget.Machine/Process/User);
only return me null values.
I have configured the variable in the aws-lambda-tools-defaults.json as directed by most sources
{
"Information" : [blah],
"profile" : "****",
"region" : "****",
"configuration" : "****",
"framework" : "netcoreapp2.1",
"function-runtime" : "dotnetcore2.1",
"function-memory-size" : 256,
"function-timeout" : 30,
"function-handler" : "****::****:****/****/****",
"function-name" : "arn:aws****:****/****/****",
"function-role" : "****",
"tracing-mode" : "PassThrough",
"environment-variables" : "ConStr=FooBar;",
"function-description" : ""
}
I can see the value populate in the publish profile when uploading. I can see the values uploaded properly to AWS Lambda through the console. All instances still fail to access the data.
Several sources also talk about a 'Serverless.template' file that I can not find in my files, and no full example is given. Is this what I'm missing? If so can someone break down how to implement that?

Related

Issue in reading a value from appsettings.Development.json

I have a program that I want to publish as a single exe file which will be used by a user who can change the appsettings as they need. Some of the settings are just for development (included in appsettings.Development.json and this file is not published) and some of them are required for production (included in appsettings.json).
For better clarification consider the following code as appsettings.Development.json
{
"SettingA":
{
"ItemA" : "some value"
},
"SettingB":
{
"ItemB": ["1010","2020","3030"]
}
}
SettingA is used by both development and production and the value can be changed by user
SettingB is only used by development and the value cannot be changed by user
So the appsettings.json would be like, which is published for the user to change:
{
"SettingA":
{
"ItemA" : "some value"
}
}
In order to use this program in production, SettingB is still needed to be set as default value like the following:
class SettingB
{
public string[] ItemB {get; set;} = new string[]{"*"}
}
However, the issue is that when I want to use this in development I expect ItemB to be overriden by the values in appsettings.Development.json, instead I get this:
What I expect: ItemB = {"1010","2020","3030"}
What the result actually is: ItemB = {"*", "1010","2020","3030"}
It seems instead of being replaced, the values are added to the default one.
I have two questions here:
Is this approach of setting default values for such properties like SettingB, OK?
How can I get the expected value for ItemB?
By the way I use Options to read the settings.
I found the answer to my second question in this article. Surprisingly the arrays are merged by design!

Overriding how serenity framework handles [ConnectionKey] attribute

Serenity has the class attribute ConnectionKey which allows you to specify the key for which connection string you want to use.
Code Example below:
[ConnectionKey("Default"), Module("Administration"), TableName("Languages")]
[DisplayName("Languages"), InstanceName("Language")]
[ReadPermission(PermissionKeys.Translation)]
[ModifyPermission(PermissionKeys.Translation)]
[LookupScript(typeof(Lookups.LanguageLookup))]
public sealed class LanguageRow : Row, IIdRow, INameRow
{
[DisplayName("Id"), Identity]
public Int32? Id
{
get { return Fields.Id[this]; }
set { Fields.Id[this] = value; }
}
}
In my case I am making use of AWS Secret Manager to hide any sensitive information so the connection string itself isn't sitting in my appsettings but rather an AWS secret key. Therefore when this code gets hit it throws an error because the secret key isn't a valid connection string.
To get the actual connection string I first need to make a request to the AWS Secret Manager.
In their documentation about a third of the way down the page, in the SqlConnections.New method section, they mention how I can specify a connection string that doesn't exist in my appsettings. However, I don't see how I could apply this solution to my particular problem.
Is there a way to override how Serenity handles this ConnectionKey or any other workaround for this problem?
Serenity has connection source what injected by dependency injection. You can find injection line there. If you want to manage it yourself just remove AddSqlConnections from startup and add manually your connection string source what implement IConnectionStrings interface.
There is default IConnectionStrings implementation what you can use as example.
My final solution to the problem was to make use of the static method inside the SqlConnections class, SetConnection which allowed me to associate a different connection string with the default connectionKey.
var csInfo = SqlConnections.GetConnectionString("SecretConnectionKey");
var connectionString = SecretManagerService.GetSecretAsync(csInfo.ConnectionString, RegionEndpoint.USEast1).Result;
SqlConnections.SetConnection("Default", connectionString, csInfo.ProviderName);
This piece of code was placed at the bottom of the Configure method in startup.
For this to work you would also need to add an empty default ConnectionString inside your appsettings.json files.
{
"Data": {
"SecretConnectionKey": {
"ConnectionString": "secretkey",
"ProviderName": "System.Data.SqlClient"
},
"Default": {
"ConnectionString": "",
"ProviderName": "System.Data.SqlClient"
}
},
I recognise that this is indeed a hacky approach but a time effective solution couldn't be found and this would be replaced with the upgrade to .Net 5.0.

How to config an instance (folder) inside redis database

I am using c# with StackExchange.Redis.
I used something like this to connect :
var client = ConnectionMultiplexer.Connect(_appSettings["Cache:Redis:Configuration"]);
_database = client.GetDatabase(int.Parse(_appSettings["Cache:Redis:LockProcessDB"]));
and then I access the set / get commands via :
_database.StringSet(data.Key, data.Value, TimeSpan.FromSeconds(_ttl), When.NotExists, CommandFlags.None);
...
I now need to divide different "sections" in my data into different "folders" in the redis database.
So instead of just setting values under DB 7, I want DB 7 to have a sub folder called : Documents and the values I am setting should be inserted under that folder.
In the Microsoft.Extensions.Caching.Distributed for .net core solution they support in registering it like this :
services.AddDistributedRedisCache(options =>
{
options.Configuration = ConfigUtils.Instance.Get("Redis_Config", "");
options.InstanceName = "Documents:";
});
which then directs my set commands into the "Documents" sub folder.
How do I achieve that with StackExchange.Redis?
It seems that I didnt understand an important part about separation in a Redis DB.
The option for a prefix and the way to use it.
When trying to set a value I can actually add a prefix like -
string _prefix = "documents:";
_database.StringSet(_prefix + data.Key, data.Value, TimeSpan.FromSeconds(_ttl), When.NotExists, CommandFlags.None);
Which achieves the desired result.
The data saves in my redis DB as documents:myKey under a folder named "documents"

Azure Search SDK Create DataSource

I've been created a datasource by Azure Search SDK.
The Datasource from Azure sql which is a View.
I tyr to setting the DataChangeDetectionPolicy and DataDeletionDetectionPolicy,
but i can't understand how to set this two property.
When i think this two property doesn't supported on the preview sdk,so i try to use REST API to solve this.
I read the article:
MSDN Create Data Source (Azure Search Service REST API)
And use Chrome Extension Postman to set the Data Change Detection Policies.
Url : https://domain.search.windows.net/datasources/temp1?api-version=2015-02-28
body :
{
"#odata.type" : "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName" : "ModifiedDatetime"
}
then i get the 400 bad request .
error message:
{
"error":
{
"code": "",
"message": "The request is invalid. Details: dataSource : Incompatible type kinds were found. The type 'Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy' was found to be of kind 'Complex' instead of the expected kind 'Entity'.\r\n"
}
}
So,i have two questions.
1.Is the SDK are not support this function Now?
2.with the REST API , how to solve the error?
Thanks for reply.
Based on the official article, the way to create the datasource for SQL integration for Views is:
{
"name" : "myazuresqldatasource",
"type" : "azuresql",
"credentials" : { "connectionString" : "connection string" },
"container" : { "name" : "table or view name" },
"dataChangeDetectionPolicy" : {
"#odata.type" : "#Microsoft.Azure.Search.HighWaterMarkChangeDetectionPolicy",
"highWaterMarkColumnName" : "[a row version or last_updated column name]"
}
}
The SDK does support data source creation. See https://learn.microsoft.com/en-us/dotnet/api/microsoft.azure.search.models.datasource

Problems when creating new notes in Simplenote using Simperium

I'm creating an Open Source C# client for Simplenote using Simperium API. Almost everything is ready, but I am facing problems when creating a new note.
How I can create a new note in Simplenote using Simperium API?
Once you have the app id and API key you can create new notes just like creating any Simperium object as referenced in the documentation.
The bucket to post to is note and it'll also need to conform to the schema in the following sample note:
{
"tags" : [ "todo", "later" ],
"systemTags" : [],
"creationDate" : 1335390338.091436,
"modificationDate" : 1335390338.091436,
"deleted" : false,
"shareURL" : "",
"publishURL" : "",
"content" : "new note content!"
}
All fields are needed when creating, but you can just specify the fields that have changed when updating.

Categories