I have been learning the bot framework from microsoft and have been following a tutorial on pluralsight. I have made the changes to my Global.asax.cs and for some reason I keep on getting the error setting must be in the form name=value. I have no idea what to do and how to get rid of these errors. Any help would be highly appreciated.
Global.asax.cs
public class WebApiApplication : System.Web.HttpApplication
{
protected void Application_Start()
{
// This code chunk below will allow us to use table bot data store instead of
// in memory data store
Conversation.UpdateContainer(
builder =>
{
builder.RegisterModule(new AzureModule(Assembly.GetExecutingAssembly()));
// here we grab the storage container string from our web config and connecting
var store = new TableBotDataStore(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
builder.Register(c => store).
Keyed<IBotDataStore<BotData>>(AzureModule.Key_DataStore).
AsSelf().
SingleInstance();
});
GlobalConfiguration.Configure(WebApiConfig.Register);
TableBotDataStore is for Azure Table Storage, and it seems you are using some sql connectionstring. You would usually have that connection string in the AppSettings section, not the ConnectionStrings section (yes, the names are a bit misguiding here).
Related
I want to use user secrets for KeyVault clientid etc. I call my configs from program.cs when I setup KeyVault. When I add the values in appsettings.json all works fine, but if I remove it and manage user secrets it's always say null when my program.cs is running.
And I have the correct values in the created secret.json and the attribute with a guid to it is also in my project file
I have also tried to add a key and value to the secret.json and tried to get it from a controller and it's also null.
So it seems like WebHost.CreateDefaultBuilder in my program.se does not load my secret.json file.
And if I add AssUserSecrets to my WebHost.CreateDefaultBuilder(args) in progam.cs there is no difference same problem.
I'm using WebHost.CreateDefaultBuilder so it shall be used by default in asp .net core 2.2
dontnet user-secret list
Will also shows the values for me from my secret.json file so the value is there, the user-secret has been initialized.
dontnet user-secret init
Also, say it's already setup.
But still just null when calling my secret.json attributes
public static IWebHostBuilder CreateWebHostBuilder(string[] args) =>
WebHost.CreateDefaultBuilder(args)
.UseStartup<Startup>()
.ConfigureServices(services => services.AddAutofac())
.ConfigureAppConfiguration((context, builder) =>
{
var config = builder.Build();
var vault = config["KeyVault:Vault"];
builder.AddAzureKeyVault($"https://{config["KeyVault:Vault"]}.vault.azure.net/", config["KeyVault:ClientId"], config["KeyVault:ClientSecret"]);
});
I test in my site and it works fine, here is the steps you could refer to.
1.Right click on the project and select Manage User Secrets. It will open the secrets.json file in Visual Studio where you can add your secrets and it will add the to the .csproj file.
2.Add what you may wish to add to your User Secrets. It includes two ways of writing a json object and a simple key/value pair.
3.Mapping User Secrets to a model.
public class KeyVault
{
public string Vault { get; set; }
public string ClientId { get; set; }
public string ClientSecret { get; set; }
}
4.Adding the Configuration.
Install package Microsoft.VisualStudio.Web.CodeGeneration.Design and Microsoft.Extensions.Configuration and Microsoft.Extensions.Configuration.UserSecrets
5.Bind the values. This is done in the Startup.cs file.
6.Using your mapped secrets
public class HomeController : Controller
{
private readonly KeyVault _keyvault;
// I’ve injected twilioAccountDetails into the constructor
public HomeController(IOptions<KeyVault> keyvault)
{
// We want to know if twilioAccountDetails is null so we throw an exception if it is
_keyvault = keyvault.Value ?? throw new ArgumentException(nameof(keyvault));
}
........
}
7.Call it in Program.cs.
For more details about how to use User Secrets in a .NET Core Web App, you could refer to this article.
It seems to be related to: Microsoft.Extensions.Configuration.AzureKeyVault
because as soon I add that nuget it stops working.
UPDATE: More info. it seems like the latest Microsoft.Extensions.Configuration.AzureKeyVault downgrade some of the configuration libs for me. And then it stops working.
I was having this same issue when using Host.CreateDefaultBuilder() and discovered that it was because my host environment was not Development.
To resolve this I added the following section to my launchSettings.json:
"environmentVariables": {
"DOTNET_ENVIRONMENT": "Development"
}
See related documentation:
The following defaults are applied to the returned HostBuilder:
load app IConfiguration from User Secrets when EnvironmentName is 'Development' using the entry assembly
In my case, I was missing the following NuGet package:
Microsoft.Extensions.Configuration.UserSecrets
Once I installed this, it worked perfectly.
I am using PCLStorage to store image in localStorage and access them via path returned.
Its working fine but the problem is, whenever I again start debugging the application, images are not accessible.
Where actually it stores images in Local Storage? Is it not permanent location?
I want to store images in fileSystem and related data and image path in sqlite. Its an offline application so need to store this data permanently.
Any suggestions for this would be helpful.
Thanks
Try below steps.
The interface is fairly simple because we're really only interested in passing the byte array and a filename when we save the image to disk.
public interface IPicture
{
void SavePictureToDisk (string filename, byte[] imageData);
}
DependencyService will delegate image saving to the appropriate class. The usage for the DependencyService is:
DependencyService.Get<IPicture>().SavePictureToDisk("ImageName", GetByteArray());
Create Classes in Platform-Specific Projects
iOS Project
[assembly: Xamarin.Forms.Dependency(typeof(Picture_iOS))]
namespace ImageSave.iOS
{
public class Picture_iOS: IPicture
{
public void SavePictureToDisk(string filename, byte[] imageData)
{
var MyImage = new UIImage(NSData.FromArray(imageData));
MyImage.SaveToPhotosAlbum((image, error) =>
{
//you can retrieve the saved UI Image as well if needed using
//var i = image as UIImage;
if(error != null)
{
Console.WriteLine(error.ToString());
}
});
}
}
}
I got the answer for this question on Xamarin Forum so just updating the link here so it can help others.
https://forums.xamarin.com/discussion/comment/217282/#Comment_217282
As explained here that everytime we redeploy app the core path changes thats why on redeploying I was not able to find images on the path where I saved it. So now I am only saving the partial path like the folderName\the image name and rest of the core path I am finding on runtime.
This solved my problem.
I am new to Azure App Service.
I've created a view in Azure database to get data across several tables. Now I want to use the data from this view in my Cordova App using the Azure Mobile Service (MobileService.GetTable...). I found several articles in the web that describe how to do that in Classic Azure Portal. But I need a solution for the NEW Azure App Service with Node.js Backend.
What is the syntax to return data from a view as an Azure table?
var table = module.exports = require('azure-mobile-apps').table();
table.read(function (context) {
// *** Need code to return data from sql view ***
//return context.execute();
});
And it would be great to use a parameter to filter data in the view before returning.
Thanks,
Uwe
You are pretty much right there. You need to just create a table controller to access the view. Ensure you have the system columns defined (version, updatedAt, createdAt, deleted and id). Also, ensure the right thing happens when you update the view (e.g. with an INSERT, UPDATE, DELETE) as that will tell you what needs to be done with the controller (for example, if you can't insert/update/delete, then make it read-only).
Reference blog post for you: https://shellmonger.com/2016/04/15/30-days-of-zumo-v2-azure-mobile-apps-day-8-table-controller-basics/
Things can be so easy sometimes ;-)
All I need to do is to write the following lines to my table controller:
var table = require('azure-mobile-apps').table();
table.databaseTableName = 'ViewName';
module.exports = table;
Thanks for your help!
Had a similar issue but fixed it now, am using a .Net backend thou.
1. Log into azure portal and select the database you want to create the view in Then select the query Editor in the left pane.
2. Use the sql to create the query.
3.Create a table in the asp.net backend that matches your fields in your view.
4.Go to your asp.net backend and create a custom Api and write the following codes:
public class HelloCustomController : ApiController
{
MobileServiceContext context;
public HelloCustomController()
{
context = new MobileServiceContext();
}
[HttpGet]
public async Task<List<vwUser>> Get()
{
try
{
var users = context.Database.SqlQuery<vwUser>("Select * from
dbo.vwUser);
return await users.ToListAsync();
}
catch(Exception ex)
{
return new List<vwUser>()
{
new vwUser
{
UserName=ex.Message
}
};
}
}
4.You edit my codes to select from your view.
5. Create a similar class in your mobile app that matches what u created in your backend.
5. You can then access your view by calling it in your mobile app with the following codes:
var users= await client.InvokeApiAsync<vwUser>("HelloCustom",HttpMethod.Get,null);
Thanks Guys. This is my fisrt answer to this beautiful community that carried me from day 1 of programming till now that am a bit conversant.
I'm trying to work with Azure Webjobs, I understand the way its works but I don't understand why I need to use two connection strings, one is for the queue for holding the messages but
why there is another one called "AzureWebJobsDashboard" ?
What its purpose?
And where I get this connection string from ?
At the moment I have one Web App and one Webjob at the same solution, I'm experiment only locally ( without publishing anything ), the one thing I got up in the cloud is the Storage account that holds the queue.
I even try to put the same connection string in both places ( AzureWebJobsDashboard,AzureWebJobsStorage) but its throw exception :
"Cannot bind parameter 'log' when using this trigger."
Thank you.
There are two connection strings because the WebJobs SDK writes some logs in the storage account. It gives you the possibility of having one storage account just for data (AzureWebJobsStorage) and the another one for logs (AzureWebJobsDashboard). They can be the same. Also, you need two of them because you can have multiple job hosts using different data accounts but sending logs to the same dashboard.
The error you are getting is not related to the connection strings but to one of the functions in your code. One of them has a log parameter that is not of the right type. Can you share the code?
Okay, anyone coming here looking for an actual answer of "where do I get the ConnectionString from"... here you go.
On the new Azure portal, you should have a Storage Account resource; mine starts with "portalvhds" followed by a bunch of alphanumerics. Click that so see a resource Dashboard on the right, followed immediately by a Settings window. Look for the Keys submenu under General -- click that. The whole connection string is there (actually there are two, Primary and Secondary; I don't currently understand the difference, but let's go with Primary, shall we?).
Copy and paste that in your App.config file on the connectionString attribute of the AzureWebJobsDashboard and AzureWebJobsStorage items. This presumes for your environment you only have one Storage Account, and so you want that same storage to be used for data and logs.
I tried this, and at least the WebJob ran without throwing an error.
#RayHAz - Expanding upon your above answer (thanks)...
I tried this https://learn.microsoft.com/en-us/azure/app-service/webjobs-sdk-get-started
but in .Net Core 2.1, was getting exceptions about how it couldn't find the connection string.
Long story short, I ended up with the following, which worked for me:
appsettings.json, in a .Net Core 2.1 Console app:
{
"ConnectionStrings": {
"AzureWebJobsStorage": "---your Azure storage connection string here---",
"AzureWebJobsDashboard":"---the same connectionstring---"
}
}
... and my Program.cs file...
using System;
using System.IO;
using Microsoft.Azure.WebJobs;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Logging;
namespace YourWebJobConsoleAppProjectNamespaceHere
{
public class Program
{
public static IConfiguration Configuration;
static void Main(string[] args)
{
var builder = new ConfigurationBuilder()
.SetBasePath(Path.Combine(AppContext.BaseDirectory))
.AddJsonFile("appsettings.json", true);
Configuration = builder.Build();
var azureWebJobsStorageConnectionString = Configuration.GetConnectionString("AzureWebJobsStorage");
var azureWebJobsDashboardConnectionString = Configuration.GetConnectionString("AzureWebJobsDashboard");
var config = new JobHostConfiguration
{
DashboardConnectionString = azureWebJobsDashboardConnectionString,
StorageConnectionString = azureWebJobsStorageConnectionString
};
var loggerFactory = new LoggerFactory();
config.LoggerFactory = loggerFactory.AddConsole();
var host = new JobHost(config);
host.RunAndBlock();
}
}
}
I have read that the easiest way for setting up a connection and creating a table is putting the following line of codes in the webrole.cs onStart() method.
but for some reason I have got errors and when I put the same code in global.asax.cs Application_start() method. it works fine?
what is the difference
here is the code I am talking about : I am using tablestorage bytheway
...
CloudStorageAccount.SetConfigurationSettingPublisher((configName, configSettingPublisher) =>
{
var connectionString = RoleEnvironment.GetConfigurationSettingValue(configName);
configSettingPublisher(connectionString);
}
);
var account =
CloudStorageAccount.FromConfigurationSetting(
Constants.KEY_STORAGE);
//create table
var client = account.CreateCloudTableClient();
client.CreateTableIfNotExist(Constants.EMAILMERGE_TABLE);
/////////////////////////////////
and the Error I am getting is-----------------------------
SetConfigurationSettingPublisher needs to be called before FromConfigurationSetting can be used
Tnx for the tips!!
cheeers
For a worker role, we only need to put the code in OnStart. But for a web role, we need to put the code in two places. If you want to access storage in OnStart, please put the code in OnStart. If you want to access storage in your web application, please put the code in Global.asax’s Application_Start. If you need both, please put the code in both places.
Best Regards,
Ming Xu.