I have a .NET Core worker project and want to add a library providing several HTTP endpoints. I have to stay with the worker project, I can't change it to a Web API project. What I have done so far:
<FrameworkReference Include="Microsoft.AspNetCore.App" />
to the item group to gain access to the webbuilder stuff.
public static class IApplicationBuilderExtensions
{
public static IApplicationBuilder AddLibrary(this IApplicationBuilder applicationBuilder)
{
applicationBuilder.UseRouting();
applicationBuilder.UseEndpoints(endpoints => { endpoints.MapControllers(); });
return applicationBuilder;
}
}
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddLibrary(this IServiceCollection services)
{
services.AddMvc(); // this might be not needed
services.AddControllers();
return services;
}
}
public static class KestrelServerOptionsExtensions
{
public static void AddLibrary(this KestrelServerOptions kestrelServerOptions)
{
kestrelServerOptions.ListenLocalhost(5000); // value from config
}
}
[ApiController]
[Route("[controller]")]
public class UsersController : ControllerBase
{
[HttpGet]
public async Task<ActionResult> Test()
{
return Ok();
}
}
Startup
class.
internal class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddLibrary();
}
public void Configure(IApplicationBuilder applicationBuilder)
{
applicationBuilder.AddLibrary();
}
}
Program
class to.
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHostBuilder =>
{
webHostBuilder.UseKestrel(kestrelServerOptions =>
{
kestrelServerOptions.AddLibrary();
}).UseStartup<Startup>();
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
Does someone know what I'm missing?
It is possible for me to Add Web API controller endpoint to Kestrel worker project but it is not possible for me to add web controllers to a library project and call them from the library.
I have a working solution on my computer.
It turns out it's actually really simple. MVC loads ApplicationPart
s from different assemblies. In a normal web application setup, this seems to be picked up properly, even when using Razor Class Libraries. However, when using a worker service and either a library, or a Razor Class Library, it doesn't work, and so the route for your controller isn't registered.
To add the library as an application part, open up the IServiceCollectionExtensions
class you created, and change it to this:
public static class IServiceCollectionExtensions
{
public static IServiceCollection AddLibrary(this IServiceCollection services)
{
services
.AddControllers()
// Notice the assembly is the type of this class, as this
// is the assembly the controller is in.
// You'll have to call this for every assembly you have
// controllers in, except for any controllers
// you might put in your worker service project.
.AddApplicationPart(typeof(IServiceCollectionExtensions).Assembly);
return services;
}
}
Now, starting the app and sending a request to http://localhost:5000/users
will work. I've confirmed this works for both libraries and Razor Class Libraries.
I should also say that controllers in the worker service project itself will work as normal - there is no special setup required for those.
services.AddMvc()
in IServiceCollectionExtensions
. Calling this, without parameters, is the same as calling AddControllersWithViews()
and AddRazorPages()
.Microsoft.AspNetCore.Mvc.Core
package in your library project - mine runs fine just with the framework reference you added. The only package I have in there is for Microsoft.AspNetCore.Server.Kestrel.Core
.First, your question looks identical to the question referenced, and the only difference is the question. So you didn't say why your web controller doesn't work, and what error did you get?
Then, you didn't say which ASP.NET Core version are you using? It is important factor because 2.x and 3.x are different things.
So please update your question to clarify those. In the meantime, I did try your code which is why I post this answer.
I'm using .NET Core 5 RC, and web controller works for me. The only thing I had to deal with is getting Razor views compiled because Sdk.Worker
doesn't compile views by default. When I hit the controller, I got a 500 error saying view cannot be found even though the view is in the correct location. I then used Razor runtime compilation and everything starts working for me.
That's all I have:
Program.cs
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webHost =>
{
webHost.UseKestrel(opt =>
{
opt.ListenLocalhost(5000);
});
webHost.UseStartup<Startup>();
})
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
Startup.cs
class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews().AddRazorRuntimeCompilation();
services.AddRazorPages();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "MyArea",
pattern: "{area:exists}/{controller=Home}/{action=Index}/{id?}");
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
endpoints.MapRazorPages();
});
}
}
TestController.cs
[Area("My")]
[Route("users")]
public class TestController : Controller
{
[Route("")]
public IActionResult Index()
{
return View();
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.