2

I have a ASP.NET MVC project which I am currently working on. I want to try some code in C# interactive, I click on "Initialize interactive with project." I can see the variables, classes and other thing in c# interactive.

Now one thing is broken is static variable that is defined through web.config is throwing exception.

If I paste the code (in interactive window) that is using web.config variable is not working. Anyway to fix this issue.

I check the answer by SeM and I check the appsettings it's have nothing enter image description here

update 2:

I setup the code on github with reading appsettings as given in answer, still didn't work, code is here https://github.com/anirugu/CsharpInteractiveTesting

Anirudha Gupta
  • 9,073
  • 9
  • 54
  • 79

2 Answers2

5

C# interactive itself runs as a separate application with separate application configuration file. If you run this in C# interactive:

AppDomain.CurrentDomain.SetupInformation.ConfigurationFile

You will see something like:

"<path to VS>\\CommonExtensions\\Microsoft\\ManagedLanguages\\VBCSharp\\InteractiveComponents\\InteractiveHost.exe.Config"

So that's the config file being used. Of course it does not contain your variables, so code trying to do ConfigurationManager.AppSettings["foo"].ToString() fails.

Usual way to set config file at runtime is:

AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", fullPathToYourConfig);

However, this should be done before any access to configuration file. When first access is made - file is being cached and subsequent changes to path will have no effect. Unfortunately, before giving you access to executing commands, C# interactive already works with that file.

There are various hacks with reflection to reset that cache. For example (copied verbatim from here):

public static void ChangeConfigTo(string path)
{
    AppDomain.CurrentDomain.SetData("APP_CONFIG_FILE", path);
    typeof(ConfigurationManager)
        .GetField("s_initState", BindingFlags.NonPublic |
            BindingFlags.Static)
        .SetValue(null, 0);

    typeof(ConfigurationManager)
        .GetField("s_configSystem", BindingFlags.NonPublic |
            BindingFlags.Static)
        .SetValue(null, null);

    typeof(ConfigurationManager)
        .Assembly.GetTypes()
        .Where(x => x.FullName ==
            "System.Configuration.ClientConfigPaths")
        .First()
        .GetField("s_current", BindingFlags.NonPublic |
            BindingFlags.Static)
        .SetValue(null, null);
}

With all that in mind, if you put that function in Program class in your sample on github and do this in C# interactive:

Program.ChangeConfigTo(Path.GetFullPath("app.config"));

Your code will work as you expect. You can put this hack in separate script (.csx) file and load it with "#load" if necessary.

Evk
  • 98,527
  • 8
  • 141
  • 191
2

For example, if you add your setting into config file

<appSettings>
    <add key="Test" value="Test"/>
</appSettings>

and try to read it by ConfigurationManager, it will throw exception of missing reference or

The name 'ConfigurationManager' does not exist in the current context

In C# interactive window you can reference assemblies with keyword #r

#r "System.Configuration"

and then you can get your value:

#r "System.Configuration"
var settings = ConfigurationManager.OpenExeConfiguration(@"bin\Debug\YourAppName.dll"); //You can use .exe files too
Console.WriteLine(settings.AppSettings.Settings["Test"].Value);

Also! You can add project's all references by right click to your project -> Initialize Interactive with Projcet and VS will do all for you.

Update

For your example:

using System.Configuration;
var settings = ConfigurationManager.OpenExeConfiguration(@"D:\TestProjects\CsharpInteractiveTesting-master\CsharpInteractiveTesting-master\CsharpInteractiveTesting\bin\Debug\CsharpInteractiveTesting.exe");
Console.WriteLine(settings.AppSettings.Settings["foo"].Value);
SᴇM
  • 7,024
  • 3
  • 24
  • 41