Baldy
Baldy

Reputation: 3659

Consuming non-orchard service classes within Orchard

We have recently developed a library of classes that are used within an MVC3 app internally. The MVC3 app uses Autofac to inject the controllers with the required service classes at runtime. The library uses its own set of tables for data storage that may or may not be in the same database as the host application.

The classes follow the dependency injection pattern, and as an example look something like this (yes, you've seen it a million times before)...

public class PackageService : ServiceBase, IPackageService
{
    private readonly IRepository _db;
    private readonly IClientService _clientSvc;

    public PackageService(IRepository db, IClientService clientService)
    {
        _db = db;
        _clientSvc = clientService;
    }

    public ServiceResult<IEnumerable<Package>> FindPackagesBy(string searchTerm, out int totalRecords, int pageSize, int pageIndex)
    {
        //...
    }

    public ServiceResult<Package> GetPackage(string packageRef)
    {
        //...
    }
}

We would like to consume these classes within modules that run in Orchard CMS. From what i have read on how orchard works it would seem that i need to decorate each class that i intend to use within Orchard with the IDependency interface - which doesnt really seem like a great idea considering this will create a dependency on orchard itself. Our classes manage their own transactions / unit of work, so do not need to be governed by orchards own transaction mechanism. Is this possible? or are we faced with making Orchard specific implementations of our existing library?

Would be good to hear from anyone who has been through this already.

Upvotes: 2

Views: 2308

Answers (2)

Baldy
Baldy

Reputation: 3659

Figured this out myself...

Within the module that consumes the 'external library' you create an Autofac folder, and add a class that inherits from the Autofac Module and add your bindings in there (this is standard procedure for setting up bindings in Autofac) - Orchard will discover this at runtime and inject your module controllers with the required dependencies.

However, the calls to the external library are included within the request transaction by default, as this is how orchard works. Because my library was calling SQL Server via EF4 i was getting an exception 'MSDTC is unavailable on '. You need to explicitly state that you do not want these operations included in the transaction, so your controller ends up looking like this...

[Themed]
public class HomeController : Controller
{
    /* this service is from the external library, 
    which calls its own database */
    private readonly IPackageService _packageSvc;

    /* this dependency is injected, based upon the bindings
    i specified within the Autofac folder at module level */
    public HomeController(IPackageService packageService)
    {
        _packageSvc = packageService;
    }

    public ActionResult Index()
    {
        /* wrap the external lib call so it avoids inclusion
        within the orchard request transaction */
        using (new TransactionScope(TransactionScopeOption.Suppress))
        {
            var package = _packageSvc.GetPackage();
            var model = new HomePageModel()
            {
                Package = package
            };
            return View("ShowPackage", model);
        }

    }
}

Upvotes: 2

Nick Daniels
Nick Daniels

Reputation: 922

Your going to need to take dependency on Orchard and "implement" IDependency to get them injected AFAIK. But that isn't a losing proposition, it doesn't sound to me like making an Orchard specific version is going to be that much work from what you describe, especially if you looking to move the data to Orchard.

Upvotes: 2

Related Questions