The requested service 'xyz' has not been registered.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.
7 years ago
Background : Order completed email will get sent to the customer between clicking finish order and then being sent to cybersource to pay for the order, which doesn't look correct to the user (order finished, email sent as completed, but still on cybersource site entering CC info to pay - so not really finished).  Taking the existing SendOrderPlacedCustomerNotification, copying functionality, but triggering after the cybersource payment authorized response message by declaring a new function SendPaymentAuthorizedCustomerNotificationEmail.

(Eventual) Error :  The requested service 'Nop.Plugin.Payments.IngramCyberSource.IngramServices.IngramWorkflowMessageService' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.

CODE :
***********     DependencyRegistrar     *****************
using Autofac;
using Nop.Core.Configuration;
using Nop.Core.Infrastructure;
using Nop.Core.Infrastructure.DependencyManagement;
using Nop.Core.Plugins;
using Nop.Services.Messages;
using System;
using System.Linq;
using Nop.Plugin.Payments.IngramCyberSource.IngramServices;

namespace Nop.Plugin.Payments.IngramCyberSource.Infrastructure
{
    public class DependencyRegistrar : IDependencyRegistrar
    {
        private const string CONTEXT_NAME = "nop_object_context_ingram_cybersource_workflowmessage";

        public int Order
        {
            get
            {
                return 1;
            }
        }

        public void Register(ContainerBuilder builder, ITypeFinder typeFinder, NopConfig config)
        {
            //Is this plugin installed??
            var isInstalled = false;
            var types = typeFinder.FindClassesOfType<IPluginFinder>(true);
            if (types.Count() == 1)
            {
                var plugins = Activator.CreateInstance(types.First()) as IPluginFinder;
                var plug = plugins.GetPluginDescriptorBySystemName("Payments.IngramCyberSource");

                if (plug != null && plug.Installed)
                {
                    isInstalled = true;
                }
            }

            if (isInstalled)
            {
                // register service
                builder.RegisterType<IngramWorkflowMessageService>()
                    .As<WorkflowMessageService>()
                    .InstancePerLifetimeScope();
            }
        }
    }
}


***********     IngramWorkflowMessageService     **********************
using Nop.Services.Messages;
using System;
using System.Collections.Generic;
using Nop.Core;
using Nop.Core.Domain.Messages;
using Nop.Services.Events;
using Nop.Services.Localization;
using Nop.Services.Stores;
using Nop.Core.Domain.Orders;

namespace Nop.Plugin.Payments.IngramCyberSource.IngramServices
{
    public class IngramWorkflowMessageService : WorkflowMessageService
    {
        #region Variables
        private readonly IMessageTokenProvider _messageTokenProvider;
        private readonly IStoreService _storeService;
        private readonly IStoreContext _storeContext;
        private readonly IEventPublisher _eventPublisher;
        #endregion

        #region Constructor
        public IngramWorkflowMessageService(IMessageTemplateService messageTemplateService, IQueuedEmailService queuedEmailService, ILanguageService languageService, ITokenizer tokenizer, IEmailAccountService emailAccountService, IMessageTokenProvider messageTokenProvider, IStoreService storeService, IStoreContext storeContext, EmailAccountSettings emailAccountSettings, IEventPublisher eventPublisher) : base(messageTemplateService, queuedEmailService, languageService, tokenizer, emailAccountService, messageTokenProvider, storeService, storeContext, emailAccountSettings, eventPublisher)
        {
            _messageTokenProvider = messageTokenProvider;
            _storeContext = storeContext;
            _storeService = storeService;
            _eventPublisher = eventPublisher;
        }
        #endregion

        #region Service Overrides/Addons

        internal int SendPaymentAuthorizedCustomerNotification(Order order, int languageId, string attachmentFilePath = null, string attachmentFileName = null)
        {
            if (order == null)
                throw new ArgumentNullException("order");

            var store = _storeService.GetStoreById(order.StoreId) ?? _storeContext.CurrentStore;
            languageId = EnsureLanguageIsActive(languageId, store.Id);

            var messageTemplate = GetActiveMessageTemplate("PaymentAuthorized.CustomerNotification", store.Id);
            if (messageTemplate == null)
                return 0;

            //email account
            var emailAccount = GetEmailAccountOfMessageTemplate(messageTemplate, languageId);

            //tokens
            var tokens = new List<Token>();
            _messageTokenProvider.AddStoreTokens(tokens, store, emailAccount);
            _messageTokenProvider.AddOrderTokens(tokens, order, languageId);
            _messageTokenProvider.AddCustomerTokens(tokens, order.Customer);

            //event notification
            _eventPublisher.MessageTokensAdded(messageTemplate, tokens);

            var toEmail = order.BillingAddress.Email;
            var toName = string.Format("{0} {1}", order.BillingAddress.FirstName, order.BillingAddress.LastName);
            return SendNotification(messageTemplate, emailAccount,
                languageId, tokens,
                toEmail, toName,
                attachmentFilePath,
                attachmentFileName);
        }
        #endregion

        #region Methods

        #endregion
    }
}

*******************     PaymentCyberSourceController     ***********************************
using System.Collections.Generic;
using System.Web.Mvc;
using Nop.Core;
using Nop.Core.Domain.Payments;
using Nop.Core.Domain.Orders;
using Nop.Plugin.Payments.IngramCyberSource.Models;
using Nop.Services.Configuration;
using Nop.Services.Orders;
using Nop.Services.Payments;
using Nop.Services.Logging;
using Nop.Web.Framework.Controllers;
using System.Text;
using System;
using System.Linq;
using Nop.Services.Events;
using Perseus.DataTypes;
using Perseus.Messages;
using Perseus.nopObjects.Messages;
using Perseus.nopObjects.Services;
using Nop.Services.Security;
using Nop.Services.Common;
using Nop.Core.Infrastructure;
using Nop.Plugin.Payments.IngramCyberSource.IngramServices;
using Nop.Services.Messages;
using Autofac;
using System.Web.Compilation;

namespace Nop.Plugin.Payments.IngramCyberSource.Controllers
{
    public class PaymentCyberSourceController : BasePaymentController {
        private readonly ISettingService _settingService;
        private readonly IPaymentService _paymentService;
        private readonly IOrderService _orderService;
        private readonly IOrderProcessingService _orderProcessingService;
        private readonly CyberSourcePaymentSettings _cyberSourcePaymentSettings;
        private readonly PaymentSettings _paymentSettings;
        private readonly ILogger _loggerService;
        private readonly IEncryptionService _encryptionService;
        private readonly IEventPublisher _eventPublishingService;
        private readonly OrderSettings _orderSettings;
        private readonly IPdfService _pdfService;
        private readonly IngramWorkflowMessageService _ingramWorkflowMessageService;



        //TODO test code
        private readonly IComponentContext _con;

#if UseAkka
        private readonly static object ActorSystemKey = new object();
        private static ActorSystem ActorSystem { get; set; }
#endif

        public PaymentCyberSourceController(ISettingService settingService,
                                            IPaymentService paymentService, IOrderService orderService,
                                            IOrderProcessingService orderProcessingService,
                                            CyberSourcePaymentSettings cyberSourcePaymentSettings,
                                            PaymentSettings paymentSettings,
                                            ILogger loggerService,
                                            IEncryptionService encryptionService,
                                            IEventPublisher eventPublishingService) {
            this._settingService = settingService;
            this._paymentService = paymentService;
            this._orderService = orderService;
            this._orderProcessingService = orderProcessingService;
            this._cyberSourcePaymentSettings = cyberSourcePaymentSettings;
            this._paymentSettings = paymentSettings;
            this._loggerService = loggerService;
            this._encryptionService = encryptionService;
            this._eventPublishingService = eventPublishingService;


            //TODO test code
            this._con = EngineContext.Current.Resolve<IComponentContext>();
            var myTYpes1 = _con.ComponentRegistry.Registrations.Where(r => typeof(WorkflowMessageService).IsAssignableFrom(r.Activator.LimitType)).Select(r => r.Activator.LimitType);
            var myTYpes2 = _con.ComponentRegistry.Registrations.Where(r => typeof(IWorkflowMessageService).IsAssignableFrom(r.Activator.LimitType)).Select(r => r.Activator.LimitType);

            // Jed-49 : PaymentAuthorizedEmail
            this._orderSettings = EngineContext.Current.Resolve<OrderSettings>();
            this._pdfService = EngineContext.Current.Resolve<IPdfService>();
            this._ingramWorkflowMessageService = EngineContext.Current.Resolve<IngramWorkflowMessageService>();

#if UseAkka
            if (ActorSystem == null) {
                lock (ActorSystemKey) {
                    if (ActorSystem == null) {
                        try {
                            _loggerService.Information("Creating Cybersource Payment Plugin Actor System...");
                            var config = ConfigurationFactory.ParseString(AkkaConfiguration);
                            ActorSystem = ActorSystem.Create("OrderTransmitter", config);
                            _loggerService.Information("Cybersource Payment Plugin Actor System Created.");
                        } catch (Exception ex) {
                            _loggerService.Error("Exception raised while creating Cybersource Payment Plugin Actor System:", ex);
                            throw;
                        }
                    }
                }
            }
#endif
        }


Although the myTypes variables show the services as expected:
myTYpes1 - myTYpes2 : Results View = Expanding the Results View will enumerate the IEnumerable:
[0] = {Name = "WorkflowMessageService" FullName = "Nop.Services.Messages.WorkflowMessageService"}
[1] = {Name = "IngramWorkflowMessageService" FullName = "Nop.Plugin.Payments.IngramCyberSource.IngramServices.IngramWorkflowMessageService"}

- when it gets to resolving I get:
An error occurred when trying to create a controller of type 'Nop.Plugin.Payments.IngramCyberSource.Controllers.PaymentCyberSourceController'. Make sure that the controller has a parameterless public constructor.

- and digging into the inner exceptions finally shows
The requested service 'Nop.Plugin.Payments.IngramCyberSource.IngramServices.IngramWorkflowMessageService' has not been registered. To avoid this exception, either register a component to provide the service, check for service registration using IsRegistered(), or use the ResolveOptional() method to resolve an optional dependency.
7 years ago
Hello

first of all you did not created interface for IngramWorkflowMessageService service.

so you need to create IIngramWorkflowMessageService and just need to declare the new method that you created named SendPaymentAuthorizedCustomerNotification

After interface is created on dependencyregister of plugin

replace your below code

 
if (isInstalled)
            {
                // register service
                builder.RegisterType<IngramWorkflowMessageService>()
                    .As<WorkflowMessageService>()
                    .InstancePerLifetimeScope();
            }


with below one


if (isInstalled)
            {
                // register service
                builder.RegisterType<IngramWorkflowMessageService>()
                    .As<IIngramWorkflowMessageService>()
                    .InstancePerLifetimeScope();
            }


and then on controller side

declare the variable of interface like
IIngramWorkflowMessageService _IngramWorkflowMessageService;


pass it to constructor and use it wherever it required.

Note: Only the issue is you did not created interface and you tried to resolve directly with service class and directly class can not be resolved by dependency injection. even with direct EngineContext.Current.Resolve<IIngramWorkflowMessageService >() also required the interface not class.

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.