OrchardCMS / OrchardCore

Orchard Core is an open-source modular and multi-tenant application framework built with ASP.NET Core, and a content management system (CMS) built on top of that framework.
https://orchardcore.net
BSD 3-Clause "New" or "Revised" License
7.37k stars 2.38k forks source link

Unable to resolve service for type 'OrchardCore.Email.ISmtpService' #5464

Closed lurumad closed 4 years ago

lurumad commented 4 years ago

Hi folks,

We are try to using Orchard Core in our application in order to use the powerfull of the headless CMS capability but we want to create our REST API with our business with api versioning.

I've attached some PoC using Orchard Core CMS and ASP.NET Core API versioning. When you try to access the administration you receive this error:

InvalidOperationException: Unable to resolve service for type 'OrchardCore.Email.ISmtpService' while attempting to activate 'OrchardCore.Email.Controllers.AdminController'.

We don't know how to resolve this and we think is a common scenario to mix Orchard Core with your own APIs and of course, the problem is related when you add API versioning.

https://1drv.ms/u/s!Aur50_mfTfWQkJJkcYi-sQISfpwV9A?e=BKhPFA

Any ideas, feedback?

lurumad commented 4 years ago

If you enable the Email feature:

orchard

Appear this page.

lurumad commented 4 years ago

If you remove the authentication cookies:

orchard2

deanmarcussen commented 4 years ago

This has been reported before https://github.com/OrchardCMS/OrchardCore/issues/4507

Are you calling `.AddMvc() from your main Startup project?

That maybe causing your issue.

Also refer https://github.com/OrchardCMS/OrchardCore/issues/5389 for an issue in aspnetcore with ApiVersioning

lurumad commented 4 years ago

Nop, you can download the example and test it.

But for the last link we suppose it's a bug from ASP.NET Core Versioning :(

Regards!

lurumad commented 4 years ago

@deanmarcussen

We have cloned the API versioning repo and we made the changes that the issue described. The null reference exception dissapear but doesn't resolve the problem mention before.

Regards!

lurumad commented 4 years ago

If you enable API versioning in your OrchardCore.Cms.Web example:

services
    .AddApiVersioning(version =>
    {
        version.DefaultApiVersion = new ApiVersion(1, 0);
        version.ReportApiVersions = true;
        version.AssumeDefaultVersionWhenUnspecified = true;
        version.UseApiBehavior = true;
    })
    .AddVersionedApiExplorer()
    .AddOrchardCms();

You received this error:

orchard3

Even if you apply the fix mentioned in #5389 for an issue in aspnetcore with ApiVersioning

Regards!

deanmarcussen commented 4 years ago

Are you calling `.AddMvc() from your main Startup project? Nop, you can download the example and test it.

this is essentially exactly what you are doing

            services
                .AddCustomApiVersioning()
                .AddCustomProblemDetails()
                .AddVersionedApiExplorer()
                .AddScoped<IService, Service>();
            services
                 .AddOrchardCms()
                 .AddOrchardCore();

The services need to be loaded in a modular fashion

So either from one of your modules or in your main Startup as part of the .AddOrchardCms() builder, for example

services.AddOrchardCms(builder =>
{
    builder.ConfigureServices(services =>
    {
        services..AddApiVersioning();   
    })
});

Also you don't need to call .AddOrchardCms() and .AddOrchardCore()

jtkech commented 4 years ago

Then, because all is running in a tenant container composed of modules, at the application level you may need to use one of our helpers to register more services as it was done in a module startup.

        services.AddOrchardCms()
            //.AddOrchardCore(); <= Depending on your version you may need this line
            .ConfigureServices(tenantServices =>
            {
                tenantServices.AddApiVersioning();
                ...
            });
lurumad commented 4 years ago

@deanmarcussen @jtkech

Thank you so much for your help guys!

Regards!

ajayvikas commented 4 years ago

I am having exact same problem but I am not able to resolve it. I am making a decoupled web site by following https://orchardcore.readthedocs.io/en/dev/docs/guides/decoupled-cms/. When I access the admin page I receive Unable to resolve service for type 'OrchardCore.Email.ISmtpService' while attempting to activate 'OrchardCore.Email.Controllers.AdminController'.

Here is my startup.cs code

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

namespace WebApplication1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOrchardCms().AddMvc();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }
            else
            {
                app.UseExceptionHandler("/Home/Error");
                // The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
                app.UseHsts();
            }
            app.UseHttpsRedirection();
            app.UseStaticFiles();

            app.UseOrchardCore();
            app.UseRouting();

            //app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllerRoute(
                    name: "default",
                    pattern: "{controller=Home}/{action=Index}/{id?}");
            });
        }
    }
}

Also I noticed one thing if shift the app.UseOrchardCore; to the end of the block (after app.UseEndpoints statement), I get a different error. Unable to resolve service for type 'Microsoft.AspNetCore.Mvc.Localization.IHtmlLocalizer`1[OrchardCore.Email.Controllers.AdminController]' while attempting to activate 'OrchardCore.Email.Controllers.AdminController'.

Please help.

P.S. If I remove the .addMvc(), I don't get the error but then I can't use the MVC features.

deanmarcussen commented 4 years ago

Please try changing your startup to look like this


namespace WebApplication1
{
    public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddOrchardCms()

// removed this should be called by AddOrchardCore
//.AddMvc();

        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
// removed - use the https module 
            app.UseStaticFiles();

            app.UseOrchardCore();

// removed this is called by .UseOrchardCore()
//app.UseRouting();

            // also called by UseOrchardCore()
            //app.UseAuthorization();

            // Removed also, this is configured by Orchard
            // app.UseEndpoints(endpoints =>

        }
    }
}

Then if you want to configure other services @jtkech shows how to do it above.

Basically the problem is you are re registering services that Orchard registers on a modular way

ajayvikas commented 4 years ago

@deanmarcussen thanks for the swift reply. I tried the way you have suggested. The admin starts to work fine but now I am not able to access the MVC feature. What I mean is that when I access http://localhost:port/home/index, asp.net is not able to resolve the route and I get "The page could not be found." error.

deanmarcussen commented 4 years ago

@ppn2 Something like this should work for you

            services.AddOrchardCms()
                .Configure((app, routes, sp) =>
                {
                    routes.MapAreaControllerRoute(
                        name: "TestIndex",
                        areaName: "OrchardCore.Cms.Web",
                        pattern: "Home/Index",
                        defaults: new { controller = "Home", action = "Index" }
                    );
                });

because by default each module, including the startup project is an area. So the default route mapping would be based on the name of your startup project, so like https://localhost:44300/OrchardCore.Cms.Web/Home/Index