We are trying to migrate from Umbraco 7 to Umbraco 8. And in the process we learned about DI and IoC, and tried to convert it to DI. But we came across an issue we dunno how to handle correctly.
Let's say, we have a layout .cshtml file for all our views. So the layout file do not have a controller assosiated and we wanna use an extension, that use code we already have in some services. What to do?
We made an Extension for the HtmlHelper to render some scripts. Inside this extension we wanna be able to use 2 custom services.
namespace {projectname}.CustomExtention
{
public static class IPublishedContentExtension
{
// IUmbracoHelperService
// IHostingEnvironmentService
public static MvcHtmlString CustomFunction(this HtmlHelper helper, int id)
{
// Just for Fiction
var content = UmbracoHelperService.TypedContent(id);
var path = HostingEnvironmentService.MapPath(content.Url);
...
return new MvcHtmlString(stylesheets);
}
}
}
We already create IHostingEnvironmentService, HostingEnvironmentService, to use in some components and controllers, so we are able to use the logger.
public interface IHostingEnvironmentService
{
DirectoryInfo GetDirectory(string pathAndName);
}
public class HostingEnvironmentService : IHostingEnvironmentService
{
private readonly ILogger _logger;
public HostingEnvironmentService(ILogger logger)
{
_logger = logger;
}
public string MapPath(string pathAndName, bool createIfNotExists = false)
{
try
{
...
}
catch (Exception ex)
{
_logger.Error<HostingEnvironmentService>("Bla bla bla", ex);
}
}
}
We also created IUmbracoHelperService, UmbracoHelperService. To use in some components and controllers, so we were able to use the IUmbracoContextFactory.
public interface IUmbracoHelperService
{
IPublishedContent TypedContent(int id);
}
public class UmbracoHelperService : IUmbracoHelperService
{
private readonly IUmbracoContextFactory _context;
public UmbracoHelperService(IUmbracoContextFactory context)
{
_context = context;
}
public IPublishedContent TypedContent(int id)
{
using (var cref = _context.EnsureUmbracoContext())
{
...
}
}
}
We already install these in an IUserComposer
public class Installer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Register<IHostingEnvironmentService, HostingEnvironmentService>();
composition.Register<IUmbracoHelperService, UmbracoHelperService>();
}
}
But are we able to use it in our CustomExtention or what would be best practice?
this might just be personal preference, but the outcome is that in the view there isn't anything 'getting' services etc - in current project I'm using this instead of the HtmlHelper ExtensionMethods... I'd used in V7.
Anyway the key to it is anywhere you can get the current reference from a service that's registered with DI by using:
using Current = Umbraco.Web.Composing.Current;
Current.Factory.GetInstance<ISiteService>()
How to work with DI in .cshtml razor views
Hi all.
We are trying to migrate from Umbraco 7 to Umbraco 8. And in the process we learned about DI and IoC, and tried to convert it to DI. But we came across an issue we dunno how to handle correctly.
Let's say, we have a layout .cshtml file for all our views. So the layout file do not have a controller assosiated and we wanna use an extension, that use code we already have in some services. What to do?
We made an Extension for the HtmlHelper to render some scripts. Inside this extension we wanna be able to use 2 custom services.
We already create IHostingEnvironmentService, HostingEnvironmentService, to use in some components and controllers, so we are able to use the logger.
We also created IUmbracoHelperService, UmbracoHelperService. To use in some components and controllers, so we were able to use the IUmbracoContextFactory.
We already install these in an IUserComposer
But are we able to use it in our CustomExtention or what would be best practice?
Hi Bo
What I tend to do is create my own version of UmbracoViewPage
There is some WIP documentation in progress here:
https://github.com/umbraco/UmbracoDocs/compare/v8/ServicesPattern?short_path=cf2726d#diff-cf2726d2ea2b6f60e0225ce051876a55
that has the following example of how to do this:
and then in your view
this might just be personal preference, but the outcome is that in the view there isn't anything 'getting' services etc - in current project I'm using this instead of the HtmlHelper ExtensionMethods... I'd used in V7.
Anyway the key to it is anywhere you can get the current reference from a service that's registered with DI by using:
(if you can't inject it via a constructor)
Not sure if that answers your question though!
regards
Marc
Hi Marc.
Thats exactly what we gonna do.
Thanks.
is working on a reply...