如何解决无法将路线与正确的动作相匹配
我有一个正在旧ASP.NET MVC上运行的应用程序,我正尝试将其移植到ASP.NET Core 3.1。旧版本可以正常工作,但是在.NET Core版本中,我无法将相同的URL匹配到等效的操作。我在禁用EndpointRouting的情况下使用MVC(AddMvc / UseMvc)。这是所有配置(无显式路由):
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc(o =>
{
o.EnableEndpointRouting = false;
});
}
public void Configure(IApplicationBuilder app,IWebHostEnvironment env)
{
app.UseMvc();
}
}
控制器动作如下:
[ApiController]
[Route("[controller]")]
public class SomeController : ControllerBase
{
[HttpPost]
public ActionResult DoSomething(bool real)
{
return Content("Something Done");
}
[HttpPost]
public ActionResult DoSomethingElse(bool unreal)
{
return Content("Something else done");
}
}
URL(同样可以在.NET MVC中使用)如下:/Some?real=true
这解决了.NET MVC中的DoSomething
操作,没有问题。在ASP.NET Core上,它引发异常:
Microsoft.AspNetCore.Mvc.Infrastructure.AmbiguousActionException: Multiple actions matched. The following actions matched route data and had all constraints satisfied:
netcore.Controllers.someController.DoSomething (netcore)
netcore.Controllers.someController.DoSomethingElse (netcore)
at Microsoft.AspNetCore.Mvc.Infrastructure.ActionSelector.SelectBestCandidate(RouteContext context,IReadOnlyList`1 candidates)
at Microsoft.AspNetCore.Mvc.Routing.MvcAttributeRouteHandler.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Routing.Tree.TreeRouter.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Routing.RouteCollection.RouteAsync(RouteContext context)
at Microsoft.AspNetCore.Builder.RouterMiddleware.Invoke(HttpContext httpContext)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddleware.Invoke(HttpContext context)
但是为什么呢?这怎么会模棱两可?布尔变量的命名方式显然不同,不应有任何混淆。我知道可以通过更改路由或方法名称来修复它,但是我需要在不更改任何底层功能/ route / etc的情况下移植应用程序。
更新:将操作方法简化为具有一个布尔变量(具有不同的变量名称),并且歧义异常仍然发生。
解决方法
但是为什么呢?这怎么会模棱两可?布尔变量的命名方式明显不同,不应有任何混淆。
在this doc中,您将找到:
在Asp.Net Core中,Controller和ApiController类被统一为一个Controller类。 Microsoft决定不再提供一种机制来尝试根据查询字符串查找正确的方法。
要达到ASP.NET Core的要求,您可以尝试实现自定义ActionMethodSelectorAttribute
并将其应用于您的操作,如下所示。
[AttributeUsage(AttributeTargets.Method,AllowMultiple = true)]
public class CheckQueryStingAttribute : ActionMethodSelectorAttribute
{
public string QueryStingName { get; set; }
public bool CanPass { get; set; }
public CheckQueryStingAttribute(string qname,bool canpass)
{
QueryStingName = qname;
CanPass = canpass;
}
public override bool IsValidForRequest(RouteContext routeContext,ActionDescriptor action)
{
StringValues value;
routeContext.HttpContext.Request.Query.TryGetValue(QueryStingName,out value);
if (CanPass)
{
return !StringValues.IsNullOrEmpty(value);
}
return StringValues.IsNullOrEmpty(value);
}
}
应用于操作
[ApiController]
[Route("[controller]")]
public class SomeController : ControllerBase
{
[HttpPost]
[CheckQuerySting("real",true)]
[CheckQuerySting("unreal",false)]
public ActionResult DoSomething(bool real)
{
return Content("Something Done");
}
[HttpPost]
[CheckQuerySting("unreal",true)]
[CheckQuerySting("real",false)]
public ActionResult DoSomethingElse(bool unreal)
{
return Content("Something else done");
}
}
测试结果
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。