2010-12-30 24 views
12

Estoy intentando que esto funcione correctamente (hace 2 días). Estoy trabajando en un inicio de sesión donde estoy llamando a la acción del controlador desde jQuery, pasando un objeto JSON (utilizando json2.js) y devolviendo un objeto Json desde el controlador. Soy capaz de llamar a la multa de acción, pero en lugar de ser capaz de poner la respuesta donde quiero que sólo se abre una nueva ventana con esta impreso en la pantalla:Devolver el objeto Json de la acción del controlador a jQuery

{"Message":"Invalid username/password combination"} 

Y la URL http parece : // localhost: 13719/Account/LogOn así que en lugar de llamar a la acción y no volver a cargar la página, lleva al usuario al controlador, lo cual no es bueno.

Así que ahora por algún código, primero el código del controlador

[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"); 
} 

Y el código 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 }; 
} 

En caso de tener que ver el formulario de acceso real aquí que es así

<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> 

El formulario de inicio de sesión se carga en la página principal con

<% Html.RenderPartial("LogonControl");%> 

No estoy seguro de si eso tiene alguna relación con esto o no, pero pensé que lo mencionaría.

EDIT: El formulario de acceso se carga similar a la de inicio de sesión de Twitter, haga clic en un enlace y se carga el formulario con la ayuda de jQuery & CSS

Respuesta

2

Pensando en lo que @ user350374 dije sobre la fabricación de la firma de mi acción JsonResult en lugar de ActionResult hice algunos retoques y modificado mi solución original a utilizar JsonResult e hizo todas las comprobaciones/redireccionamientos en jQuery en lugar de en la acción.

Mi acción cambió a

[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" }); 
    } 

} 

Y mi llamado jQuery para

$("#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 es una clase simple sólo para mantener las piezas

public class LoginResult 
{ 
    public bool Success { get; set; } 
    public string Message { get; set; } 
    public string ReturnUrl { get; set; } 
} 

Gracias por la punta @ user35037, ahora tengo 2 formas de abordar esto en el futuro.

+0

mi placer. y sí, gracias por publicar una solución detallada. – Baz1nga

+0

@psycho Tuve el mismo problema aquí. Además del hecho de que la redirección como ActionResult no funcionaría cuando se llama a través de jQuery, la razón principal por la que tu primer código devolvió el "archivo json" es porque no has tenido el 'return false;' en la función de envío, por lo tanto, devolviendo el JSON como un "archivo". –

9

Si está utilizando MVC 2, usted tiene que devolver algo de esta manera:

return Json(your_object, JsonRequestBehavior.AllowGet); 

lo he encontrado here

Para un uso diferente, aquí está mi código.

JQuery:

$(document).ready(function() { 
    $("#InputDate").live('click', function() { 
     var date = $("#InputDate").val(); 
     if (date != "") { 
      $.getJSON("/Home/GetNames", 
        { date: $("#InputDate").val() }, 
        function (data) { 
         $("#ProviderName").empty(); 
         // [...] 
         }); 
        }); 
     } 
    }); 
}); 

y C#

public JsonResult GetNames(string date) 
{ 
    List<Provider> list = new List<Provider>(); 
    // [...] 
    return Json(list, JsonRequestBehavior.AllowGet); 
} 
+1

Gracias Kerrubin, no es solo para MVC2, es para MVC 3,4 y 5 –

2

Ok se acercó con una resolución que pensé que me gustaría compartir aquí por si alguien viene con un tema simliar. En lugar de utilizar $ .ajax que me pasa a utilizar $ .post y cambiado de código de jQuery para parecerse a esto y todo funciona de la manera que esperaba inicialmente a:

$("#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; 
    }); 
}); 

Gracias a todos los que veían en mi pregunta, y a @kerrubin ya que no estaba al tanto de ese problema.

12

Su firma acción se verá de la siguiente manera:

public virtual JsonResult ActionName() 
{ 
    var abcObj = new ABC{a=1,b=2}; 

    return Json(abcObj); 
} 
+0

Gracias por la sugerencia, pero lo tengo como _ResultadoAcción_ porque si es un inicio de sesión válido entonces me redirecciona a una vista. – PsychoCoder

+0

PODEMOS devolver cualquier tipo de servidor desde el servidor y creo que Json es el mejor que puede serializar su vista parcial como json y enviarla de vuelta al cliente y probablemente anexe una propiedad isValid al json en función de la cual elija wat para renderizar en la página. – Baz1nga

+0

Además, si eso no es algo que no quiera considerar, lo que puede hacer es si el usuario inicia sesión con éxito u activa otra llamada frm js que obtiene la vista parcial – Baz1nga

Cuestiones relacionadas