#c# #asp.net-core #asp.net-core-webapi #asp.net-core-2.2
#c# #asp.net-core #asp.net-core-webapi #asp.net-core-2.2
Вопрос:
Наше приложение загружает контроллеры во внешние сборки, которые мы называем пакетами. Я хочу создать маршрут, который перенаправляет к пакету, используя URL-адреса, подобные package/BillingPackage/Invoice
, а не api/BillingPackage/Invoice
. Вот что я сделал:
Startup.cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseEndpointRouting()
.UseMvc(routes =>
{
routes.MapRoute(
name: "package",
template: "package/{package}/{controller}/{id?}");
routes.MapRoute("api", "api/{controller}/{action=Get}/{id?}");
routes.MapRoute("default", "{controller=Home}/{action=Index}/{id?}");
});
app.UseStaticFiles();
}
public IServiceProvider ConfigureServices(IServiceCollection services)
{
var source = new PackageAssemblySource(Configuration);
var packageAssemblies = source.Load();
var builder = new ContainerBuilder();
builder.RegisterModule(new WebApiModule(packageAssemblies));
services
.AddMvc()
.ConfigureApplicationPartManager(manager =>
{
// Add controllers and parts from package assemblies.
foreach (var assembly in packageAssemblies)
{
manager.ApplicationParts.Add(new AssemblyPart(assembly));
}
});
.AddControllersAsServices() // Now that AssemblyParts are loaded.
.SetCompatibilityVersion(CompatibilityVersion.Version_2_2);;
builder.Populate(services);
ApplicationContainer = builder.Build();
return new AutofacServiceProvider(ApplicationContainer);
}
Затем я определяю контроллер следующим образом:
[Route("package/BillingPackage/[controller]", Name = "Invoice")]
public class InvoiceController : ControllerBase
{
[HttpGet()]
public ActionResult<Invoice> Get()
{
return new SampleInvoice();
}
}
Даже при всем этом package/BillingPackage/Invoice
выдает значение 404, тогда api/BillingPackage/Invoice
как нет. Как мне заставить мой WebAPI обслуживать конечные точки package
, а не api
?
Комментарии:
1. конфликт маршрута с
template: "package/{package}/{controller}/{id?}"
. Если вы используете атрибутивную маршрутизацию на контроллере, удалите этот маршрут на основе соглашения2. Интересно, но тогда как мне указать имя пакета «BillingPackage», если не с маршрутом на контроллере?
3. Вы уже жестко запрограммировали имя пакета в шаблоне маршрута атрибута
package/BillingPackage/[controller]
4. Да, я понимаю вашу точку зрения, но как контроллеры в пакете могут указывать имя пакета, если не по атрибутам? Как эти контроллеры могут быть связаны с этим именем пакета? Кроме того, RouteData всегда содержит только
{"action":"Get","controller":"Customer"}
вместо значения дляpackage
. Что мне нужно написать, чтобы извлечь это из URL?5. вам нужно будет включить параметр шаблона
[Route("package/{package}/[controller]", Name = "Invoice")]
вместе с аргументом метода / действияpublic ActionResult<Invoice> Get(string package)
, который будет заполняться из соответствующего значения из URL.
Ответ №1:
Вероятно, у вас возник конфликт маршрутов с template: "package/{package}/{controller}/{id?}"
.
Если вы используете атрибутивную маршрутизацию на контроллере, удалите этот маршрут на основе соглашения
Чтобы получить желаемое поведение, вам нужно будет включить параметр шаблона [Route("package/{package}/[controller]", Name = "Invoice")]
вместе с аргументом метода / действия public ActionResult<Invoice> Get(string package)
, который будет заполнен из соответствующего значения из URL.
Например
[Route("package/{package}/[controller]", Name = "Invoice")]
public class InvoiceController : ControllerBase {
//GET package/BillingPackage/Invoice
[HttpGet()]
public ActionResult<Invoice> Get(string package) {
return new SampleInvoice();
}
}
Ссылочная маршрутизация на действия контроллера в ASP.NET Ядро