2009-05-06 3 views
54

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

+1

Это на самом деле по дизайну. Параметр returnUrl заносится автоматически только при попытке получить доступ к авторизованному ресурсу, но не прошел проверку подлинности или авторизации. см. https://github.com/aspnet/Templates/issues/420. Вы можете использовать подход @davewasthere (или с помощью помощника тега), если вы хотите, чтобы returnUrl был установлен для случаев, отличных от auth. – RickAndMSFT

ответ

23

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

+0

Не уверен, что я следую. Вы считаете, что считаете, что я не включаю параметр ReturnURL в действие на контроллере? – aherrick

+0

Нет Я имел в виду атрибут действия тега HTML-формы. На странице входа в систему может появиться запрос с возвратом ReturnURL. Но если форма входа отправляет его без этого параметра querystring, то он потерян. –

+0

Хм ... Нет, где в коде я явно устанавливаю ReturnURL на любом сообщении формы. Он автоматически генерируется в строке запроса структурой. – aherrick

1

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

 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) 
{ 
} 
+0

Итак, как я могу установить значение Id из формы без указания действия? Вот как выглядит мой Html.BeginForm. <% using (Html.BeginForm ("Logon", "Account", null, FormMethod.Post, new {id = "logonForm"})) {%> – aherrick

118

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

Просто чтобы прояснить, это то, что ваш код должен выглядеть в вашем BeginForm:

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

EDIT: Это, Дези gn, как упоминает RickAnd в комментариях ниже. Однако это не позволяет шаблону пользовательского интерфейса быть глубоко на сайте, нажав на LogOn, а затем вернется к предыдущей странице, если это позволяет анонимным пользователям. Это часто запрашиваемый шаблон. Подход Дэвида Аллена к LogOff также хорошо подойдет для чистой переадресации в LogOn.

+0

Спасибо за фрагмент dave. – Rake36

+7

Он думает, что это действительно сломано на стандартных шаблонах ASP.NET MVC. Вышеприведенный код работает! Спасибо, Дэйв. :) –

+2

Да - он разбит в новом шаблоне MVC 4. Чтобы воспроизвести ошибку, просто создайте новое веб-приложение ASP.NET MVC 4 и добавьте атрибут [Авторизовать] в «О действии». Параметр returnUrl всегда будет иметь значение null, если он не добавлен как указано @davewasthere. – Catch22

3

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

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

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

+0

Да, мне это очень нравится. Поскольку @ rickand-msft говорит в комментарии ниже моего сообщения, это по дизайну. Мы немного меняем этот поток пользователей, но довольно распространенный шаблон для возврата пользователя на страницу, в которую они вошли, хотя он не украшен атрибутом Authorize. – davewasthere

7

В основном, 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 
} 
Смежные вопросы