Returning Json object from controller action to jQuery
I'm attempting to get this working properly (2 days now). I'm working on a log in where I'm calling the controller action from jQuery, passing it a JSON object (utilizing json2.js) and returning a Json object from the controller. I'm able to call the action fine, but instead of being able to put the response where I want it it just opens a new window with this printed on the screen:
{"Message":"Invalid username/password combination"}
And the URL looks like http://localhost:13719/Account/LogOn so instead of calling the action and not reloading the page it's taking the user to the controller, which isn't good.
So now for some code, first the controller code
[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");
}
And the jQuery code
$("#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 };
}
In case you need to see the actual login form here that is as well
<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 clas开发者_JS百科s="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>
The login form is loaded on the main page with
<% Html.RenderPartial("LogonControl");%>
Not sure if that has any bearing on this or not but thought I'd mention it.
EDIT: The login form is loaded similar to the Twitter login, click a link and the form loads with the help of jQuery & CSS
Your action signature will look as follows:
public virtual JsonResult ActionName()
{
var abcObj = new ABC{a=1,b=2};
return Json(abcObj);
}
If you're using MVC 2, you have to return something like this :
return Json(your_object, JsonRequestBehavior.AllowGet);
I've found it here
For a different usage, here is my 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();
// [...]
});
});
}
});
});
And C#
public JsonResult GetNames(string date)
{
List<Provider> list = new List<Provider>();
// [...]
return Json(list, JsonRequestBehavior.AllowGet);
}
Ok came up with a resolution that I thought I'd share here in case someone comes along with a simliar issue. Instead of using $.ajax I switched to using $.post and changed my jQuery code to look like this and everything works just the way I initially expected it to:
$("#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;
});
});
Thanks to all who looked at my question, and to @kerrubin as I was unaware of that issue.
Thinking about what @user350374 said about making the signature of my action JsonResult instead of ActionResult I did some tinkering and modified my original solution to utilize JsonResult and did all the checking/redirecting in jQuery instead of in the action.
My action changed to
[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" });
}
}
And my jQuery call to
$("#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 is a simple class just to hold the parts
public class LoginResult
{
public bool Success { get; set; }
public string Message { get; set; }
public string ReturnUrl { get; set; }
}
Thanks for the tip @user35037, now I have 2 ways to approach this in the future.
精彩评论