I am new in how to used MVC Pattern in asp.net. In general web Application I have initialize configuration which are common on website level
Like,
public partial class Default : MyBaseClass
{
}
public class MyBaseClass : System.Web.UI.Page
{
public override OnDo()
{
}
}
Please ignore if any spell mistake. In OnDo() function I initialize StoreClass which properties can be access whole application.
This scenario how I achieve in asp.net MVC
You could use the global.asax events
http://www.techrepublic.com/article/working-with-the-aspnet-globalasax-file/5771721
In ASP.Net project, you can place your configuration information in web.config. However, I prefer to place my config in an XML file and deploy it with the ASP.Net to web site. Here is one example to define my configuration class:
public class MyAppConfig {
private static _config = null;
// Configuration is a simple class with a list of properties
public static Configuration Configuration {
if (_config == null ) {
_config = new Configuration();
// parse XMl file and set properties
}
return _config;
}
}
In your case, you can use MyAppConfig to get web application level configuration properties:
public class MyBaseClass : System.Web.UI.Page
{
public override OnDo()
{
Configuration myConfig = MyAppConfig.Configuration;
// use properties ....
}
}
The advantage of placing configuration in your own XML file is that this component can be used in other apps such as console app with very little changes. However, you cannot write changes to the XML file in Web applications. Normally, I place writable information in databases to resolve the issue.
For an event to be triggered before every action, you can do this.
Define a base controller and use it for all your controllers.
public class BaseController : Controller
{
protected override void OnActionExecuting(ActionExecutingContext context)
{
}
}
Your controllers will look like this:
public class MyController : BaseController
OnActionExecuting will get fired before each action
For a session level or application level event, you should use global.asax
Related
I have an httphandler like this:
public class MyProxy : IHttpHandler
{
public MyProxy() { }
public void ProcessRequest(HttpContext context)
{
//do something
}
}
I want to be able to inject a service (KeyVaultService) so I can move some app settings that are sitting in the web.config to the key vault. However, when I inject the KeyVaultService the MyProxy is no longer hit. I'm assuming this is how httpHandlers work, so why is this and is there some way round this (both generally and specifically for a KeyVaultService)? For this case could I create SecretClient?
There are plenty of examples how to set controllers to use services etc. But what about plain old class? Lets use some simple configuration service
JSON
{
....,
"AppSettings": {
"SchemaFile": "some file name.xml"
}
}
POCO
public class AppSettings
{
public string SchemaFile { get;set; }
}
In startup.cs
public void ConfigureServices(IServiceCollection services)
{
IConfigurationSection appSettingsSection = Configuration.GetSection("AppSettings");
services.Configure<AppSettings>(appSettingsSection);
. . . .
}
This is the point where all examples move directly to the controller. But we are going to have plenty of code outside controller. What I need is to access this service using provider.GetService(typeof(T)) or provider.GetRequiredService(typeof(T)), from, lets say a static class
internal static MyClass
{
internal static void DosomeThing()
{
// acquire my service
// use it to retrieve some value
// continue with my logic
}
}
Thanks
Just as the services can be injected into controllers, so too can they be injected into other classes.
static classes however to not lend themselves well to dependency injection by default.
Instead of using a static class, make a regular class and explicitly depend on the desired service via constructor injection
internal class MyClass : IMyService {
readonly AppSettings settings;
public MyClass(AppSettings settings) {
this.settings = settings;
}
internal void DosomeThing() {
// retrieve some value from settings
// continue with my logic
}
}
You can then register your desired POCO and utilities with the service container
public void ConfigureServices(IServiceCollection services) {
AppSettings appSettings = Configuration.GetSection("AppSettings").Get<AppSettings>();
services.AddSingleton(appSettings);
services.AddSingleton<IMyService, MyClass>();
//. . . .
}
Inject your service where it is needed and it will have access to the POCO when being resolved for injection.
There really is no need to be passing IServiceProvider around as that can be seen as a code smell.
Simplifying your design to follow explicit dependency principle should make your code more SOLID and easier to follow and maintain.
You should pass AppSettings as parameter from the caller method
public class HomeController : Controller
{
public HomeController(AppSettings settings)
{
this.Settings = settings;
}
private AppSettings Settings { get; }
public IActionResult Index()
{
MyClass.DosomeThing(this.Settings);
}
}
internal static MyClass
{
internal static void DosomeThing(AppSettings settings)
{
// acquire my service
// use it to retrieve some value
// continue with my logic
}
}
I am working with the web application and I have a class which have all the business logic which implement Interface. I am trying to referenced Interface and class in startup.cs and trying to initialise in Controller. My business logic class is like this:
public class User_MasterDataAccesss: IUserMasterRepository
{
.... business logic
public int validate(string name)
{
...... doing something
}
}
I have an interface which have definition for the validate function like this
public interface IUserMasterRepository
{
int validate(string name);
}
I am trying to bind the interface in startup.cs like this
public partial class Startup
{
public void Configuration(IAppBuilder app)
{
ConfigureAuth(app);
}
public void ConfigureServices(IServiceCollection services)
{
// Add framework services.
// services.AddMvc();
// Add application services.
services.AddSingleton<IUserMasterRepository, User_MasterDataAccesss>();
}
}
and I am trying to initialise the interface in controller like this
public class AuthenticationController : Controller
{
private IUserMasterRepository UserMasterRepository;
public AuthenticationController() { }
public AuthenticationController(IUserMasterRepository userMasterRepository)
{
this.UserMasterRepository = userMasterRepository;
}
......... action result actions which is using the UserMasterRepository
}
My problem is as follows:
Constructor is not executing and as a result UserMasterRepository is null when accessing from action.
services.AddMvc(); in startup.cs is doesnot exist
I know I can achieve my requirement by using Ninject but I want to use startup.cs file for that matter
I do not want to use new key word in controller.
How can I achieve this? Where I am wrong?
Installing ASP.NET 5 runtime and tooling solve my problem.
I'm currently trying to work with dependency injection and so far I love. But it's one thing I can't really get my head around and where my current solution just seems wrong.
I'm working with WPF, MVVM and many of the classes I inject need an instance of a project configuration class that isn't initialized until the user create or open a new project in the application.
So my current solution is to have a "ConfigurationHandler" with load/save method and a property that hold an instance of the configuration class after it's loaded. I inject ConfigurationHandler to the others classes and then they can access the configuration after it's loaded. But it seems weird to let classes that never should save/load configuration handle the whole "ConfigurationHandler" and 100% they would just use it to access the configuration instance likt this:
var configuration = configurationHandler.Configuration;
Another problem is that if they try to access the configuration before it's loaded they will get exception (should not really happen as you can't do anything before a project is created/loaded, but still).
But the only other solution I can think of is to use "intialize" methods after a project is created/open but that seems just as bad.
So how do you usually handle cases like this?
Edit: Should add that this configuration class handle information like project path, project name, etc so have nothing to do with the dependency injection itself.
If your configuration is static (read: It's only read during startup of your application, such as from project.json or Web.Config), you can also set it during app startup/the composition root.
The new ASP.NET 5 uses it heavily and it works very well. Basically you will have an IConfiguration<T> interface and a POCO class, which you set up during the app startup and can resolve/inject it into your services.
public interface IConfiguration<T> where T : class
{
T Configuration { get; }
}
And it's default implementation
public interface DefaultConfiguration<T> where T : class
{
private readonly T configuration;
public T Configuration {
return configuration;
}
public DefaultConfiguration<T>(T config)
{
this.configuration = this.configuration;
}
}
And your POCO class
public class AppConfiguration
{
public string OneOption { get; set; }
public string OtherOption { get; set; }
}
In your composition root, you would then register it, like
// read Web.Config
Configuration rootWebConfig = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(null);
container.AddSingleton<IConfiguration<AppConfiguration>>(new DefaultConfiguration<AppConfiguration>(
new AppConfiguration
{
OneOption = rootWebConfig.AppSettings.Settings["oneSetting"],
OtherOption = rootWebConfig.AppSettings.Settings["otherSetting"],
})
);
And finally, all you have to declare in your services is
public class MyService : IMyService
{
public MyService(IUserRepository, IConfiguration<AppConfiguration> appConfig)
{
...
if(appConfig.OneOption=="someValue") {
// do something
};
}
}
Finally you can make this a bit easier to configure, if you write an extension method like
public static class MyContainerExtension
{
public static void Configure<T>(this IMyContainer container, Action<T> config) where T : class, new()
{
var t = new T();
config(t);
container.AddSingelton<IConfiguration<T>>(t);
}
}
Then all you need to do is
container.Configure<AppConfiguration>(
config =>
{
config.OneOption = rootWebConfig.AppSettings.Settings["oneSetting"],
config.OtherOption = rootWebConfig.AppSettings.Settings["otherSetting"],
})
);
to set it up
Instead of Constructor Injection, consider using an Ambient Context approach.
The last type of DI we’ll discuss is making dependencies available
through a static accessor. It is also called injection through the
ambient context. It is used when implementing cross-cutting concerns.
This is a good option if the classes that need access to your configuration are of different types in different layers or libraries - i.e. is a true cross-cutting concern.
(Quote source)
Example, based on the classic Time Provider one from [Dependency Injection in .NET][2]
abstract class CustomConfiguration
{
//current dependency stored in static field
private static CustomConfiguration current;
//static property which gives access to dependency
public static CustomConfiguration Current
{
get
{
if (current == null)
{
//Ambient Context can't return null, so we assign a Local Default
current = new DefaultCustomConfiguration();
}
return current;
}
set
{
//allows to set different implementation of abstraction than Local Default
current = (value == null) ? new DefaultCustomConfiguration() : value;
}
}
//service which should be override by subclass
public virtual string SomeSetting { get; }
}
//Local Default
class DefaultCustomConfiguration : CustomConfiguration
{
public override string SomeSetting
{
get { return "setting"; }
}
}
Usage
CustomConfiguration.Current.SomeSetting;
There are other DI Patterns that could be used, but require changes to the class that need it. If Configuration is a cross cutting concern Ambient Context could be the best fit.
Constructor Injection Example
public SomeClass(IConfiguration config)
{
}
Property Injection
public SomeClass()
{
IConfiguration configuration { get; set; }
}
Method Injection
public SomeClass()
{
public void DoSomethingNeedingConfiguation(IConfiguration config)
{
}
}
There is also Service Locator, but Service Locator is (IMO) an anti-pattern.
In my MVC application I defined two interfaces: IQueryMappingsConfigurator and ICommandMappingsConfigurator. Those two interfaces are used for supplying EntityFramework mappings for query and command contexts.
In the same solution I have two services: IMembershipService and IMessagingService; for each of those services there is a Registry specifying implementations for ICommandMappingsConfigurator and IQueryMappingsConfigurator:
// In Services.Membership project
public class MembershipRegistry : Registry
{
public MembershipRegistry()
{
For<ICommandMappingsConfigurator>()
.Use<MembershipCommandMappingsConfigurator>();
For<IQueryMappingsConfigurator>()
.Use<MembershipQueryMappingsConfigurator>();
For<IMembershipService>()
.Use<MembershipService>();
}
}
// In Services.Messaging project
public class MessagingRegistry : Registry
{
public MessagingRegistry()
{
For<ICommandMappingsConfigurator>()
.Use<MessagingCommandMappingsConfigurator>();
For<IQueryMappingsConfigurator>()
.Use<MessagingQueryMappingsConfigurator>();
For<IMessagingService>()
.Use<MessagingService>();
}
}
Each service has a dependency on both IQueryMappingsConfigurator and ICommandMappingsConfigurator.
IMembershipService and IMessagingService are used by controllers in the MVC project:
public class MessageController : Controller
{
public MessageController(IMessagingService service){ }
}
public class MembershipController : Controller
{
public MembershipController(IMembershipService service){}
}
How can I configure the StructureMap container so that when a dependency for IMessagingService is required it will load the proper implementation for ICommandMappingsConfigurator and IQueryMappingsConfigurator?
I've tried using a custom registration convention like this:
public class ServiceRegistrationConvention : IRegistrationConvention
{
public void Process(Type type, Registry registry)
{
if (IsApplicationService(type))
{
registry.Scan(_ =>
{
_.AssemblyContainingType(type);
_.LookForRegistries();
});
}
}
}
However, when I try accessing an action method from MessageController I get the error
There is no configuration specified for IMessagingService
When I debug the application I can see the Process method being hit with the type of IMessagingService.
The correct way to compose your application is to make a composition root. If you indeed have one (which isn't clear from your question), this step is done only 1 time per application start so there is no way to change the DI configuration's state during runtime (or at least you should assume there is not). It doesn't matter if the dependencies are in different application layers, they will overlap if they use the same interface.
Before you change your DI configuration, you should check whether you are violating the Liskov Substitution Principle. Unless you really need the ability to swap the MembershipCommandMappingsConfigurator and MessagingCommandMappingsConfigurator in your application, a simple solution is just to give each a different interface (in this case IMembershipCommandMappingsConfigurator and IMessagingCommandMappingsConfigurator).
If you are not violating the LSP, one option is to use generics to disambiguate the dependency chain.
public class MyRegistry : Registry
{
public MyRegistry()
{
For(typeof(ICommandMappingsConfigurator<>))
.Use(typeof(CommandMappingsConfigurator<>));
For(typeof(IQueryMappingsConfigurator<>)
.Use(typeof(QueryMappingsConfigurator<>));
For<IMessagingService>()
.Use<MessagingService>();
For<IMembershipService>()
.Use<MembershipService>();
}
}
public class CommandMappingsConfigurator<MessagingService> : ICommandMappingsConfigurator<MessagingService>
{
// ...
}
public class QueryMappingsConfigurator<MessagingService> : IQueryMappingsConfigurator<MessagingService>
{
// ...
}
public class MessagingService
{
public MessagingService(
ICommandMappingsConfigurator<MessagingService> commandMappingsConfigurator,
IQueryMappingsConfigurator<MessagingService> queryMappingsConfigurator)
{
// ...
}
}
public class CommandMappingsConfigurator<MembershipService> : ICommandMappingsConfigurator<MembershipService>
{
// ...
}
public class QueryMappingsConfigurator<MembershipService> : IQueryMappingsConfigurator<MembershipService>
{
// ...
}
public class MembershipService
{
public MembershipService(
ICommandMappingsConfigurator<MembershipService> commandMappingsConfigurator,
IQueryMappingsConfigurator<MembershipService> queryMappingsConfigurator)
{
// ...
}
}
Another option - in StructureMap you can used smart instances in the configuration to specify exactly what instance goes where, so at runtime you can have different implementations of the same interface.
public class MembershipRegistry : Registry
{
public MembershipRegistry()
{
var commandMappingsConfigurator = For<ICommandMappingsConfigurator>()
.Use<MembershipCommandMappingsConfigurator>();
var queryMappingsConfigurator = For<IQueryMappingsConfigurator>()
.Use<MembershipQueryMappingsConfigurator>();
For<IMembershipService>()
.Use<MembershipService>()
.Ctor<ICommandMappingsConfigurator>().Is(commandMappingsConfigurator)
.Ctor<IQueryMappingsConfigurator>().Is(queryMappingsConfigurator);
}
}
public class MessagingRegistry : Registry
{
public MessagingRegistry()
{
var commandMappingsConfigurator = For<ICommandMappingsConfigurator>()
.Use<MessagingCommandMappingsConfigurator>();
var queryMappingsConfigurator = For<IQueryMappingsConfigurator>()
.Use<MessagingQueryMappingsConfigurator>();
For<IMessagingService>()
.Use<MessagingService>();
.Ctor<ICommandMappingsConfigurator>().Is(commandMappingsConfigurator)
.Ctor<IQueryMappingsConfigurator>().Is(queryMappingsConfigurator);
}
}
You can also use named instances, but smart instances have compile-time type checking support which makes them easier to configure.
There is no reason to use .Scan (which uses Reflection) to configure the registries, unless your application has some kind of plugin architecture. For a normal application with multiple layers, you can configure them explicitly.
var container = new Container();
container.Configure(r => r.AddRegistry<MembershipRegistry>());
container.Configure(r => r.AddRegistry<MessagingRegistry>());