I am using MVC 3, I have a range of Controllers depending on various repositories, 1 of my repository relies on the http context session.
I have created interfaces for each of my repositories in order to use the Windsor-Castle IoC.
How can I pass the current session object down to the repository that needs it?
I used to be able to do this and the "Resolve" would take care passing the session to the repository that needed it, somehow I cannot do this in the latest version (2.5.3 Feb 2011):
Protected Overrides Function GetControllerInstance(ByVal requestContext As System.Web.Routing.RequestContext, _
ByVal controllerType As System.Type) As System.Web.Mvc.IController
Dim match As IController
' 1 or more components may need the session,
' adding it as a (possible) dependency
Dim deps As New Hashtable
deps.Add("session", HttpContext.Current.Session)
match = container.Resolve(controllerType, deps)
Return match
End Function
Thanks, Vincent
Look closely at your design. When you look at it functionaly, your repository doesn't really depend on the the session at all, but at some data you store in the session. Create an abstraction over the things you want to extract from the session and let the repository depend on such abstraction. For instance:
public interface IUserProvider
{
int GetCurrentUserId();
}
public class SomeRepository : ISomeRepository
{
private readonly IUserProvider userProvider;
public SomeRepository(IUserProvider userProvider)
{
this.userProvider = userProvider;
}
}
Now you can create the following implementation of that abstraction:
private class HttpSessionUserProvider : IUserProvider
{
public int GetCurrentUserId()
{
return (int)HttpContext.Current.Session["UserId"];
}
}
You can register this concrete type in your IoC configuration.
This is much better, because you don't want to let your repository depend directly on the HTTP session. This makes testing harder and creates a dependency between your repository and a specific presentation technology.
The controller factory's sole responsibility is to create controllers. Not handling sessions or any other dependencies. It's best to just register the session as a separate component and let Windsor autowire it. Remove the 'deps' Hashtable from there and register:
container.Register(Component.For<HttpSessionStateBase>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(() => new HttpSessionStateWrapper(HttpContext.Current.Session)));
Then inject HttpSessionStateBase in your controller.
BTW: controllers already have access to the session, there is no need to do this if you're just injecting the session to controllers.
Related
I'm evaluating asp.net core and .net core and I'm not yet sure about some things. In the past it was possible to configure many components using the web.config out of the box.
To name some examples:
There was the membership-provider and I could implement many providers but I was able ton configure later which provider should be used. This was dependend of the use-case. Now I should use asp.net identity - but I can only find configurations that are performed in sourcecode.
Same for authentication. I can define "CookieAuthentication" and have to set the name, loginpath or the timeout within sourcecode. In the past I was able to set timeout, etc... via web.config.
Is there any way to configure partially these things out of the box from a config-file? Or is this not supported anymore and I have to implement this configuration on my own? In the past this was a really comfortable way.
In ASP.NET Core, Web.config file is used ONLY for IIS configuration, you cannot use it for application configuration, but there are new, better, more flexible configuration options that you can use.
There are multiple configuration sources that you can use, but in this example I'm using json. These examples are from working code in my SimpleAuth project.
You can configure things in startup from configuration files.
First you add a config file in json format that maps to your class. You can see my example class here, and the json file it maps from here
builder.AddJsonFile("simpleauthsettings.json", optional: true);
Then, in the ConfigureServices method you configure your class to be wired up from the config system as shown
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
Then you add an IOptions accessor of your class to the method signature of the Configure method in the Startup.cs
The Dependency Injection will inject it into that method for you so you can use it there to configure things. Specifically I'm setting the cookie authentication scheme and name from my settings object.
The noteworthy part is that you can add whatever you want to the Configure method signature, and as long as it is something that has been registered in the ConfigureServices method, the DI will be able to inject it for you.
public class Startup
{
public Startup(IHostingEnvironment env, IApplicationEnvironment appEnv)
{
var builder = new ConfigurationBuilder()
.AddJsonFile("appsettings.json")
.AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true);
// this file is the custom configuration file to hydrate my settings from
builder.AddJsonFile("simpleauthsettings.json", optional: true);
....
Configuration = builder.Build();
}
public IConfigurationRoot Configuration { get; set; }
public void ConfigureServices(IServiceCollection services)
{
....
services.Configure<SimpleAuthSettings>(Configuration.GetSection("SimpleAuthSettings"));
....
}
// note that the DI can inject whatever you need into this method signature
// I added IOptions<SimpleAuthSettings> authSettingsAccessor to the method signature
// you can add anything you want as long as you register it in ConfigureServices
public void Configure(
IApplicationBuilder app,
IHostingEnvironment env,
ILoggerFactory loggerFactory,
IOptions<SimpleAuthSettings> authSettingsAccessor
)
{
...
// Add cookie-based authentication to the request pipeline
SimpleAuthSettings authSettings = authSettingsAccessor.Value;
var ApplicationCookie = new CookieAuthenticationOptions
{
AuthenticationScheme = authSettings.AuthenticationScheme,
CookieName = authSettings.AuthenticationScheme,
AutomaticAuthenticate = true,
AutomaticChallenge = true,
LoginPath = new PathString("/Login/Index"),
Events = new CookieAuthenticationEvents
{
//OnValidatePrincipal = SecurityStampValidator.ValidatePrincipalAsync
}
};
app.UseCookieAuthentication(ApplicationCookie);
// authentication MUST be added before MVC
app.UseMvc();
}
}
I use StructureMap, EF 4.1/POCO.
Console app supposes to run 2 consequent operations upon some set of data, lets say operation1 and operation2. I set DbContext up as an singleton. This causes problem in operation2 as operation1 left some trash in its DbContext that prevent operation2 works well. In the same time I can not set up DbContext as 'per call' coz operation1 uses 2 repositories sharing the same DbContext passing through their constructor. So ideally I need reinitialize/reset/cleanup DbContext before operation2. Any ideas?
Thanks
Simply use two different contexts. There is no better solution to reset context then creating a new one. If you are fighting with your current architecture simply improve it to support new scenario. Instead of passing context instance pass a context factory which will be able to create you as many context instances as you need. Same with repositories - you can have factory to create a new repository instances on demand.
Edit with example:
Let's suppose that you are using EFv4.1 Update 1. It offers new interface IDbContexFactory<TContext>. You can define your class this way:
public class YourClass
{
private readonly IDbContextFactory<IYourContext> _factory;
public YourClass(IDbContextFactory<IYourContext> factory)
{
_factory = factory;
}
public void Operation1()
{
using (IYourContext context = _factory.Create())
{
RepositoryA repository = new RepositoryA(context);
RepositoryB repository = new RepositoryB(context);
...
}
}
public void Operation2()
{
using (IYourContext context = _factory.Create())
{
RepositoryA repository = new RepositoryA(context);
RepositoryB repository = new RepositoryB(context);
...
}
}
}
This was example where you pass factory for context but you can do the same for repository if you want to.
Here are my questions and then I'll give you the background for them:
I would prefer to use Method 2 as my application design, so is there a way to provide filtering like Method 1 without introducing references to non-business code and without allowing access to the database model in the Core project?
How do you handle code reuse? The namespaces for each object are something like Project.Core.Domain or Project.Core.Services, but if feels weird making the namespace something like CompanyName.Core.Domain when it is not stored in that project. Currently, I'm copying the source code files and renaming namespaces to handle this, but I'm wondering if there is an organizational way to handle this or something else I hadn't thought of?
Technologies I'm using:
ASP.NET MVC 3
Linq-to-SQL
StructureMap
Moq
MSTest
Method 1:
Here's how I used to setup my web projects:
The Data project would contain all repositories, and Linq data contexts. In a repository, I would return a collection of objects from the database using IQueryable.
public IQueryable<Document> List()
{
return from d in db.Documents
select d;
}
This allowed me to setup filters that were static methods. These were also stored in the Data project.
public static IQueryable<Document> SortByFCDN(this IQueryable<Document> query)
{
return from d in query
orderby d.ID
select d;
}
In the service layer, the filter could be applied like this.
public IPagedList<Document> ListByFCDN(int page, IConfiguration configuration)
{
return repository.List().SortByFCDN().ToPagedList(page, configuration.PageSize, configuration.ShowRange);
}
Therefore, the repository would only have to provide a ListAll method that returned all items as an IQueryable object and then the service layer would determine how to filter it down before returning the subset of data.
I like this approach and it made my repositories cleaner while leaving the bulk of the code in the services.
Method 2
Here's how I currently setup my web projects:
Using the Onion Architecture:
Core: Contains business domain model, all interfaces for the application, and the service class implementations.
Infrastructure: Contains the repository implementations, Linq data contexts, and mapping classes to map the Linq database model to the business model.
Since I'm separating my business code from database code, I do not want to add references in the Core project to things like Linq to gain access to IQueryable. So, I've had to perform the filtering at the repository layer, map the database model to the domain model, and then return a collection of domain objects to the service layer. This could add additional methods into my repositories.
This is what I ended up doing:
1) Created a filtering enum object in the Core project.
public enum FilterType
{
SortFCDN
}
2) In the service class (also within the Core project), do something like:
public IPagedList<Document> ListByFCDN(int page)
{
Dictionary<FilterType, object> filters = new Dictionary<FilterType, object>();
filters.Add(FilterType.SortFCDN, "");
return repository.List(page, filters);
}
3) In the repository (under the Infrastructure project):
public IPagedList<Document> List(int page, Dictionary<FilterType, object> filters)
{
//Query all documents and map to the model.
return (from d in db.DbDocuments
select d).Filter(filters).Map(
page,
configuration.Setting("DefaultPageSize", true).ToInt(),
configuration.Setting("DefaultShowRange", true).ToInt());
}
4) Create a filters class in the Infrastructure project:
public static class DocumentFilters
{
public static IQueryable<DbDocument> Filter(this IQueryable<DbDocument> source, Dictionary<FilterType, object> filters)
{
foreach (KeyValuePair<FilterType, object> item in filters)
{
switch (item.Key)
{
case FilterType.SortFCDN:
source = source.SortFCDN();
break;
}
}
return source;
}
public static IQueryable<DbDocument> SortFCDN(this IQueryable<DbDocument> source)
{
return from d in source
orderby d.ID
select d;
}
}
The service layer (Core project) can then decide what filters to apply and pass those filters to the repository (Infrastructure project) before the query executes. Multiple filters can be applied as long as only one per FilterType is applied.
The filters dictionary can hold the type of filter and any value/object that needs to be passed into the filter. New filters can easily be added as well.
I'm new to Castle Windsor, so go easy!!
I am developing an MVC web app and one of my controllers has a dependency on knowing the current request Url.
So in my Application_Start I initialise a WindsorContainer (container below), register my controllers and then try the following...
container.AddFacility<FactorySupportFacility>();
container.Register(Component.For<Uri>().LifeStyle.PerWebRequest.UsingFactoryMethod(() => HttpContext.Current.Request.Url));
However when I run up my web app I get an exception that my controller...
is waiting for the following dependencies:
Keys (components with specific keys)
- uri which was not registered.
The controller it is trying to instantiate has the following signature:
public MyController(Uri uri)
For some reason it is not running my factory method?
However if I change the controller signature to:
public MyController(HttpContext httpContext)
and change the registration to:
container.Register(Component.For<HttpContext>().LifeStyle.PerWebRequest.UsingFactoryMethod(() => HttpContext.Current));
Then everything works a treat!!
What am I missing when trying to register a Uri type? Its seems exactly the same concept to me? I must be missing something!?
Updated:
I have done some more debugging and have registered both the Uri and the HttpContext using the factory methods shown above. I have added both types as parameters on my Controller constructor.
So to clarify I have a both Uri and HttpContext types registered and both using the FactoryMethods to return the relevant types from the current HttpContext at runtime. I also have registered my controller that has a dependency on these types.
I have then added a breakpoint after I have registration and have taken a look at the GraphNodes on the kernal as it looks like it stores all the dependencies. Here it is:
[0]: {EveryPage.Web.Controllers.BaseController} / {EveryPage.Web.Controllers.BaseController}
[1]: {EveryPage.Web.Controllers.WebpagesController} / {EveryPage.Web.Controllers.WebpagesController}
[2]: {System.Web.HttpContext} / {System.Web.HttpContext}
[3]: {Castle.MicroKernel.Registration.GenericFactory1[System.Web.HttpContext]} / {Castle.MicroKernel.Registration.GenericFactory1[System.Web.HttpContext]}
[4]: {System.Uri} / {System.Uri}
[5]: {Castle.MicroKernel.Registration.GenericFactory1[System.Uri]} / {Castle.MicroKernel.Registration.GenericFactory1[System.Uri]}
It looks as though it has registered my Controller and both the types, plus it has the Factories. Cool.
Now if I drill into the WebpagesController and take a look at its dependencies it only has 1 registered:
[0]: {System.Web.HttpContext} / {System.Web.HttpContext}
Now shouldn't this have 2 registered dependencies as it takes a HttpContext and Uri on its constructor??
Any ideas? Am I barking up the wrong tree?
UPDATE3:
There's new extension point in Windsor trunk now that you can use easily for that.
UPDATE2:
Turns out that I was right from the start (well kind of). Uri is a class, but Windsor treats it as a primitive. There are still at least two quick solutions to this:
Wrap the Uri in some kind of IHasUri or something and take dependency on that interface in your controller
public class FooController
{
public IHasUri CurrentUri { get; set; }
public void SomeAction()
{
var currentUri = CurrentUri.GetCurrentUri();
// do something with the uri
}
}
Tell the Windsor you don't want it to treat Uris like some primitive (but like a lady).
You need a IContributeComponentModelConstruction implementation for that:
public class UriIsAServiceNotAParameter:IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
if (model.Service != typeof(UsesUri)) // your controller type here
return;
foreach (var constructor in model.Constructors)
{
foreach (var dependency in constructor.Dependencies)
{
if(dependency.TargetType ==typeof(Uri))
{
dependency.DependencyType = DependencyType.Service;
}
}
}
}
}
and add it to the container:
container.Kernel.ComponentModelBuilder.AddContributor(new UriIsAServiceNotAParameter());
There's also the most correct way of doing this, which means telling Windsor not to register Uris as primitives in the first place, rather than fixing this afterwards, but this would require reaching into the deepest guts of the kernel, and the result is far more code (though a straightforwad one) than the workarounds outlined above.
A database application that I'm currently working on, stores all sorts of settings in the database. Most of those settings are there to customize certain business rules, but there's also some other stuff in there.
The app contains objects that specifically do a certain task, e.g., a certain complicated calculation. Those non-UI objects are unit-tested, but also need access to lots of those global settings. The way we've implemented this right now, is by giving the objects properties that are filled by the Application Controller at runtime. When testing, we create the objects in the test and fill in values for testing (not from the database).
This works better, in any case much better than having all those objects need some global Settings object --- that of course effectively makes unit testing impossible :) Disadvantage can be that you sometimes need to set a dozen of properties, or that you need to let those properties 'percolate' into sub-objects.
So the general question is: how do you provide access to global application settings in your projects, without the need for global variables, while still being able to unit test your code? This must be a problem that's been solved 100's of times...
(Note: I'm not too much of an experienced programmer, as you'll have noticed; but I love to learn! And of course, I've already done research into this topic, but I'm really looking for some first-hand experiences)
You could use Martin Fowlers ServiceLocator pattern. In php it could look like this:
class ServiceLocator {
private static $soleInstance;
private $globalSettings;
public static function load($locator) {
self::$soleInstance = $locator;
}
public static function globalSettings() {
if (!isset(self::$soleInstance->globalSettings)) {
self::$soleInstance->setGlobalSettings(new GlobalSettings());
}
return self::$soleInstance->globalSettings;
}
}
Your production code then initializes the service locator like this:
ServiceLocator::load(new ServiceLocator());
In your test-code, you insert your mock-settings like this:
ServiceLocator s = new ServiceLocator();
s->setGlobalSettings(new MockGlobalSettings());
ServiceLocator::load(s);
It's a repository for singletons that can be exchanged for testing purposes.
I like to model my configuration access off of the Service Locator pattern. This gives me a single point to get any configuration value that I need and by putting it outside the application in a separate library, it allows reuse and testability. Here is some sample code, I am not sure what language you are using, but I wrote it in C#.
First I create a generic class that will models my ConfigurationItem.
public class ConfigurationItem<T>
{
private T item;
public ConfigurationItem(T item)
{
this.item = item;
}
public T GetValue()
{
return item;
}
}
Then I create a class that exposes public static readonly variables for the configuration item. Here I am just reading the ConnectionStringSettings from a config file, which is just xml. Of course for more items, you can read the values from any source.
public class ConfigurationItems
{
public static ConfigurationItem<ConnectionStringSettings> ConnectionSettings = new ConfigurationItem<ConnectionStringSettings>(RetrieveConnectionString());
private static ConnectionStringSettings RetrieveConnectionString()
{
// In .Net, we store our connection string in the application/web config file.
// We can access those values through the ConfigurationManager class.
return ConfigurationManager.ConnectionStrings[ConfigurationManager.AppSettings["ConnectionKey"]];
}
}
Then when I need a ConfigurationItem for use, I call it like this:
ConfigurationItems.ConnectionSettings.GetValue();
And it will return me a type safe value, which I can then cache or do whatever I want with.
Here's a sample test:
[TestFixture]
public class ConfigurationItemsTest
{
[Test]
public void ShouldBeAbleToAccessConnectionStringSettings()
{
ConnectionStringSettings item = ConfigurationItems.ConnectionSettings.GetValue();
Assert.IsNotNull(item);
}
}
Hope this helps.
Usually this is handled by an ini file or XML configuration file. Then you just have a class that reads the setting when neeed.
.NET has this built in with the ConfigurationManager classes, but it's quite easy to implement, just read text files, or load XML into DOM or parse them by hand in code.
Having config files in the database is ok, but it does tie you to the database, and creates an extra dependancy for your app that ini/xml files solve.
I did this:
public class MySettings
{
public static double Setting1
{ get { return SettingsCache.Instance.GetDouble("Setting1"); } }
public static string Setting2
{ get { return SettingsCache.Instance.GetString("Setting2"); } }
}
I put this in a separate infrastructure module to remove any issues with circular dependencies.
Doing this I am not tied to any specific configuration method, and have no strings running havoc in my applications code.