RedirectToRoute выбрасывает исключение: ни один маршрут не соответствует предоставленным значениям, когда я передаю URL как параметр запроса - PullRequest
0 голосов
/ 29 октября 2019

RedirectToRoute выбрасывает InvalidOperationException: ни один маршрут не соответствует предоставленным значениям , когда я передаю значение маршрута из параметра запроса (который является строкой шаблона маршрута), но работает нормально, когда параметр запроса равен нулю.

Я пытаюсь перенаправить на returnUrl, используя RedirectToRoute(routeName, routeValues) после входа в систему, но любая попытка сделать это вызывает InvalidOperationException: ни один маршрут не соответствует предоставленным значениям, , но работает, когда returnUrl равен нулю или пуст.

Здесь я конвертирую шаблон маршрута в имя маршрута, используя FormatRoute(route-template

[Route("/"), HttpGet("account-login/{returnUrl:alpha?}", Name = "account_login"), AllowAnonymous]
        public async Task<IActionResult> Login([FromQuery] string returnUrl = null)
        {
            // Clear the existing external cookie to ensure a clean login process
            await HttpContext.SignOutAsync(IdentityConstants.ExternalScheme);

            return View(new LoginViewModel { ReturnUrl = returnUrl?.FormatRoute() });
        }

Здесь я вхожу в систему и пытаюсь перейти к verify_login_token , но это не удаетсякогда returnUrl имеет значение, но работает, когда он нулевой или пустой.

[AllowAnonymous, HttpPost("account-login/{returnUrl:alpha?}")]
        public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
        {
            if (ModelState.IsValid)
            {
                ResponseHelper response = await context.LoginAsync(mapper.Map<LoginDTO>(model));

                switch(response.Status)
                {
                    case ResultCode.Success:
                        return this.RedirectToLocal(returnUrl ?? "/home_page");
                    case ResultCode.RequiresTwoFactor:
                        return this.RedirectToLocal("/verify_login_token", new { tokenProvider = ConstantHelper.TokenProvider, rememberMe = model.RememberMe, returnUrl }, ResponseHelper.ResponseHandler(response));
                    case ResultCode.UnconfirmedEmail:
                        AuthenticationDTO authentication = response.Data;

                        response = await context.GetUserClaimsAsync(model.EmailAddress);

                        if (response.Status.Equals(ResultCode.Success) && response.Data != null)
                        {
                            string callbackUrl = HtmlEncoder.Default.Encode(Url.Action("ConfirmEmail", "Account", new { userId = authentication.UserId, token = authentication.Token }, Request.Scheme));

                            string recipientName = response.GetData<IList<Claim>>().FirstOrDefault(r => r.Type.Equals("UserName")).Value;

                            response = await context.CreateConfirmationEmailAsync(model.EmailAddress, recipientName, callbackUrl);
                        }
                        break;
                    case ResultCode.Error:
                    case ResultCode.Exception:
                        return this.RedirectToLocal("/account_login", null, ResponseHelper.ResponseHandler(response));
                }
            }

Я пытаюсь перейти к этому методу действия

[AllowAnonymous, HttpGet("verify-login-token/{tokenProvider:alpha}/{rememberMe:bool}/{returnUrl:alpha?}", Name = "verify_login_token")]
        public async Task<IActionResult> VerifyLoginToken(string tokenProvider, bool rememberMe, string returnUrl = null)
        {
            // Require that the user has already logged in via username/password or external login
            ResponseHelper response = await context.GetTwoFactorAuthenticationUserAsync();

            if (!response.Status.Equals(ResultCode.Success))
            {
                this.SetViewErrorMessage(response);

                return View("Error");
            }

            return View(new VerifyLoginTokenVM { TokenProvider = tokenProvider, RememberMe = rememberMe, ReturnUrl = returnUrl });
        }

У меня есть вспомогательная функция, чтобы помочь мнепроверить маршруты

public static IActionResult RedirectToLocal(this Controller context, string routeName, object routeValues = null, ResponseFormat response = null)
        {
            if (!string.IsNullOrEmpty(routeName))
            {
                if (context.Url.IsLocalUrl(routeName))
                {
                    routeName = routeName.Contains("/", System.StringComparison.CurrentCultureIgnoreCase) ? routeName.TrimStart('/') : routeName;

                    if (response != null)
                    {
                        return context.RedirectToRoute(routeName, routeValues).WithResponseData(response);
                    }
                    else
                    {
                        return context.RedirectToRoute(routeName, routeValues);
                    }
                }
            }

            return context.RedirectToRoute("home_page");
        }

Любая попытка перенаправить на URL в returnUrl не удалась: например, следующее: this.RedirectToLocal(returnUrl ?? "/home_page"); не работает. Я добавил вспомогательную функцию для преобразования любого шаблона маршрута в имя маршрута, используя следующий код:

public static string FormatRoute(this string routeTemplate)
        {
            if(string.IsNullOrEmpty(routeTemplate))
            {
                return "/home_page";
            }

            return routeTemplate.Replace("-", "_");
        }

Если returnUrl имеет / create-user-profile , тогда FormatRoute("/create-user-profile") возвращает / create_user_profile

В настоящее время я получаю InvalidOperationException: ни один маршрут не соответствует предоставленным значениям , когда я пытаюсь перенаправить на returnUrl. Я ищу помощи в понимании того, что я сделал не так и как исправить эту ошибку.

1 Ответ

0 голосов
/ 30 октября 2019

RedirectToRoute использует имя маршрута , в то время как вы, кажется, вместо этого передаете url.

A Redirect , который перенаправляет наurl, может быть достаточно для вашего варианта использования.

Редактировать: чтобы включить routeValues в URL, с небольшим переписыванием вы можете использовать QueryString , например:

var uri = "/verify_login_token" + QueryString.Create(new List<KeyValuePair<string, string>>
{
    new KeyValuePair<string, string>("userId", "yourUserId"),
    new KeyValuePair<string, string>("token", "yourToken"),
}).ToUriComponent();
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...