Hi I need to provide each user with some default settings - list of string
Then each user can add new and sav?
I am using user-scope settings.
What are my options?
UPDATE:
I cant even find default settings in file in debug folder. So the question is what do I need tp deploy to user machine
I would add class as AppSetting and make it serialize able.
Then I will add a ApplicationSettingManager it will look at a default path in such a folder like Environment.SpecialFolder.ApplicationData if the setting file was there it will use it to deserialize AppSetting if not it will save the default setting there (you can put default setting in AppSetting class or you can use app.config file beside .exe to have your default setting). whenever a user changed the setting ApplicationSettingManager will over write the setting file.
string ApplicationDataFolder
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
Assembly.GetExecutingAssembly().GetName().Name);
}
}
string UserSettingFilePath
{
get
{
return Path.Combine(ApplicationDataFolder, "Setting.xml");
}
}
[Serializable]
public class AppSetting
{
public AppSetting()
{
//default instantiation
}
public int? CurrentUserId
{
get;
set;
}
}
enter code he
Look at http://msdn.microsoft.com/en-us/library/system.environment.specialfolder.aspx for different paths you can use
You can use the Settings object that is part of the Microsoft.VisualBasic library.
In C# you can access these through:
Properties.Settings.Default.FirstUserSetting = "abc";
And then save them out to disk with:
Properties.Settings.Default.Save();
This will store them in an app specific directory under Users\[UserName]\AppData\Local
Alternatively, you can manage the serialization yourself and write them out to either Environment.SpecialFolder.ApplicationData or Environment.SpecialFolder.LocalApplicationData
Related
I want to assign Active Directory group name dynamically as an attribute to authorize filter.
Currently we have 2 Active Directory groups, one is for DEV and other is for Prod. However if I have access to dev while debugging in local, I need to have access to the action method. If the AD group is prod, I should not have have access to the action method.
I tried using constants in static class classA
public const string DevActiveDirectoryName = "DevdirectoryName";
public const string ProdActiveDirectoryName = "ProddirectoryName";
My action method is like this:
[Authorize(Roles = ClassA.DevActiveDirectoryName)]
public async task<Iactionresult>GetMemberID()
{
}
The only problem with above solution is if I want to deploy to prod, I need to change code and deploy it. Instead if I can pass value dynamically to attribute that would solve my problem. I have tried many ways. Please suggest the best solution for this case. Is there any workaround for this kind of problem? I appreciate your help.
In order to be able to change the group name for different environments, you need to use configuration settings instead of constants. There are many options on how to provide configuration settings to an ASP.NET Core application. This link gives an overview.
If your application uses the default host builder, it will read configuration settings from a variety of sources, e.g. appsettings.json. You can add a setting to this file (if it does not exist yet, add it to the project), e.g.:
{
"ADGroupName": "ProddirectoryName"
}
For your dev-environment there is a dedicated file appsettings.dev.json that you can use to hold your dev settings:
{
"ADGroupName": "DevdirectoryName"
}
When protecting the controller with an Authorize attribute, you need to provide a constant value to the constructor. As the configuration setting can be changed later, it is (obviously) not constant.
Therefore, you have to set up a policy with a constant name in the ConfigureServices method in Startup.cs:
var adGroupName = Configuration.GetValue<string>("ADGroupName");
services.AddAuthorization(options =>
{
options.AddPolicy("ADGroupPolicy", policy =>
{
// This requirement checks for the group
policy.RequireRole(adGroupName);
});
});
For the controller, you need to add the policy name to the Authorize attribute:
[Authorize("ADGroupPolicy")]
public async task<Iactionresult>GetMemberID()
{
}
You can add an entry in your <appSettings> of your web.Config file and use ConfigurationManager to look up the value that should be assigned to a variable ActiveDirectoryName.
<appSettings>
<add key="ActiveDirectoryName" value="DevdirectoryName" />
... // other keys
</appSettings>
and in your code, you could look up what you have in your web.Config file (Dev for development and Prod for production servers (you dont need to deploy new web.config when deploying new code unless you make changes to it.
public const string ActiveDirectoryName = ConfigurationManager.AppSettings["ActiveDirectoryName"];
If you are using Visual Studio, web.config have two different configs (web.debug.config / web.release.config). You can use debug for development and Release that works on production.
This will stay constant and only your config files are changed,
[Authorize(Roles = ClassA.ActiveDirectoryName)]
public async task<Iactionresult>GetMemberID()
{
}
I have a class library i want end up packaging into a nuget package, i have some configurations i wish to use which are in a json file (apsettings.json).
I have added this file to my class library project, and at the moment i just want to read the values in the configurations in a constructor without using a .config file, i will like to use a .json similar to how i'll do it in a web project.
I am trying something like this, but i get an error stating that the settings.json file does not exist in \bin\Debug\netcoreapp2.0. It is not in that folder, it is in the root of my project.
public TokenGenerator()
{
var builder = new ConfigurationBuilder().SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("settings.json");
_configuration = builder.Build();
_tokenServiceSettings = new TokenServiceSettings()
{
Audience = _configuration.GetSection("JwtBearer:Audience").Value
};
}
At the moment, i have just hard coded the directory as a string inside the SetBasePath method
If you are writing a library that other teams might use in other projects, you should not bind it to another package (Microsoft.Extensions.Configuration) just for configuration.
You should have your own Option class which is a simple class with bunch of properties
public class TokenServiceOptions
{
public TokenServiceOptions()
{
Audience = "Audience_Default_Value!";
}
public string Audience { set; get; }
public string OtherOption1 { set; get; }
public string OtherOption2 { set; get; }
///
}
and let your library users pass an instance of TokenServiceOptions to your method.
It should not be important to a library how options are gathered.
Because this is in a library, this class cannot know where and what json file to read.
Pass the full path to the file to the library or,
Pass a structure as an argument to the library so the calling assembly can pass in the data and store it anywhere and any way it likes or
Get the location of the CallingAssembly (Assembly.GetCallingAssembly().Location) and construct a relative path to that.
We are converting an existing web application over to .NET Core. While in the process, we would like to be able to access both the web.config and the appsettings.config. In order to do so, we are creating a MySiteConfigurationManager class so that we can just do a quick find a replace for all of the ConfigurationManager.AppSettings["Datawarehouse.ConnectionString."] instances. Inside of the custom indexer property similarly called AppSettings[string key] of my MySiteConfigurationManagerclass I plan to do something similar to the following:
public string this[string key]
{
get
{
if (!key.Contains(":"))
{
return ConfigurationManager.AppSettings["key"];
}
return //some code here to access the appsettings.json value
}
}
Now I could just StreamRead the file itself and get the value needed but I am not sure if there is another way to access the appsettings.json values. As an example both of the following might appear in the project trying to access a configuration value:
MySiteConfigurationManager.AppSettings["Audit.DisableLogging"];
MySiteConfigurationManager.AppSettings["MRU:ItemLimit"]
My goal is for both to be able to work seamlessly if possible.
var userName = ConfigurationManager.AppSettings["FileUploadRoot"];
Iam getting null for the variable Username. The key FileUploadRoot is in another projects web config entry and the above piece of code is in another projects class file. so can you please tell me how to get the value from the web config file
The best way would be to include the config value in your first project too, to make it self-contained.
You can use a static class in the project that has the web.config file and expose the value in the web.config in an internal property
You can use something like this:
static class Utility
{
internal static string FileUploadRoot
{
get
{
return ConfigurationManager.AppSettings["FileUploadRoot"];
}
}
}
Another solution would be to add the file as a link to your project.
Right click on you project in solution explorer.
Select Add Existing Item...
Select the web.config file in the OpenFileDialog, but choose the Add as Link option in the dialog.
There is built in functionality for this:
string otherExe = #"C:\projects\otherExe\bin\Debug\BillsAndStatementsArchiver.exe";
Configuration otherConfig = ConfigurationManager.OpenExeConfiguration(otherExe);
string fileUploadRoot = otherConfig.AppSettings.Settings["fileUploadRoot"].Value;
I searched here for the answer. I'm sorry if this has been asked before (as I suspect it has).
Summary: How can I have strongly typed calls into my web.config without duplicating the property names?
Details: In my code, I try to minimize string usage, and I don't like defining something twice.
Complementing both of these wonts is my restriction of AppSettings usage (and its strings) to one class, which I reference throughout the project. The AppSettings class exposes public properties:
12 public static string DateFormatString {
13 get {
14 return ConfigurationManager.AppSettings["DateFormatString"];
15 }
16 }
How can I keep this class and prevent the duplication (lines 12 & 14) of the property name?
Alternatively, what other solution might you recommend?
I like using Custom Configuration Handlers.
http://haacked.com/archive/2007/03/12/custom-configuration-sections-in-3-easy-steps.aspx
There's no duplication in your example: One DateFormatString is a property name and the other is a string. You're just following a convention which names the property identically to the lookup key for the value.
I do see one possible improvement. You should read the config file once in a static constructor and store the values instead of reading them from AppSettings every time a property is accessed.
I'd probably recommend deserializing the web.config into an object. You can then access all configuration entries as if they were properties (can't get much more strongly typed than that!)
I create a wrapper for everything that doesn't belong to me directly. This includes cache, session, configuration, external web services, etc. This allows me to encapsulate the dirty details of using that widget. In the case of configuration I have a bare bones configuration class that exposes the various properties that I have housed my app.config or web.config. This might look something like this:
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using RanchBuddy.Core.Services.Impl;
using StructureMap;
namespace RanchBuddy.Core.Services.Impl
{
[Pluggable("Default")]
public class ConfigurationService : IConfigurationService
{
internal static int GetDefaultCacheDuration_Days()
{
return Convert.ToInt32(ConfigurationManager.AppSettings["DefaultCacheDuration_Days"]);
}
...
internal static LoggingType GetLoggingType()
{
string loggingType = ConfigurationManager.AppSettings["LoggingType"].ToString();
if(loggingType.ToLower() == "verbose")
{
return LoggingType.Verbose;
}
else if (loggingType.ToLower() == "error")
{
return LoggingType.Error;
}
return LoggingType.Error;
}
...
public static string GetRoot()
{
string result = "";
if(ConfigurationManager.AppSettings["Root"] != null)
{
result = ConfigurationManager.AppSettings["Root"].ToString();
}
return result;
}
}
}
Inside here you can do more than simply get values from the config file. You can convert a string to the type that it needs to be. You can use the string to determine an enum value to be returned. Etc. But the key is that any changes that ever need to be made regarding configuration can be made here. To include if you want to swap out the mechanism for the configuration store!
Build your own ConfigurationSection with the Configuration Section Designer, this way you don't have to use AppSettings at all... but you'll have your own collection of settings that will even have Intellisense in the web.config file.
One solution could be,
public enum Settings
{
None,
DateFormatString,
DefeaultUserPrefix,
SomeOtherValue
}
and then have a helper class like,
public static class ConfigurationHelper
{
public static Get<T>(Settings setting)
{
string output = ConfigurationManager.AppSettings[setting.ToString()];
if(string.isNullOrEmpty(output))
throw new ConfigurationErrorsException("Setting " + setting + " is not defined in Configuration file.");
return (T)output; //You can probably use Convert.* functions.
}
}
Your calling code will look like,
ConfigurationHelper.Get<string>(Settings.DateFormatString);
The above approach provides some level of strong typing but you still have to make sure that the settings name in config file matches with the name of the enum.
The best choice would be to auto-generate class based on the configuration file.
If you wanted strongly typed properties, you can write
public static string DateFormatString
{
get { return ConfigurationHelper.Get<string>(Settings.DateFormatString); }
}
Also, I would advice against reading the config file in constructor (premature optimization?). If you read the config file in constructor, it means that you can not change config file while application is running.
I have written a nuget package that does this (among other things). The accompanying blog post goes in to the details, but this simplified snippet shows the gist of it as related to your question.
public string DateFormatString =>
ConfigurationManager.AppSettings[MethodBase.GetCurrentMethod().Name.Replace("get_", "")];