27

I am using ASP.NET Core 1.0.1. I have the following

  • A class library that uses "Microsoft.AspNetCore.Mvc": "1.0.1" in order to develop my controllers:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;

namespace CoreAPIsLibrary.Controllers
{

    [Route("api/[controller]")]
    public class ValuesContoller : Controller
    { 
        public string Get()
        {
            return "value";
        }

        // GET api/values/5
        [HttpGet("{id}")]
        public string Get(int id)
        {
            return "value";
        }

        // POST api/values
        [HttpPost]
        public void Post([FromBody]string value)
        {
        }

        // PUT api/values/5
        [HttpPut("{id}")]
        public void Put(int id, [FromBody]string value)
        {
        }
    }
}

This is my class libray's project.json:

{
  "version": "1.0.0-*",

  "dependencies": {
    "Microsoft.AspNetCore.Mvc": "1.0.1",
    "NETStandard.Library": "1.6.0"
  },

  "frameworks": {
    "netstandard1.6": {
      "imports": "dnxcore50"
    }
  }
}
  • Asp.net core application (Web API Template) that will host my controllers and reference that class library. However, It never hits the break point in the controller. Here is my startup class in the web application:

  using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Reflection;
using CoreAPIsLibrary.Controllers;

namespace APIsHost
{
    public class Startup
    {
        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();
        }

        public IConfigurationRoot Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddMvc()
              .AddApplicationPart(typeof(ValuesContoller).GetTypeInfo().Assembly).AddControllersAsServices();
        }

        // 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(Configuration.GetSection("Logging"));
            loggerFactory.AddDebug();

            app.UseMvc(routes =>
            {
                routes.MapRoute("default", "{controller}/{action}/{id}");
            });
            //app.UseMvc();
        }
    }
}

I also checked if the controller was injected:

enter image description here

So, what is missing?

Hussein Salman
  • 7,806
  • 15
  • 60
  • 98
  • try replacing `typeof(ValuesContoller).GetTypeInfo().Assembly` for `typeof(ValuesContoller).Assembly` – Fabricio Koch Nov 08 '16 at 16:36
  • This is not valid a method or extension. – Hussein Salman Nov 08 '16 at 16:45
  • This method is available for me. Can you update your question with your complete Startup.cs ? – Fabricio Koch Nov 08 '16 at 17:16
  • 1
    Try to insert `[Route("api/[controller]")]` in your controller. Also, try to create a controller in the same assembly of the app to make sure the MVC is working fine. – Fabricio Koch Nov 08 '16 at 17:30
  • I created a controller in the assembly itself, but not was working also. I didn't imagine that. What is the problem? – Hussein Salman Nov 08 '16 at 17:36
  • I added a new asp.net core (web API) project tested a controller in the same assembly, it is working. Then, I deleted the Controllers Folder in the Web App. and then referenced the class library and modified the startup class of the new web. But, it didn't hit the controller yet. So, this is not a routing issue. – Hussein Salman Nov 08 '16 at 17:42
  • I guess you're doing something wrong. I'm gonna post an answer with the steps to make this work. – Fabricio Koch Nov 08 '16 at 18:18

4 Answers4

34

Maybe you're doing something wrong. So, here are the steps to make this work.

  • Create a new project: ASP.NET Core Web Application (.NET Core);
  • Choose the Web API template;
  • Run the project and access the "api/values" to make sure it's working;
  • Add a new project to the solution named ClassLibrary: Class Library (.NET Core);
  • Delete the Class1.cs and create a TestController.cs class;
  • Add the MVC dependency in the project.json from the ClassLibrary project:

    "dependencies": {
      "NETStandard.Library": "1.6.0",
      "Microsoft.AspNetCore.Mvc": "1.0.0"
    },
    
  • Update your TestController.cs to be like this:

    [Route("api/[controller]")]
    public class TestController : Controller{
      [HttpGet]
      public IEnumerable<string> Get() {
        return new string[] { "test1", "test2" };
      }
    }
    
  • Add the reference to ClassLibrary in your WebAPI Project: right-click on "References"->"Add Reference..." or update your project.json like this:

    "dependencies": {
      "Microsoft.NETCore.App": {
        "version": "1.0.0",
        "type": "platform"
      },
      "Microsoft.AspNetCore.Mvc": "1.0.0",
      "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0",
      "Microsoft.AspNetCore.Server.Kestrel": "1.0.0",
      "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.0.0",
      "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0",
      "Microsoft.Extensions.Configuration.Json": "1.0.0",
      "Microsoft.Extensions.Logging": "1.0.0",
      "Microsoft.Extensions.Logging.Console": "1.0.0",
      "Microsoft.Extensions.Logging.Debug": "1.0.0",
      "Microsoft.Extensions.Options.ConfigurationExtensions": "1.0.0",
      "ClassLibrary": "1.0.0-*"
    },
    
  • Update your Startup.cs ConfigureServices method:

    public void ConfigureServices(IServiceCollection services) {
      services.AddMvc().AddApplicationPart(Assembly.Load(new AssemblyName("ClassLibrary")));
    }
    
  • Run the project again and access "api/test";
Fabricio Koch
  • 1,395
  • 12
  • 20
  • Thanks, Fabrico. This is exactly what I did and there is something really wierd on my machine, because I have made a change on my startup, then return it back to the code in my question and now its working, but don't know the reason. – Hussein Salman Nov 08 '16 at 19:23
  • I wish I had found this answer a few hours ago. It would have saved me a lot of time. Sometimes it comes down to the specific search terms. Great job. – IAbstract Aug 15 '20 at 20:30
8

you don't need to do anything special in Startup.cs of the main web app, it just needs to reference the class library.

The one trick is that for your controllers to be discovered your class library must directly reference MVC in its project.json file dependencies section:

"Microsoft.AspNetCore.Mvc": "1.0.*"

UPDATE: for MVC app I did not need anything special in my Startup but in one of my api apps I did need it maybe because using attribute routing.

services.AddMvc()
            .AddApplicationPart(Assembly.Load(new AssemblyName("CSharp.WebLib")))
            ;

where CSharp.WebLib is the name of my class library

Joe Audette
  • 35,330
  • 11
  • 106
  • 99
  • 3
    In Asp.Net Core 6, you no longer need to include `AddApplicationPart(Assembly.Load(new AssemblyName("CSharp.WebLib")))`. It automatically picks up controllers with attribute routing – MikeT Feb 13 '22 at 23:21
0
// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    ...

    services.AddMvc()
        .AddApplicationPart(typeof(Namespace.SubNamespace.ControllerName).Assembly);

    ...
}
Ryan Harlich
  • 157
  • 1
  • 7
  • 1
    That does exactly the same as the other responses, you are returning the full assembly from the type... – Gusman Feb 08 '21 at 10:16
-1

@Fabricio Koch

How does it work on following code, if i publish Enabling Trimming option in dotnet 5.

public void ConfigureServices(IServiceCollection services) {
  services.AddMvc().AddApplicationPart(Assembly.Load(new AssemblyName("ClassLibrary")));
}
Prem
  • 73
  • 1
  • 6