Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ASP.NET Core MVC main project can't reach Controllers in separate assembly

I want to use a separate project to store the Controllers for my test app. Due to how ASP.NET Core is working, you need to call services.AddMvc().AddApplicationPart with the assembly you want to add.

I use Visual Studio 2017 (so no more project.json there)

The problem is I can't reach the assembly I want to include!

I added reference there in my project:

enter image description here

Also, I decided to use polyfill for AppDomian like so (to reach assembly I need):

 public class AppDomain
    {
        public static AppDomain CurrentDomain { get; private set; }

        static AppDomain()
        {
            CurrentDomain = new AppDomain();
        }

        public Assembly[] GetAssemblies()
        {
            var assemblies = new List<Assembly>();
            var dependencies = DependencyContext.Default.RuntimeLibraries;
            foreach (var library in dependencies)
            {
                if (IsCandidateCompilationLibrary(library))
                {
                    var assembly = Assembly.Load(new AssemblyName(library.Name));
                    assemblies.Add(assembly);
                }
            }
            return assemblies.ToArray();
        }

        private static bool IsCandidateCompilationLibrary(RuntimeLibrary compilationLibrary)
        {
            return compilationLibrary.Name == ("TrainDiary")
                || compilationLibrary.Dependencies.Any(d => d.Name.StartsWith("TrainDiary"));
        }
    }

But when I used it there wasonly one assembly in the list (only linked to this project itself, not one with Controllers).

Here is my Startup.cs:

public class Startup
    {

        public IConfigurationRoot Configuration { get; }
        public Startup(IHostingEnvironment env)
        {
            var builder = new ConfigurationBuilder()
                .SetBasePath(env.ContentRootPath)
                .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true)
                .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true)
                .AddEnvironmentVariables();

            Configuration = builder.Build();
        }
        // This method gets called by the runtime. Use this method to add services to the container.
        // For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
        public void ConfigureServices(IServiceCollection services)
        {
            var assemblies = GetAssemblies(); // I tought I will find there Assmbly I need but no

            services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
            services.AddReact();
            services.AddMvc();
            services.AddLogging();
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseReact(config =>
            {
            });

            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

        public List<Assembly> GetAssemblies()
        {
            Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
            List<Assembly> currentAssemblies = new List<Assembly>();

            foreach (Assembly assembly in assemblies)
            {
                if (assembly.GetName().Name.Contains("TrainDiary"))
                {
                    currentAssemblies.Add(assembly);
                }
            }

            return currentAssemblies;
        }

    }

How can I get my project to also lookup controllers in the other project? Why couldn't it see it?

UPD

Tried to make directly like in this exapmle here.

So my code started looks like that:

var controllersAssembly = Assembly.Load(new AssemblyName("TrainDiary.Controllers")); 
services.AddMvc()
        .AddApplicationPart(controllersAssembly)
        .AddControllersAsServices();

And it succeed to get the assembly:

enter image description here

But when I try to call Controller function - it fails!

Controller code:

[Route("Login")]
    public class LoginController: Controller
    {
        [Route("Login/Test")]
        public void Test(string name, string password)
        {
            string username = name;
            string pass = password;
        }
    }

Requests:

enter image description here

UPD2:

For some reason remove Routes helped:

public class LoginController: Controller
    {
        public void Test(string name, string password)
        {
            string username = name;
            string pass = password;
        }
    }

enter image description here

like image 325
DanilGholtsman Avatar asked Jan 30 '23 21:01

DanilGholtsman


1 Answers

So, if sum this up:

1) You need to Add Reference to your separate project with controllers.

2) Configure services (part):

public void ConfigureServices(IServiceCollection services)
{
  var controllersAssembly = Assembly.Load(newAssemblyName("SomeProject.MeetTheControllers"));

  services.AddMvc().AddApplicationPart(controllersAssembly).AddControllersAsServices();
}

3) My configure looks like that (pay attention to UseMvcWithDefaultRoute):

   // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
        {
            loggerFactory.AddConsole();

            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
            }

            app.UseReact(config =>
            {
            });

            app.UseStaticFiles();
            app.UseMvcWithDefaultRoute();
        }

So in my case of controller like this you don't need to put Routes attribute here, just call it by Some/Test url

namespace SomeProject.MeetTheControllers.Test
{
    using Microsoft.AspNetCore.Mvc;

    public class SomeController: Controller
    {
        public void Test(string name, string notname)
        {
            string username = name;
            string nan = notname;
        }
    }
}
like image 133
DanilGholtsman Avatar answered Feb 02 '23 09:02

DanilGholtsman