I was wondering how to wire up Castle Windsor in WebForms.
I'm assuming that the second line wires up the controllers in MVC:
// Initialize Windsor
IWindsorContainer container = new WindsorContainer().Install(FromAssembly.This());
ControllerBuilder.Current.SetControllerFactory(new WindsorControllerFactory(container.Kernel));
How do I then wire up WebForms in ASP.NET?
I had a project which I have modified into an identical WebForms setup. Everything works up until the point where I want Castle Windsor to inject ISession into the ASPX page. It simply doesn't and I am under the assumption that the second line of code, above, is what does it for MVC controllers.
I have this in my nHibernate installer, in teh same place on both projects:
container.Register(Component.For<ISession>()
.LifeStyle.PerWebRequest
.UsingFactoryMethod(kernel => kernel.Resolve<ISessionFactory>().OpenSession()));
I had originally assumed this would do it but it is not the case.
I have been stuck on this for days and with very little official documentation on this I am close to ripping my hair out, what's left of it.
I do know the ASP.NET WebForms are not specifically designed to work with dependancy injection but Ninject have done it, albeit with a little hacking, if I can confirm that Castle Windsor is not compatible and/or will no longer support WebForms I will move to something else.
I managed to stuff Castle Windsor in to WebForms using the code here How to use Castle Windsor with ASP.Net web forms? It uses an an attribute to mark where a dependency should be injected in the a WebFrom.
I then used an MVP pattern. Each WebForm had a presenter
public partial class TestPage : UserControl, IShowTestPage
{
[Inject]
public TestPagePresenter Presenter { get; set; }
protected void Page_Load(object sender, EventArgs e)
{
if (IsPostBack) return;
this.Presenter.OnViewInitialized();
}
public string TestMessage
{
get { return litTestMessage.Text; }
set { litTestMessage.Text = value; }
}
}
As the Presenter is resolved form the container, it is then back to normal for wiring up the dependencies
public interface IShowTestPage {
string TestMessage { get; set;}
}
public class TestPagePresenter {
private ISession session;
public TestPagePresenter(ISession session) {
this.session = session;
}
private IShowTestPage view;
public IShowTestPage { set { view = value; } }
public void OnViewInitialized {
TestMessage = session.Query("some database query");
}
}
My solution was based on a great article by Billy McCafferty
Related
I am new to ASP.NET Core. learning new version of .NET Core 2.0 using VS Code. I got stuck while doing creating database using migration. First, it gives an exception of implementation of IDesignTimeDbContextFactory. After solving this, it still gives an exception of
No parameterless constructor defined for this object
Here's my code for DbContextClass:
public VegaDbContext CreateDbContext(string[] args)
{
IConfigurationRoot configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();
var builder = new DbContextOptionsBuilder<VegaDbContext>();
var connectionString =
configuration.GetConnectionString("DefaultConnection");
builder.UseSqlServer(connectionString);
return new VegaDbContext(builder.Options);
}
I had tried a couple of ways when I was experimenting with ef core. I faced similar issues too. Finally I found services working great. First you will need to create your DBContext with the following override constructor:
public VegaDbContext(DbContextOptions<VegaDbContext> options) : base(options)
{
}
In your start up, you can add your context as a service like this:
services.AddDbContext<ApplicationDBContext>(config => {
config.UseSqlServer(Configuration.GetConnectionString("DefaultConnection"));
});
You can read in full detail about how dependency injection works here:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/dependency-injection
This part should help you with the migration. You can perform your migrations using the dotnet ef commands https://learn.microsoft.com/en-us/ef/core/miscellaneous/cli/dotnet.
When using your db context, do ensure that you are using dependency injection so you make full use of the AddDbContext function and keep it DRY.
https://learn.microsoft.com/en-us/aspnet/core/data/ef-mvc/intro
If I were your in your shoes, I look at this document.
Here is the simple DbContext that you can find on this webSite
namespace ContosoUniversity.Data
{
public class SchoolContext : DbContext
{
public SchoolContext(DbContextOptions<SchoolContext> options) : base(options)
{
}
public DbSet<Course> Courses { get; set; }
public DbSet<Enrollment> Enrollments { get; set; }
public DbSet<Student> Students { get; set; }
protected override void OnModelCreating(ModelBuilder modelBuilder)
{
modelBuilder.Entity<Course>().ToTable("Course");
modelBuilder.Entity<Enrollment>().ToTable("Enrollment");
modelBuilder.Entity<Student>().ToTable("Student");
}
}
}
I just got the same error. If you are careful the error description is actually giving you the solution of the problem.
DesignTimeFactoryObject's constructor function should not take parameters.
public class ExampleDesignTimeFactory : IDesignTimeDbContextFactory<YourDBContext>{
public ExampleDesignTimeFactory(){ no constructor or no parameter constructor }
}
I use ASP.NET CORE 3.1 to create the project and it solved
at this moment we are migrating from Entityspaces(Tiraggo) into Servicestack Ormlite.
One point is the way to open and close the DBConnection.
I apologize for the comparission but it is useful for the question. In Tiraggo, inside my wep application, in the global.asax.cs I put this:
protected void Application_Start(object sender, EventArgs e)
{
Tiraggo.Interfaces.tgProviderFactory.Factory = new Tiraggo.Loader.tgDataProviderFactory();
}
In web.config exists the section for Tiraggo, the connectionstring and the ORM does the rest.
During the use of the classes we just do this:
User user = new User(); user.Name="some"; user.Comment = "some"; user.Save();
I dont open, close a DBConnection. It is transparent for the programmer. Just create the instance classes and use them.
I define a class, a repository and that's all. No DB definition or interaction. Everything happens in a webforms app, with the datalayer inside the same app.
When we are migrating to Servicestack ORMLite, I see the open of the DBConnection is too inside the globlal.asax.cs, but it references a Service no a class or repository.
public class AppHost : AppHostBase
{
public AppHost() : base("Hello ServiceStack", typeof(HelloService).Assembly) {}
public override void Configure(Container container) {}
}
So my first question is: how can I use it if I dont have a Service (HelloService), I have just classes or repositories. So I cant use this technique for DBConnection my DB.
I also see that accesing the Db, I need a open connection. I try to do this:
using (var Db = DbFactory.Conn.OpenDbConnection())
{
return Db.SingleById<Anio>(id);
}
Later, I found a sample like I was looking for, the Pluralsight video ".NET Micro ORMs" Steve Mihcelotti, and he just open the connection, but never Close it, never use the "using" syntax.
So my 2 questions are:
1) Is there a way for open the DbFactory(dbConnection) like all the samples using servicestack ormlite, but without using a Services ( I dont use Services, I want to use Ormlite but just with classes and repositories)
2) Is there a way for connnect to the database in each trip to the class or repository without using the "using" syntax, or
3) the only way is the one showed in the Pluralsight video, ie. open the connection throw the using syntax in each Method (trip to the class)
I hope I was clear.
The nice thing about IDbConnectionFactory is that it's a ThreadSafe Singleton which can be safely passed around and referenced as it doesn't hold any resources open itself (i.e. DB Connections).
A lazy pattern which provides a nice call-site API is the RepositoryBase class:
public abstract class RepositoryBase : IDisposable, IRepository
{
public virtual IDbConnectionFactory DbFactory { get; set; }
IDbConnection db;
public virtual IDbConnection Db
{
get { return db ?? (db = DbFactory.OpenDbConnection()); }
}
public virtual void Dispose()
{
if (db != null)
db.Dispose();
}
}
This is the same pattern ServiceStack's Service class uses to provide a nice API that only gets opened when it's used in Services, e.g:
public class MyRepository : RepositoryBase
{
public Foo GetFooById(int id)
{
return Db.SingleById<Foo>(id);
}
}
Note: This pattern does expect that your dependencies will be disposed after use.
Another alternative is to leverage your IOC to inject an Open IDbConnection with a managed lifetime scope, e.g:
container.Register<IDbConnection>(c =>
c.Resolve<IDbConnectionFactory>().OpenDbConnection())
.ReusedWithin(ReuseScope.Request);
The life-cycle of the connection is then up to your preferred IOC.
Without Using an IOC
Whilst it's typically good practice to use an IOC to manage your Apps dependencies and provide loose-coupling, if you don't want to use an IOC you can also make DbFactory a static property, e.g:
public abstract class RepositoryBase : IDisposable
{
public static IDbConnectionFactory DbFactory { get; set; }
IDbConnection db;
public virtual IDbConnection Db
{
get { return db ?? (db = DbFactory.OpenDbConnection()); }
}
public virtual void Dispose()
{
if (db != null)
db.Dispose();
}
}
Which you can just initialize directly on startup, e.g:
protected void Application_Start(object sender, EventArgs e)
{
RepositoryBase.DbFactory = new OrmLiteConnectionFactory(
connectionString, SqlServer.Provider);
}
Note: If you're not using an IOC then you want to make sure that instances of your repository classes (e.g. MyRepository) are disposed of after use.
I'm trying to wrap my head around dependency injection in the Onion Architecture, I've found this solution which uses a dependency resolution layer around the onion. But there is so much going on that I'm completely lost.
So I setup a project to try it out. I like to start off simple, so a simple log entry on a (MVC) controller method would be a good start.
I'd like to use Dynamic Module Loading (kernel.Load("*.dll");) since it comes recommended from the Ninject wiki.
My solution looks like this: (For now)
Solution
- Core.Services
- Infrastructure.Logging
- DependencyResolution
- UI.MVC (default internet template)
I'd like to follow the guides lines for dependency resolution outlined here.
Ilogger
namespace Core.Services
{
public interface ILogger
{
void Log(string message);
}
}
Logging Implementation
namespace Infrastructure.Logging
{
public class DebugLogger : ILogger
{
public void Log(string message)
{
Debug.WriteLine(message);
}
}
}
Dependency Resolution
namespace DependencyResolution
{
public class TestModule : NinjectModule
{
public override void Load()
{
Bind<ILogger>().To<DebugLogger>();
}
}
}
What I want to accomplish
UI
namespace UI.MVC.Controllers
{
public class HomeController : Controller
{
private readonly ILogger _logger;
public HomeController(ILogger logger)
{
_logger = logger;
}
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
_logger.Log("It works!");
return View();
}
}
}
I need to run kernel.Load("*.dll"); somehow and I need to setup my MVC to use DI. I'm just now sure how since the UI cannot know about the Dependency Resolution layer.
Your DI container should be composed somewhere. This place is called the composition root and is the outermost layer. In your case that would be the ASP.NET MVC application. So saying that it should not know about the DI simply doesn't make sense. The Ninject.MVC3 package comes with a custom dependency resolver implementation that gets plugged into the application and you will get automatic DI in your controllers.
The problem I'd like to solve is sharing an ISessionProvider between IXyzRepositories (where ISessionProvider holds the current NHibernate ISession).
I'm tweaking the "Setting up session per presenter" recipe from NHibernate 3 Cookbook, and would like to keep StructureMap (brownfield project).
I think you would have to create a custom Lifecyle to do that, although I am not sure what exactly you are trying to accomplish...
To create a custom Lifecycle, you just have to implement the ILifecycle interface and the use it in your registration. Here is an example you can look at: http://blog.mikeobrien.net/2010/01/creating-structuremap-lifecycle-for-wcf.html.
In a web application I use Singleton for the sessionFactory and HybridHttpOrThreadLocalScoped for the session:
This is my structuremap registry:
public class NhibernateRegistry: Registry
{
public NhibernateRegistry()
{
For<ISessionFactory>()
.Singleton()
.Use(new NHibernateSessionFactory(connectionString).SessionFactory);
For<ISession>()
.HybridHttpOrThreadLocalScoped()
.Use(o => o.GetInstance<ISessionFactory>().CurrentSession);
}
}
My NHibernateSessionFactory is similar to SessionProvider class used in the book.
Everything is disposed at the end of the request (web app):
protected void Application_EndRequest(object sender, EventArgs e)
{
ObjectFactory.ReleaseAndDisposeAllHttpScopedObjects();
}
I use a generic repository:
public class GenericRepository<T> : IGenericRepository<T> where T : class
{
private readonly ISession _session;
public GenericRepository(ISession session)
{
_session = session;
}
public T Load(Guid Code)
{
return (_session.Load<T>(Code));
}
}
but you can easily change it with your own implementation.
I register the repository here:
public class RepositoriesRegistry : Registry
{
public RepositoriesRegistry()
{
For <Data.IRepository<Domain.Reminder, Guid>>()
.HybridHttpOrThreadLocalScoped()
.Use<Data.NH.Repository<Domain.Reminder, Guid>>();
}
}
Although there are many examples of Silverlight projects using MEF (Managed Extensibility Framework), since the System.ComponentModel.Composition.Packaging.Toolkit package was removed in the version that is shipped inside Silverlight 4, these projects are away from helping to run some basic MEF example.
Some tutorials using the newer API will be very beneficial.
Thanks.
Although I can't point you in the direction of a concrete example, it's quite trivial to start composing parts of your Silverlight 4 application. Given the example:
public partial class MainPage : UserControl, IContext
{
[ImportMany]
public IEnumerable<IPlugin> Plugins { get; set; }
public MainPage()
{
InitializeComponent();
CompositionInitializer.SatisfyImports(this);
Plugins.First().Run(this);
}
public void ShowMessage(string message)
{
textBox1.Text = message;
}
}
public interface IContext
{
void ShowMessage(string message);
}
public interface IPlugin
{
void Run(IContext context);
}
[Export(typeof(IPlugin))]
public class SamplePlugin : IPlugin
{
public void Run(IContext context)
{
context.ShowMessage("Hello World");
}
}
The CompositionInitializer type provides SatisfyImports methods which action a default CompositionContainer which is plugged into a catalog that reads parts from your deployed XAP files. If you want more fine grained control over how the catalog is created, you can always create your own CompositionContainer.
Are there any particular aspects of MEF with Silverlight you are looking for advice on?
I wrote a blog post how you can implement MEF into you Silverlight applictaion see
http://www.arrangeactassert.com/solid-design-principles-using-mef-in-silverlight-and-wpf/
I think this is what you are after.