Override WebConfigurationManager.AppSettings["SomeProperty"] dynamically during execution - c#

I have a code like that:
// can't make any changes at that class
class MyClass
{
void SomeMethod()
{
// some code ...
var someVar = WebConfigurationManager.AppSettings["SomeProperty"];
// some code ...
}
}
I can't change that code, but I need that WebConfigurationManager.AppSettings["SomeProperty"] return different values depending on some external conditions (for example, depending on user role). So I'm looking for some way to override accessing to that property. In that override method I would check user role and
return appropriate value.
Is there any way to do that?
I found that question: Is there a way to override ConfigurationManager.AppSettings? but it seems that it's not suitable for me, because here value of WebConfigurationManager.AppSettings["SomeProperty"] set once when application starts. And I need to do it dynamically.

In MVC, in order to simplify the testing and mocking, I tend to use customized object for all the common classes, like Request, Session and ConfigManager, referenced through interfaces.
You basically don't need to realize classes from scratch obviously, so your implementation can be a wrapper which is actually using the .net class under the hood, but which gives also the chance to insert some custom logic in the middle, like in your case.
Therefore, you can create a wrapper of the webconfigurationManager, with a method like GetAppConfig(key) containing your own logic.
Playing with the concept of dependency injection is then easy enough having this class available wherever you need it.
Therefore to make a simple example:
//this will be injected
public MyControllerCtor(IConfig cfg)
public interface IConfig
{
string GetAppConfig(string key);
}
public class myConfig:IConfig
{
public string GetAppConfig(string key)
{
//your logic
var someVar = WebConfigurationManager.AppSettings["SomeProperty"];
//your logic
return yourCustomAppSetting;
}
}
Big advantage of this approach is that if you wanted to store your config in a database or a service, and change your code, you simply need to change your interface implementation and the inject the new instance.

If you can't change the code that is reading the AppSettings, then there is no way to do what you want. WebConfigurationManager is not pluggable or replacable externally.
You'll have to change the code.

No, of course not.
If you can't change the class, then you can't change the behavior. There's no general reason why Microsoft would have placed an "override" capability inside of WebApplicationManager. Usually, one is expected to be able to change ones class, or else to design it properly so that it can be overridden the right way.

It sounds like you need to do some logic after retrieving the value from the web.config. If the logic modifies the value itself, you could always store a format string in the web.config instead.
Here's an example using a connection string setting. I'm using a format string to populate the server name at runtime:
<add name="sqlconnection" connectionString="Server={0}\SQLEXPRESS;Database=xxx;Trusted_Connection=True;"/>
And then I'm using this logic:
string connect = ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString;
if (!String.IsNullOrEmpty(connect))
{
//check to see if the connection string needs to be set at runtime
if (connect.Contains("{0}"))
connect = String.Format(connect, HttpContext.Current.Server.MachineName);
}
return connect;
EDIT: If you can't edit the class directly, I would consider creating a partial class to implement this.

If you make direct changes to Web.config they will be effective only during the next request, and as I understand, this is not the desired effect.
You can not directly affect WebConfigurationManager.AppSettings["SomeProperty"], and that's the desired behavior, as the AppSettings as configurations are something static.
To achieve an effect close to what you desire, I'd suggest you to use the HttpContext.Current.Items collection, in which you will initialize in Application_BeginRequest to a certain value if conditions are met or default to WebConfigurationManager.AppSettings["SomeProperty"] otherwise.
Than, instead of accessing WebConfigurationManager.AppSettings["SomeProperty"] you will be accessing HttpContext.Current.Items["SomeProperty"].

Related

ASP.NET Core - Add Custom Property to HttpRequest

I have some ASP.NET Middleware that analyzes a request as it comes in. Based on what's available in that HttpRequest, I would like to add a custom property that I can use in my code. My question is, is there a way for me to add a property to HttpRequest so that I can access it in my controller? For example, in my Controller, I would like to do something like this:
namespace MyWebsite.Controllers
{
public class MyController : Controller
public IActionResult Index()
{
if (this.Request.MyProperty == null)
{
return View("~/Views/NoExist.cshtml");
}
return View ("/Views/Index.cshtml");
}
}
MyProperty represents the custom property that I would like to inject, or add, via my custom middleware. Is this possible? If so, how? If not, what is the recommended approach?
Thank you!
The traditional way of achieving what you want is sharing everything via HttpContext.Items. That way you should manage the keys yourself or even can declare your extension methods for conveniently setting & getting the values.
However here I'd like to introduce a new way associated with a new concept request feature in asp.net core. The features associated with each request can be added by different middlewares along the pipeline and can be consumed by any (if available). That looks like neater and more organized, although may not be very convenient compared to the old way.
Suppose you're in the context of your middleware, the following code will add a feature which exposes your property:
//declare the feature interface first
public interface IMyFeature {
string MyProperty {get;}
}
//the concrete type for the feature
public class MyFeature : IMyFeature {
public MyFeature(string myProperty){
MyProperty = myProperty;
}
public string MyProperty {get;}
}
//the context is in your middleware
//add the feature
var myFeature = new MyFeature("value of your choice");
//context here is the HttpContext
context.Features.Set<IMyFeature>(myFeature);
Now anywhere later in the pipeline, you can consume the feature added like this:
//context here is the HttpContext
var myFeature = context.Features.Get<IMyFeature>();
if(myFeature != null){
//consume your feature
}
One point I think the request features concept is good about is its clear definition of feature interfaces which can be learned, referenced and managed easily by your code. Even porting it to some library for reusing makes more sense than depending on some constant key for accessing the shared data (as achieved by using HttpContext.Items). Of course for some simple data sharing, you can just use HttpContext.Items, the request feature should be used when it may evolve later, has a clear cool concept around it and may contain more data.
Create a singleton that has a readonly ConcurrentDictionary property. Alternatively, create a static class with a readonly static property of type ConcurrentDictionary.
Add a readonly Queue property to your global class.
Use the HttpContext.TraceIdentifier as a unique key and add
the data to the ConcurrentDictionary as the value. Also add the HttpContext.TraceIdentifier and DateTime.Now to the Queue property.
Create a clean-up method that removes old data from the Queue and ConcurrentDictionary by pulling data off the Queue until it is under a particular age, say 90 seconds.
Create a background worker that runs periodically and calls the cleanup method. There are libraries that do this. You can also spin off a thread at startup, but this lacks redundancy unless you code it.
Access your data from any called code using the key HttpContext.TraceIdentifier.
Happy Coding!

How to, using dependency injection, get configuration from multiple sources?

I'm using Simple Injector, but maybe what I need is more of a conceptual answer.
Here's the deal, suppose I have an interface with my application settings:
public interface IApplicationSettings
{
bool EnableLogging { get; }
bool CopyLocal { get; }
string ServerName { get; }
}
Then, one would usually have a class which implements IApplicationSettings, getting each field from a specified source, for instance:
public class AppConfigSettings : IApplicationSettings
{
private bool? enableLogging;
public bool EnableLogging
{
get
{
if (enableLogging == null)
{
enableLogging = Convert.ToBoolean(ConfigurationManager.AppSettings["EnableLogging"];
}
return enableLogging;
}
}
...
}
HOWEVER! Let's say I want to get EnableLogging from app.config, CopyLocal from database, and ServerName from another implementation which gets the current computer name. I want to be able to mix-match my app configuration without having to create 9 implementations, one for each combination.
I'm assuming that I can't pass any parameters because the interfaces are resolved by the injector (container).
I thought of this, initially:
public interface IApplicationSettings<TEnableLogging,TCopyLocal,TServerName>
where TEnableLogging : IGetValue<bool>
where TCopyLocal : IGetValue<bool>
where TServerName : IGetValue<string>
{
TEnableLogging EnableLog{get;}
TCopyLocal CopyLocal{get;}
TServerName ServerName{get;}
}
public class ApplicationSettings<TEnableLogging,TCopyLocal,TServerName>
{
private bool? enableLogging;
public bool EnableLogging
{
get
{
if (enableLogging == null)
{
enableLogging = Container.GetInstance<TEnableLogging>().Value
}
return enableLogging;
}
}
}
However, with this I have one main problem: How do I know how to create an instance of TEnableLogging (which is a IGetValue<bool>)? Oh, assume that IGetValue<bool> is an interface which has a Value property, which will be implemented by the concrete class. But the concrete class may need some specifics (like what's the name of the key in app.config) or not (I may simply want to return always true).
I'm relatively new to dependency injection, so maybe I'm thinking in a wrong way. Does anyone have any ideas on how to accomplish this?
(You may answer using another DI library, I won't mind. I think I just need to grab the concept of it.)
You are definitely heading the wrong way here.
Some years ago I built an application that contained an interface much like your IApplicationSettings. I believe I named it IApplicationConfiguration, but it contained all application's configuration values as well.
Although it helped me make my application testable at first, after some time the design started to get in the way. A lot of implementations depended on that interface, but it kept changing a lot and with it the implementation, and the test version.
Just like you I implemented some lazy loading, but this had a terrible down side. When one of the configuration values was missing, I only found out that it did when the value was called for the first time. This resulted in a configuration that was hard to verify.
It took me a couple of iterations of refactoring to find out what the core of the problem was. Big interfaces are a problem. My IApplicationConfiguration class was violating the Interface Segregation Principle and the result was poor maintainability.
In the end I found out that this interface was completely useless. Besides violating the ISP, those configuration values described an implementation detail and instead of making an application wide abstraction, it is much better to supply each implementation directly with the configuration value they need, and only the values they need.
When you do this, the easiest thing to do is to wrap those values into a Parameter Object (even if it is just one value), and inject those configuration values into the constructor. Here's an ecample:
var enableLogging =
Convert.ToBoolean(ConfigurationManager.AppSettings["EnableLogging"]);
container.RegisterSingleton(new LoggerSettings(loggingEnabled: enableLogging));
In this case, LoggerSettings is a configuration object specific to Logger, which requires it as constructor argument.
When doing this, the enableLogging value is read just once from the configuration file and is done so during application startup. This makes it fast and makes it fail at application startup when the value is missing.

C# Proxies and the var keyword

This question is related to a previous post of mine Here. Basically, I want to inject a DAO into an entity i.e.
public class User
{
IUserDAO userDAO;
public User()
{
userDAO = IoCContainer.Resolve<IUserDAO>;
}
public User(IUserDAO userDAO)
{
this.userDAO = userDAO;
}
//Wrapped DAO methods i.e
public User Save()
{
return userDAO.Save(this);
}
}
Here if I had a custom methods in my DAO then I basically have to wrap them in the entity object. So if I had a IUserDAO.Register() I would then have to create a User.Register() method to wrap it.
What would be better is to create a proxy object where the methods from the DAO are dynamically assign to the User object. So I may have something that looks like this:
var User = DAOProxyService.Create(new User());
User.Save();
This would mean that I can keep the User entity as a pretty dumb class suitable for data transfer over the wire, but also magically give it a bunch of DAO methods.
This is very much out of my confort zone though, and I wondered what I would need to accomplish this? Could I use Castles Dynamic proxy? Also would the C# compiler be able to cope with this and know about the dynamically added methods?
Feel free to let me know if this is nonsense.
EDIT:
What we need to do it somehow declare DAOProxyService.Create() as returning a User object -- at compile time. This can be done with generics.
This isnt quite true, what I want to return isn't a User object but a User object with dynamically added UserDAO methods. As this class isn't defnied anywhere the compiler will not know what to make of it.
What I am essentially returning is a new object that looks like: User : IUserDAO, so I guess I could cast as required. But this seems messy.
Looks like what I am looking for is similar to this: Mixins
I was initially going to say what you ask cannot work. But with some tweaking, we might be able to get it to work.
var is just a compiler feature. When you say.
var x = GetSomeValue();
the compiler says "'GetSomeValue' is defined as returning a string, so the programmer must of meant to write 'string x = GetSomeValue();'". Note that the compiler says this; this change is done at compile time.
You want to define a class (DAOProxyService) which essentially returns an Object. This will work, but "var User" would be the same as "Object user".
What we need to do it somehow declare DAOProxyService.Create() as returning a User object -- at compile time. This can be done with generics:
class DAOProxyService
{
static DAOProxyService<T> Create<T>(T obj) { ......}
}
It's not entirely automatic, but you might consider using a variation of Oleg Sych's method for generating decorator classes. Whenever IUserDAO changes (new method, etc) just regenerate the file. Better than maintaining it manually :-)
http://www.olegsych.com/2007/12/how-to-use-t4-to-generate-decorator-classes/

Is it possible to pass a App setting in the web.config to a Common C# class

Is it possible to pass a App setting "string" in the web.config to a Common C# class?
In any class you can use ConfigurationManager.AppSettings["KeyToSetting"] to access any value in the element of web.config (or app.config)
Of course it's possible - but the thing to keep in mind is that a properly designed class (unless it's explicitly designed for ASP.NET) shouldn't know or care where the information comes from. There should be a property (or method, but properties are the more '.NET way' of doing things) that you set with the string value from the application itself, rather than having the class directly grab information from web.config.
If you have configuration values that are used in many places consider developing a Configuration class that abstracts the actual loading of the configuration items and provides strongly typed values and conversions, and potentially default values.
This technique localizes access to the configuration file making it easy to switch implementations later (say store in registry instead) and makes it so the values only have to be read from the file once -- although, I would hope that the configuration manager would be implemented this way as well and read all values the first time it is used and provide them from an internal store on subsequent accesses. The real benefit is strong typing and one-time-only conversions, I think.
public static class ApplicationConfiguration
{
private static DateTime myEpoch;
public static DateTime Epoch
{
get
{
if (myEpoch == null)
{
string startEpoch = ConfigurationManager.AppSettings["Epoch"];
if (string.IsNullOrEmpty(startEpoch))
{
myEpoch = new DateTime(1970,1,1);
}
else
{
myEpoch = DateTime.Parse(startEpoch);
}
}
return myEpoch;
}
}
}

c# properties with repeated code

I have a class with a bunch of properties that look like this:
public string Name
{
get { return _name; }
set { IsDirty = true; _name = value; }
}
It would be a lot easier if I could rely on C# 3.0 to generate the backing store for these, but is there any way to factor out the IsDirty=true; so that I can write my properties something like this and still get the same behaviour:
[MakesDirty]
public string Name { get; set; }
No. Not without writing considerably more (arcane?) code than the original version (You'd have to use reflection to check for the attribute on the property and what not.. did I mention it being 'slower').. This is the kind of duplication I can live with.
MS has the same need for raising events when a property is changed. INotifyPropertyChanged that is a vital interface for change notifications. Every implementation I've seen yet
does
set
{
_name = value;
NotifyPropertyChanged("Name");
}
If it was possible, I'd figure those smart guys at MS would already have something like that in place..
You could try setting up a code snippet to make it easy to create those.
If you really want to go that way, to modify what the code does using an attribute, there are some ways to do it and they all are related to AOP (Aspect oriented programming). Check out PostSharp, which is an aftercompiler that can modify your code in a after compilation step. For example you could set up one custom attribute for your properties (or aspect, how it is called in AOP) that injects code inside property setters, that marks your objects as dirty. If you want some examples of how this is achieved you can check out their tutorials.
But be careful with AOP and because you can just as easily create more problems using it that you're trying to solve if not used right.
There are more AOP frameworks out there some using post compilation and some using method interception mechanisms that are present in .Net, the later have some performance drawbacks compared to the first.
No, when you use automatic properties you don't have any control over the implementation. The best option is to use a templating tool, code snippets or create a private SetValue<T>(ref T backingField, T value) which encapsulates the setter logic.
private void SetValue<T>(ref T backingField, T value)
{
if (backingField != value)
{
backingField = value;
IsDirty = true;
}
}
public string Name
{
get
{
return _name;
}
set
{
SetValue(ref _name, value);
}
}
The other alternative might be a code generator such as codesmith to automate creating the properties. This would be especially useful if the properties you are creating are columns in a database table
I can recommend to use Enterprise Library for that purpose. Policy Application Block delivers the infrastructure to do "something" (something = you can code that on your own) whenever you enter/exit a method for example. You can control the behavior with attributes. Take that as a hint an go into detail with the documentation of enterprise library.
There's a DefaultValueAttribute that can be assigned to a property, this is mainly used by the designer tools so they can indicate when a property has been changed, but, it might be a "tidy" way of describing what the default value for a property is, and thus being able to identify if it's changed.
You'd need to use Reflection to identify property changes - which isn't actually that expensive unless you're doing lots of it!
Caveat: You wouldn't be able to tell if a property had been changed BACK from a non-default value to the default one.
I'd say that the best way of solving this is to use Aspect-Oriented Programming (AOP). Mats Helander did a write up on this on InfoQ. The article is a bit messy, but it's possible to follow.
There are a number of different products that does AOP in the .NET space, i recommend PostSharp.
If you do go with Attributes, I'm fairly certain you'll have to roll your own logic to deduce what they mean and what to do about them. Whatever is using your custom class objects will have to have a way of performing these attribute actions/checks, preferably at instantiation.
Otherwise, you're looking at using maybe events. You'd still have to add the event to every set method, but the benefit there would be you're not hard-coding what to do about dirty sets on every property and can control, in one place, what is to be done. That would, at the very least, introduce a bit more code re-use.
ContextBound object. If you create a class that extends context bound object and you create a ContextAttribute you can intercept the calls made to such a property and set the IsDirty. .NET will create a proxy to your class so all calls go over something like a remoting sink.
The problem with such an approach though is that your proxy will only be invoked when called externally. I'll give you an example.
class A
{
[Foo]
public int Property1{get; set;}
public int Property2{get {return variable;} set{ Property1 = value; variable = value; }
}
When property1 is called from another class, your proxy would be invoked. But if another class calls property2, even though the set of property2 will call into property1 no proxy will be invoked, (a proxy isn't necessary when you're in the class itself).
There is a lot of sample code out there of using ContextBoundObjects, look into it.

Categories

Resources