J'essaie de faire fonctionner cela correctement (2 jours maintenant). Je travaille sur une connexion où j'appelle l'action du contrôleur à partir de jQuery, en lui passant un objet JSON (en utilisant json2.js) et en renvoyant un objet Json à partir du contrôleur. Je peux appeler l'action bien, mais au lieu de pouvoir mettre la réponse où je veux, cela ouvre simplement une nouvelle fenêtre avec celle-ci imprimée à l'écran:
{"Message":"Invalid username/password combination"}
Et l'URL ressemble à http: // localhost: 13719/Account/LogOn donc au lieu d'appeler l'action et de ne pas recharger la page, il emmène l'utilisateur à le contrôleur, ce qui n'est pas bon.
Alors maintenant, pour du code, d'abord le code du contrôleur
[HttpPost]
public ActionResult LogOn(LogOnModel model, string returnUrl = "")
{
if (ModelState.IsValid)
{
var login = ObjectFactory.GetInstance<IRepository<PhotographerLogin>>();
var user = login.FindOne(x => x.Login == model.Username && x.Pwd == model.Password);
if (user == null)
return Json(new FailedLoginViewModel { Message = "Invalid username/password combination" });
else
{
if (!string.IsNullOrEmpty(returnUrl))
return Redirect(returnUrl);
else
return RedirectToAction("Index", "Home");
}
}
return RedirectToAction("Index", "Home");
}
Et le code jQuery
$("#signin_submit").click(function () {
var login = getLogin();
$.ajax({
type: "POST",
url: "../Account/LogOn",
data: JSON.stringify(login),
dataType: 'json',
contentType: 'application/json; charset=utf-8',
error: function (xhr) {
$("#message").text(xhr.statusText);
},
success: function (result) {
}
});
});
function getLogin() {
var un = $("#username").val();
var pwd = $("#password").val();
var rememberMe = $("#rememberme").val();
return (un == "") ? null : { Username: un, Password: pwd, RememberMe: rememberMe };
}
Au cas où vous auriez besoin de voir le formulaire de connexion réel ici aussi
<fieldset id="signin_menu">
<div>
<span id="message"></span>
</div>
<% Html.EnableClientValidation(); %>
<% using (Html.BeginForm("LogOn", "Account", FormMethod.Post, new { @id = "signin" }))
{%>
<% ViewContext.FormContext.ValidationSummaryId = "valLogOnContainer"; %>
<%= Html.LabelFor(m => m.Username) %>
<%= Html.TextBoxFor(m => m.Username, new { @class = "inputbox", @tabindex = "4", @id = "username" })%><%= Html.ValidationMessageFor(m => m.Username, "*")%>
<p>
<%= Html.LabelFor(m=>m.Password) %>
<%= Html.PasswordFor(m => m.Password, new { @class = "inputbox", @tabindex = "5", @id = "password" })%><%= Html.ValidationMessageFor(m => m.Password, "*")%>
</p>
<p class="remember">
<input id="signin_submit" value="Sign in" tabindex="6" type="submit"/>
<%= Html.CheckBoxFor(m => m.RememberMe, new { @class = "inputbox", @tabindex = "7", @id = "rememberme" })%>
<%= Html.LabelFor(m => m.RememberMe) %>
<p class="forgot"> <a href="#" id="forgot_password_link" title="Click here to reset your password.">Forgot your password?</a> </p>
<p class="forgot-username"> <a href="#" id="forgot_username_link" title="Fogot your login name? We can help with that">Forgot your username?</a> </p>
</p>
<%= Html.ValidationSummaryJQuery("Please fix the following errors.", new Dictionary<string, object> { { "id", "valLogOnContainer" } })%>
<% } %>
</fieldset>
Le formulaire de connexion est chargé sur la page principale avec
<% Html.RenderPartial("LogonControl");%>
Je ne sais pas si cela a une incidence sur cela ou non, mais j'ai pensé que je le mentionnerais.
EDIT: Le formulaire de connexion est chargé de la même manière que la connexion Twitter, cliquez sur un lien et le formulaire se charge à l'aide de jQuery & CSS
En pensant à ce que @ user350374 a dit à propos de la signature de mon action JsonResult au lieu de ActionResult J'ai fait quelques bricolages et modifié ma solution d'origine pour utiliser JsonResult et fait toute la vérification/redirection dans jQuery au lieu de dans l'action.
Mon action est devenue
[HttpPost,MoveFormsScript]
public JsonResult LogOn(LogOnModel model, string returnUrl = "")
{
if (ModelState.IsValid)
{
var login = ObjectFactory.GetInstance<IRepository<PhotographerLogin>>();
var user = login.FindOne(x => x.Login == model.Username && x.Pwd == model.Password);
if (user == null)
return Json(new LoginResult { Success = false, Message = "Invalid login" });
else
{
return Json(new LoginResult
{
Success = true,
Message = "Redirecting...",
ReturnUrl = (!string.IsNullOrEmpty(returnUrl)) ? returnUrl : string.Format("Account/Index/{0}", user.Photographer.Key)
});
}
}
else
{
return Json(new LoginResultDTO { Success = false, Message = "Incomplete fields" });
}
}
Et mon appel jQuery à
$("#signin_submit").click(function () {
var f = $($("form")[0]);
f.submit(function () {
var loginData = f.serialize();
$.post(f.attr("action"), loginData, function (result, status) {
if (!result.Success) {
$("#message").text(result.Message);
$("#username").focus();
$("#username").select();
}
else {
window.location.replace(result.ReturnUrl);
}
}, "json");
return false;
});
});
LoginResult est une classe simple juste pour contenir les pièces
public class LoginResult
{
public bool Success { get; set; }
public string Message { get; set; }
public string ReturnUrl { get; set; }
}
Merci pour l'astuce @ user35037, j'ai maintenant 2 façons d'aborder cela à l'avenir.
La signature de votre action se présente comme suit:
public virtual JsonResult ActionName()
{
var abcObj = new ABC{a=1,b=2};
return Json(abcObj);
}
Si vous utilisez MVC 2, vous devez renvoyer quelque chose comme ceci:
return Json(your_object, JsonRequestBehavior.AllowGet);
Je l'ai trouvé ici
Pour un usage différent, voici mon code.
JQuery:
$(document).ready(function () {
$("#InputDate").live('click', function () {
var date = $("#InputDate").val();
if (date != "") {
$.getJSON("/Home/GetNames",
{ date: $("#InputDate").val() },
function (data) {
$("#ProviderName").empty();
// [...]
});
});
}
});
});
Et C#
public JsonResult GetNames(string date)
{
List<Provider> list = new List<Provider>();
// [...]
return Json(list, JsonRequestBehavior.AllowGet);
}
Ok est venu avec une résolution que je pensais partager ici au cas où quelqu'un viendrait avec un problème similaire. Au lieu d'utiliser $. Ajax je suis passé à l'aide de $. Post et j'ai changé mon code jQuery pour qu'il ressemble à ceci et tout fonctionne exactement comme je m'y attendais initialement:
$("#signin_submit").click(function () {
var f = $($("form")[0]);
f.submit(function () {
var loginData = f.serialize();
$.post(f.attr("action"), loginData, function (result, status) {
if (!result.Success) {
$("#message").text(result.Message);
}
}, "json");
return false;
});
});
Merci à tous ceux qui ont regardé ma question et à @kerrubin car je n'étais pas au courant de ce problème.