7

Using GlassMapper 4, Sitecore 8.2 update 3 and Microsoft DI

How do I register the GlassMapper SitecoreService in my Ioc. It requires a Database and Im not entirely clear on how to get that inside my method for registering items in my Ioc:

public class DependencyInjection : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {

        var serviceProvider = serviceCollection.BuildServiceProvider();

        serviceCollection.AddTransient<ISitecoreContext>(provider => new SitecoreContext());
        serviceCollection.AddTransient<IGlassHtml>(provider => new GlassHtml(serviceProvider.GetService<ISitecoreContext>()));
        serviceCollection.AddTransient<IControllerSitecoreContext>(provider => new ControllerSitecoreContext(serviceProvider.GetService<IGlassHtml>()));
        serviceCollection.AddTransient<ISitecoreService>(provider => new SitecoreService(serviceProvider.GetService<ISitecoreContext>().Database));

        serviceCollection.AddGlassMaps("DD.Data*");
        serviceCollection.AddMvcControllers("DD.Web*");
    }
}

This does not work. The database item in null at this point.

2
  • For Glassmapper 5 and Sitecore 9.3 or Sitecore 10 There is a good blog from Corey Smith coreysmith.co/glass-mapper-5-dependency-injection
    – Mamdouh
    Commented Mar 18, 2021 at 20:49
  • Thanks. I used that article to configure this for Sitecore 9.3. this post was particularly about Sitecore 8. ITs different in 8. (9 is way easier to deal with). Commented Mar 19, 2021 at 12:54

4 Answers 4

7

I wanted to add this as the other answers are close, but not 100% IMO.

First - SitecoreContext and SitecoreService have overloaded constructors. So you have to use a factory registration to be able to resolve those. Otherwise you will be dependent the constructor that the container will select, if it is able to select one.

This is how I register the dependencies:

serviceCollection.AddTransient<ISitecoreContext>(provider => new SitecoreContext());
serviceCollection.AddTransient<ISitecoreService>(provider => new SitecoreService(Sitecore.Context.ContentDatabase));
serviceCollection.AddTransient<IControllerSitecoreContext, ControllerSitecoreContext>();
serviceCollection.AddTransient<IGlassHtml, GlassHtml>();

Notice that I'm using factory registrations for ISitecoreContext and ISitecoreService. Also for ISitecoreService, I'm using Sitecore.Content.Database - this makes sure that in a pipeline or other instance where the Sitecore.Context.Database is core, I can still work on content. If you want one dedicated to the core db, you could create another registration for that.

IControllerSitecoreContext and IGlassHtml can just be registered without the factory methods. The container will resolve those dependencies just fine.

2

Since what you want is for Glass to have the current user's Sitecore Context, I believe this is right. I just tested it local and it works.

serviceCollection.AddTransient<ISitecoreService>(provider => new SitecoreService(Sitecore.Context.Database));
1
  • 2
    Yup - that will work, as long as you remember that you will get the core db in any pipelines or background processes. If you want the content database its safer to use Sitecore.Content.Database
    – Richard Seal
    Commented Nov 7, 2017 at 14:58
1

It looks like you are trying to resolve objects from the container when registering.

I think the code you want is the following:

public class DependencyInjection : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
        serviceCollection.AddTransient<ISitecoreContext, SitecoreContext>();
        serviceCollection.AddTransient<ISitecoreService, SitecoreService>();
        serviceCollection.AddTransient<IGlassHtml, GlassHtml>();
        serviceCollection.AddTransient<IControllerSitecoreContext, ControllerSitecoreContext>();


        serviceCollection.AddGlassMaps("DD.Data*");
        serviceCollection.AddMvcControllers("DD.Web*");
    }
}

You don't need to create instances when registering your interfaces/classes in the container, you just need to tell it the interface and the concrete class. The container will create the instance when it is requested from the container.

In the case of the GlassHtml class, you do not need to tell the container how to resolve its constructor args. Since on the first line you have already registered what a ISitecoreContext is, it will automatically recognize this and will resolve an instance of ISitecoreContext to pass in at the same time it resolves the IGlassHtml instance.

2
  • Registering ISitecoreContext and ISitecoreService like that can give you unexpected results depending on the container you use because they both have overloaded constructors and not all containers can handle that. With the MS container is should use the default constructor, but it is much safer to be explicit and tell the container which one to use.
    – Richard Seal
    Commented Nov 7, 2017 at 14:57
  • Are you suggesting this: serviceCollection.AddTransient<ISitecoreContext>(s => new SitecoreContext())? Commented Nov 7, 2017 at 17:20
0

None of those implementations worked for me because I had to use SitecoreService from sitecore pipeline. SitecoreService.Database context was sometimes null or core. To avoid it I had to use that code below:

public class DependencyInjection : IServicesConfigurator
{
    public void Configure(IServiceCollection serviceCollection)
    {
          /* your code */
          serviceCollection.AddScoped<ISitecoreService>(sp => new SitecoreService(Sitecore.Context.ContentDatabase ?? Sitecore.Context.Database ?? Factory.GetDatabase("web")));            
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.