ASP.NET MVC Login ReturnUrl всегда NULL?

Используя проверку подлинности с помощью форм в ASP.NET MVC при попытке снова войти на сайт, он помещает параметр ReturnUrl в строку запроса. Метод действия My Logon принимает строку returnUrl. Однако кажется, что строка returnUrl всегда равна нулю, даже если она явно присутствует в строке запроса. Есть мысли о том, почему это может быть так или о возможном исправлении?


person aherrick    schedule 06.05.2009    source источник
comment
На самом деле это сделано специально. Параметр returnUrl заполняется автоматически только тогда, когда вы пытаетесь получить доступ к авторизованному ресурсу, но не прошли аутентификацию или авторизацию. см. github.com/aspnet/Templates/issues/420. Вы можете использовать подход @davewasthere (или с помощью Tag Helper), если вы хотите, чтобы returnUrl был установлен для случаев без авторизации.   -  person RickAndMSFT    schedule 03.03.2016


Ответы (5)


Может быть, вы не включаете параметр ReturnURL в атрибут действия формы входа в систему, тем самым отправляя сообщение по URL-адресу без этого параметра?

person Çağdaş Tekin    schedule 06.05.2009
comment
Не уверен, что понимаю. Вы говорите, что думаете, что я не включаю параметр ReturnURL в действие на контроллере? - person aherrick; 06.05.2009
comment
Нет, я имел в виду атрибут действия тега HTML-формы. У вас может быть строка запроса ReturnURL на странице входа. Но если форма входа отправляет его без этого параметра строки запроса, он теряется. - person Çağdaş Tekin; 06.05.2009
comment
Хм ... Нет, в коде я явно не устанавливаю ReturnURL для любого сообщения формы. Он автоматически создается структурой в строке запроса. - person aherrick; 06.05.2009
comment
Установите точку останова внутри рассматриваемого метода действия, затем проверьте свойство Request.RawUrl. Вероятно, отсутствует сегмент строки запроса? ReturnUrl = ..., указывающий на то, что ваша форма отправляет сообщение в ‹form action = / Account / Login /›, а не в ‹form action = / Account / Login? ReturnUrl = ... /›. - person Levi; 06.05.2009
comment
Не знаете, почему? ReturnUrl = должен явно присутствовать в атрибуте действия формы. Разве демонстрационный проект MVC не использует Html.Beginform () для автоматической отправки сообщений в Account / Logon? - person aherrick; 06.05.2009
comment
Да, Html.BeginForm () отправит сообщение обратно на текущий URL-адрес, но вам нужно убедиться, что (а) вы действительно вызываете BeginForm () вместо другой перегрузки, (б) исходный URL-адрес содержит? ReturnUrl =. ..параметр, (c) что-то не написано с ошибками и т. д. Но психическая отладка сложна, и было бы гораздо полезнее установить точку останова в методе действия, проверить свойства, связанные с URL-адресом объекта Request, и работать назад, чтобы попытаться понять, что не так. - person Levi; 06.05.2009
comment
+1 только что наткнулся на эту проблему, и этот ответ помог мне ее исправить - person Adam Ralph; 05.06.2009
comment
@Jon, вот так: ‹form action = your-url? ReturnUrl =‹% = Request.QueryString [ReturnUrl]% ›method = post› - person Çağdaş Tekin; 15.06.2009

Это обычно происходит, когда вы используете одну общую форму входа, но вы явно указываете Controller и ActionMethod (что вызывает публикацию формы, но теряет строку запроса)

Чтобы уточнить, вот как должен выглядеть ваш код в вашей BeginForm:

Html.BeginForm("LogOn", "Account", new { ReturnUrl = Request.QueryString["ReturnUrl"] })

РЕДАКТИРОВАТЬ: Это сделано специально, как упоминает RickAnd в комментариях ниже. Однако он не позволяет шаблону пользовательского интерфейса находиться в глубине сайта, нажимать «Вход в систему», а затем возвращаться на страницу, на которой вы были ранее, если это позволяет анонимным пользователям. Это часто запрашиваемый шаблон. Подход Дэвида Аллена к LogOff также отлично подойдет для чистого перенаправления при LogOn.

person davewasthere    schedule 30.07.2009
comment
Думаю, это действительно не работает в стандартных шаблонах ASP.NET MVC. Приведенный выше код просто работает! Спасибо, Дэйв. :) - person Leniel Maccaferri; 16.12.2011
comment
Да, это не работает в новом шаблоне MVC 4. Чтобы воспроизвести ошибку, просто создайте новое веб-приложение ASP.NET MVC 4 и добавьте атрибут [Authorize] в действие About. Параметр returnUrl всегда будет иметь значение NULL, если он не добавлен в соответствии с указаниями @davewasthere. - person Catch22; 26.01.2012
comment
Если по какой-то причине вы не можете редактировать BeginForm (например, при использовании одной формы для всей страницы), вы также можете разместить следующее скрытое поле на странице входа в систему: ‹input type = hidden name = ReturnUrl value = @ Request. QueryString [ReturnUrl] / › - person Shackles; 18.04.2012
comment
@ Catch22: Есть ли для этого отчет об ошибке? Довольно неприятно, когда вы пытаетесь изучить MVC, и он не работает правильно из коробки. - person mpen; 31.08.2012
comment
У меня это работает: [HttpPost] [ValidateAntiForgeryToken] public ActionResult LogOff () {WebSecurity.Logout (); return RedirectToAction (логин, аккаунт, новый {ReturnUrl = Request.UrlReferrer.AbsolutePath}); } - person learnerplates; 04.04.2013
comment
Ответ @SimonW лучше работает для меня при использовании смешанных контроллеров GET / POST. Ввод ReturnUrl в 3-м параметре BeginForm не сработал при использовании POST. - person Charles Burns; 03.06.2013
comment
На самом деле это сделано специально. Параметр returnUrl заполняется автоматически только тогда, когда вы пытаетесь получить доступ к авторизованному ресурсу, но не прошли аутентификацию или авторизацию. см. github.com/aspnet/Templates/issues/420 - person RickAndMSFT; 03.03.2016

По сути, у Asp.net MVC есть некоторые скрытые функции. Например, когда вы передаете переменную id в действие контроллера, он интерпретирует id как идентификатор по умолчанию и помещает его в запрос браузера с косой чертой. Используя другое имя вместо id, мы увидим '?' а не косую черту. Из-за установки имени id для RegisterRoutes метода в файле global.asax.

В этой задаче вы создали пользовательский передатчик данных для контроллера с помощью этого кода:

using(Html.BeginForm("LogOn", "Account", FormMethod.Post))
{
//form fields
}

Таким образом, Asp.net MVC игнорирует другие полезные данные, передаваемые в действие контроллера, и мы будем видеть returnUrl всегда null.

При этом Asp.net MVC работает правильно и returnUrl смонтирован:

using(Html.BeginForm())
{
//form fields in LogOn View
}

Между прочим, когда мы используем настраиваемое действие, передающее данные контроллеру, мы должны передать другие данные вручную следующим образом:

using(Html.BeginForm("LogOn", "Account", new {ReturnUrl = Request.QueryString["ReturnUrl"] }))
{
//form fields
}
person Amirhossein Mehrvarzi    schedule 21.07.2013

Я могу думать о двух способах работы со сценариями входа и выхода. Дэйв Бир описал один из способов выше. Есть еще один подход, который работает во многих ситуациях. Я использовал его при написании учебника NerdDinner. Учебник предоставляет нам функцию выхода из системы, которая выводит вас из системы и отправляет домой. Я этого не хотел. Я хотел вернуться на страницу, на которой был до выхода из системы. Поэтому я изменил действие выхода из системы контроллера учетной записи, чтобы оно выглядело следующим образом

   public ActionResult LogOff()
    {
        FormsService.SignOut();
        return Redirect(Request.UrlReferrer.ToString());
    }

Вы можете стать более привлекательным и передать returnUrl и протестировать его, если вы хотите переопределить это поведение. Но мне это не нужно. Этим достигается желаемый результат. Вход в систему может работать аналогично. Возможно, есть способы использовать инфраструктуру MVC, чтобы сделать это за меня, но пока я их не изучу, это ОЧЕНЬ просто и работает надежно.

person David Allen    schedule 03.04.2010
comment
Да, мне это очень нравится. Как говорит @ rickand-msft в комментарии под моим сообщением, это задумано. Мы несколько изменяем этот пользовательский поток, но это довольно распространенный шаблон для возврата пользователя на страницу, с которой он вошел в систему, даже если она не украшена атрибутом авторизации. - person davewasthere; 08.03.2016

Попробуйте следующее:

        public static MvcForm BeginForm(this HtmlHelper htmlHelper, string id)
    {
        string formAction = htmlHelper.ViewContext.HttpContext.Request.RawUrl;

        TagBuilder tagBuilder = new TagBuilder("form");

        tagBuilder.MergeAttribute("id", id);
        tagBuilder.MergeAttribute("action", formAction);
        tagBuilder.MergeAttribute("method", HtmlHelper.GetFormMethodString(FormMethod.Post), true);

        HttpResponseBase httpResponse = htmlHelper.ViewContext.HttpContext.Response;
        httpResponse.Write(tagBuilder.ToString(TagRenderMode.StartTag));

        return new MvcForm(htmlHelper.ViewContext.HttpContext.Response);
    }

Сначала убедитесь, что вы установили URL-адрес входа в web.config, затем убедитесь, что ваша форма входа не содержит ничего похожего на действие, например:

Вид:

Если вы укажете действие, вы всегда получите нулевой URL-адрес для возврата:

Контроллер:

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult SignIn(string userName, string password, bool? rememberMe, string returnUrl)
{
}
person kazimanzurrashid    schedule 06.05.2009
comment
Итак, как мне установить идентификатор формы без указания действия? Так выглядит мой Html.BeginForm. ‹% Using (Html.BeginForm (Logon, Account, null, FormMethod.Post, new {id = logonForm})) {%› - person aherrick; 06.05.2009