2

使用属性路由时,我遇到了不明确的路由问题。问题源于(我相信)在我们的路线根部使用可变参数。让我烦恼的是文字参数似乎没有优先权,而且 MVC5 无法确定使用哪个路由。

我以前在其他路线上遇到过这种情况,并认为我已经通过定义约定路线来解决问题。考虑到这一点,我在哪里可以找到有关属性路由和解决歧义的最佳实践的更多信息?

这是我遇到问题的代码以及异常。

“/”应用程序中的服务器错误。

找到多个与 URL 匹配的控制器类型。如果多个控制器上的属性路由与请求的 URL 匹配,就会发生这种情况。

该请求找到了以下匹配的控制器类型:

帐户控制器

圆形控制器

说明:执行当前 Web 请求期间发生未处理的异常。请查看堆栈跟踪以获取有关错误及其源自代码的位置的更多信息。

异常详细信息:System.InvalidOperationException:找到与 URL 匹配的多个控制器类型。如果多个控制器上的属性路由与请求的 URL 匹配,就会发生这种情况。

该请求找到了以下匹配的控制器类型:

帐户控制器

圆形控制器

路由配置.cs

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    // I added this constraint resolver to resolve some other ambiguous routes that end
    // with a literal, but MVC5 wasn't able to determine whether to use those routes
    var constraintResolver = new System.Web.Mvc.Routing.DefaultInlineConstraintResolver();
    constraintResolver.ConstraintMap.Add("notWriteAction", typeof(IsNotWriteActionConstraint));

    routes.MapMvcAttributeRoutes(constraintResolver);

    // This is the convention route I added to resolve another ambiguous route.
    routes.MapRoute(
        name: "Account",
        url: "Account/{action}/{GroupName}/{AccessToken}",
        defaults: new { controller = "Account", action = "Login", GroupName = UrlParameter.Optional, AccessToken = UrlParameter.Optional }
    );

    routes.MapRoute(
        name: "Default",
        url: "{controller}/{action}/{id}",
        defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );
}

RoundController.cs

public class RoundController : ControllerBase
{
    [Route("{groupid}/{campaignid}/{accesstoken}")]
    public async Task<ActionResult> TempRoundLink(string groupid, string campaignid, string accesstoken)
    {
    }
}

AccountController.cs

public class AccountController : ControllerBase
{
    [AllowAnonymous]
    [Route("Account/ResetPassword/{token}")]
    public async Task<ActionResult> ResetPassword(string token)
    {
    }
}
4

2 回答 2

1

我打算写比这更长的东西,但我没有时间。我最终采用的解决方案是去掉对 Microsoft 属性路由库的任何调用,而是使用此处找到的“属性路由”包。http://htmlpreview.github.io/?https://github.com/mccalltd/AttributeRouting/blob/gh-pages/index.html

它运行良好,*Precedence 属性解决了我在原始问题中遇到的确切问题。

于 2014-04-10T22:22:51.447 回答
1

我知道这不是你要问的,但我认为这可以通过使用RoutePrefix属性来解决。例如

[RoutePrefix("Round")]
public class RoundController : ControllerBase
{
    [Route("{groupid}/{campaignid}/{accesstoken}")]
    public async Task<ActionResult> TempRoundLink(string groupid, string campaignid, string accesstoken)
    {
    }
}

[RoutePrefix("Account")]
public class AccountController : ControllerBase
{
    [AllowAnonymous]
    [Route("Account/ResetPassword/{token}")]
    public async Task<ActionResult> ResetPassword(string token)
    {
    }
}

我认为它试图不做出假设的原因是因为偏好可能并不总是可以确定的。例如,您希望路由器如何解决这两个问题:

Routes (from attributes):
"Account/ResetPassword/{token}"
"Account/{something}/alpha"

Reequest:
"/Account/ResetPassword/alpha"

但这只是一个猜测......

于 2014-03-11T21:22:57.380 回答