Второй пример будет представлять собой реализацию авторизации пользователя без перезагрузки страницы, с использованием только Ajax-запросов. Кроме того, сделаем так, чтобы возможность произвести вход в систему была доступна с любой страницы проекта.
Первоначально переопределим действие LogOn в контроллере Account так, чтобы поддержать возможность произведения входа в систему черезе Ajax-запросы (листинг 7.2).
Листинг 7.2. Переопределение действия LogOn
public ActionResult LogOn(string userName,
string password,
bool rememberMe,
string returnUrl)
{
if (Request.IsAjaxRequest())
{
var result = new AjaxResult();
if (!ValidateLogOn(userName, password))
{
result.IsSuccess = false;
result.ErrorString = "введен неверный логин или пароль";
return Json(result);
}
FormsAuth.SignIn(userName, rememberMe);
result.IsSuccess = true; return Json(result);
}
else
{
if (!ValidateLogOn(userName, password))
{
return View();
}
FormsAuth.SignIn(userName, rememberMe);
if (!String.IsNullOrEmpty(returnUrl))
{
return Redirect(returnUrl);
}
else
{
return RedirectToAction("Index", "Home");
}
}
}
Обратите внимание на выделенный в листинге 7.2 фрагмент. В нем используется метод Request.IsAjaxRequest() для определения типа запроса. Если запрос был произведен с помощью Ajax, то выполнятся дальнейшая обработка и возврат результата в виде JSON-данных с булевым значением, описывающим, произведен ли вход в систему, и строкой описания ошибки, если она возникла. Когда запрос не является Ajax-запросом, выполняется предыдущая логика.
Сделаем так, чтобы вход в систему был возможен на любой странице проекта (рис. 7.10). Для этого добавим разметку, необходимую для отображения элементов управления входа в систему, в элемент управления LogOnUserControl.ascx:
<% if (Request.IsAuthenticated) { %>
Welcome <b><%= Html.Encode(Page.User.Identity.Name) %></b>!
[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]
<% } else { %>
<div id="loginPanel">
<% using(Ajax.BeginForm("LogOn", "Account",
(object) null,
new AjaxOptions{OnSuccess = "OnLogon",
OnFailure = "OnError"})) {%>
Логин: <%= HtmL.TextBoxC'userNams'') %>
Пароль: <%= Html.Password ("password") %>
<%= HtmL.CheckBox("RememberMe") %> запомнить <input type^'submit" vaLue="Логин" /><br/>
<span id="message"></span>
<% } %>
</div>
<p id="logoutPanel" style="display: none;">
Welcome <b><span id="username"></span></b>!
[ <%= Html.ActionLink("Log Off", "LogOff", "Account") %> ]
</p>
<% } %>
Здесь в выделенном фрагменте кода с помощью вспомогательного метода Ajax.BeginForm объявляется форма для ввода данных. Устанавливаются параметры формы: действие, контроллер, которые требуется вызвать. С помощью определения экземпляра AjaxOptions определяются параметры Ajax-запроса: при успешном запросе будет вызвана JavaScript-функция onLogon, при возникновении ошибки будет вызваана другая функция — onError. Определим логику этих JavaScript-функций, которые будут реагировать на результат Ajax-запросов (листинг 7.3).
Листинг 7.3. JavaScript-код для реагирования на события
<script type="text/javascript">
function OnLogon(result) {
var response = result.get_response();
var resString = response.get_responseData();
var resultData = Sys.Serialization
.JavaScriptSerializer.deserialize(resString) ;
if (resultData.IsSuccess) {
document.getElementById('loginPanel').style.display = 'none';
document.getElementById('logoutPanel').style.display = '';
var username = document.getElementById('userName');
document.getElementById('username')
.innerHTML = "<b>" + username.value + "</b>";
} else {
document.getElementById('message')
.innerText = resultData.ErrorString;
}
}
function OnError(result) {
alert(result);
}
</script>
Здесь определяются две JavaScript-функции: OnLogon и OnError. Первая функция предназначена для обработки результата успешного выполнения авторизации. Функция OnLogon принимает один параметр — result, который содержит результат выполнения запроса и дополнительные данные. Для получения JSON-данных, которые были получены от действия LogOn, в функции OnLogon используются сужебные функции ASP.NET Ajax:
□ get_response — возвращает объект с данными ответа от сервера;
□ get_responseData — позволяет получить строку данных, которые были возвращены действием контроллера;
□ Sys.Serialization.JavaScriptSerializer.deserialize — преобразует строку с JSON-данными в объект с соответствующими полями.
После обработки ответа и извлечения полученных данных, в зависимости от результата, формируется либо разметка, соответствующая приглашению пользователя, либо выводится строка с сообщением об ошибке.
Для реализации поставленной задачи с помощью jQuery необходимо определить следующую разметку элементов управления:
<div id="loginPanel">
<form id="loginForm" method="post" action="Account/LogOn">
Логин: <input id="userName" type="text" />
Пароль: <input id="password" type="password" />
<input id="RememberMe" type="checkbox" />
запомнить <input type="submit" value="Логин" /><br/>
<span id="message"></span>
</form>
</div>
Здесь определена стандартная форма для отправки данных на сервер. Для обработки работы формы и формирования Ajax-запроса необходимо переопределить поведение формы с помощью JavaScript. Далее представлен фрагмент кода, определяющий логику работы формы:
<script type="text/javascript">
$('document').ready(function() {
$('#loginForm').submit(function(event) {
var postData = new Object();
postData.userName = $('#userName').val();
postData.password = $('#password').val();
postData.rememberMe = $('#RememberMe').is(':checked');
$.post('Account/LogOn',
postData,
function OnResult(result) {
if (result.IsSuccess) {
$('#loginPanel').hide();
$('#logoutPanel').show();
var username = $('#userName').val();
$('#username')
.html("<b>" + username + "</b>");
} else {
$('#message').text(result.ErrorString);
}
},
'json');
event.preventDefault();
})
});
</script>
Здесь определяется обработчик окончания загрузки документа, который после загрузки сайта в браузере у клиента выполнит необходимые привязки к разметке. Так, с помощью $('#loginForm').submit определяется функция, которая будет вызвана в момент, когда данные с формы будут передаваться на сервер. Обратите внимание на параметр event этой функции. После определения своей логики поведения при отправке данных с формы мы вызываем event.preventDefault(), который предотвращает поведение по умолчанию, т. е. позволяет нам отменить отправку данных с формы стандартным путем.
Для отправки данных мы используем функцию $.post, передав в нее предварительно сформированные данные, полученные с элементов управления. При вызове $.post мы определяем функцию OnResult, которая должна быть вызвана после завершения Ajax-запроса. Эта функция определяет обработку результата запроса и выводит либо сообщение об ошибке, либо приглашения для пользователя, в случае когда вход в систему был произведен удачно.