我有一个Asp.Net Core MVC
web应用程序,其中我有一个名为AdminUI
的区域。
我的控制器是这样的:
[Area("AdminUI")]
public class ConfigurationController : BaseController
{
public async Task<IActionResult> Client(int? id)
{
if (id == default)
{
var clientDto = _clientService.BuildClientViewModel();
return View(clientDto);
}
var client = await _clientService.GetClientAsync(id.Value);
client = _clientService.BuildClientViewModel(client);
return View(client);
}
}
我也有下面的方法来添加功能,以一些特定的名称前缀整个区域:
public static IEndpointConventionBuilder MapIdentityServer4AdminUI(
this IEndpointRouteBuilder endpoint, string patternPrefix = "/")
{
return endpoint.MapAreaControllerRoute("AdminUI", "AdminUI",
patternPrefix + "{controller=Home}/{action=Index}/{id?}");
}
如果我使用这个:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env,
ILoggerFactory loggerFactory)
{
app.UseRouting();
app.UseEndpoints(endpoint =>
{
endpoint.MapIdentityServer4AdminUI("/myPrefix/");
});
}
我可以通过以下链接访问AdminUI区域:
https://localhost:43000/myPrefix/Configuration/Client
https://localhost:43000/myPrefix/Configuration/Client/2
它工作得很好,但现在我需要限制上面的URL,这是可能的,只能访问方法客户端与id是数字或没有id参数在URL。我不知道如何实现,如果我想保持URL上面的前缀。
我已经尝试了这个解决方案,它不起作用:
[Route("[area]/[controller]/[action]")]
[Route("[area]/[controller]/[action]/{id:int}")]
public async Task<IActionResult> Client(int id)
{
...
}
这工作,我可以只使用ID,如数字和不使用ID,但这破坏了URL,因为它忽略了我上面的前缀。
URL现在是:
https://localhost:43000/AdminUI/Configuration/Client
:
https://localhost:43000/myPrefix/Configuration/Client
我如何实现以下行为?
[Route("[area]/[controller]/[action]")] [Route("[area]/[controller]/[action]/{id:int}")] public async Task<IActionResult> Client(int id) { ... }
问题与上述Route属性有关。
我们都知道,操作要么是常规路由的,要么是属性路由的。在控制器或动作上放置路由使其属性路由。定义属性路由的操作不能通过常规路由到达,反之亦然。控制器上的任何路由属性都会使控制器属性中的所有动作路由。
因此,通过使用上面的代码,它将使用属性routes。试着像下面这样修改你的代码:[Route("myPrefix/[controller]/[action]")]
[Route("myPrefix/[controller]/[action]/{id:int}")]
public async Task<IActionResult> Client(int id)
{
...
}
参考:混合路由:属性路由与常规路由。
此外,你还可以修改路由模板,如下所示:
public static IEndpointConventionBuilder MapIdentityServer4AdminUI(this IEndpointRouteBuilder endpoint, string patternPrefix = "/")
{
return endpoint.MapAreaControllerRoute("AdminUI", "AdminUI",
patternPrefix + "{controller=Home}/{action=Index}/{id:int?}");
}
然后,在控制器中移除Route
属性。
[Area("AdminUI")]
public class ConfigurationController : BaseController
{
public async Task<IActionResult> Client(int? id)
{
...
}
}
编辑
我想说的是:对于整个AdminUI区域使用
endpoint.MapAreaControllerRoute("AdminUI", "AdminUI", patternPrefix + "{controller=Home}/{action=Index}/{id?}")
对于ConfigurationController和action Client使用这个:
endpoint.MapAreaControllerRoute("AdminUI", "AdminUI", patternPrefix + "{controller=Home}/{action=Index}/{id:int?}");
知道如何将这两个设置结合起来吗?
恐怕我们不能这样做(添加两个路由模板:一个用于整个AdminUI区域,另一个用于AdminUI区域的动作方法)。因为,如果我们同时添加它们,如果url不匹配动作方法的路由模板,它会使用区域路由模板。我能想到的唯一方法是为每个动作方法添加多个路由模板,而不是为整个区域添加路由模板。这样的:
endpoint.MapAreaControllerRoute("AdminUI", "AdminUI", patternPrefix + "Home/Index2/{id:int}");
(注意以上路由只适用于Home控制器Index2动作方法。
或使用Route属性。