如何在Asp中限制控制器动作和区域的参数类型.净的核心



我有一个Asp.Net Core MVCweb应用程序,其中我有一个名为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属性。

最新更新