Возврат объекта Json из действия контроллера в jQuery - PullRequest
14 голосов
/ 30 декабря 2010

Я пытаюсь заставить это работать должным образом (2 дня сейчас). Я работаю над журналом, в котором я вызываю действие контроллера из jQuery, передавая ему объект JSON (используя json2.js) и возвращая объект Json из контроллера. Я могу нормально вызвать действие, но вместо того, чтобы поместить ответ туда, где я хочу, он просто открывает новое окно со следующим напечатанным на экране:

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

И URL выглядит как http://localhost:13719/Account/LogOn, поэтому вместо вызова действия и перезагрузки страницы пользователь переносит пользователя в контроллер, что не очень хорошо.

Так что теперь для некоторого кода, сначала код контроллера

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

И код 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 };
}

На тот случай, если вам нужно увидеть здесь реальную форму входа, а также

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

Форма входа загружается на главную страницу с

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

Не уверен, имеет ли это какое-либо отношение к этому или нет, но подумал, что я упомяну это.

РЕДАКТИРОВАТЬ: Форма входа загружается аналогично входу в Twitter, нажмите ссылку, и форма загружается с помощью jQuery & CSS

Ответы [ 4 ]

14 голосов
/ 30 декабря 2010

Ваша подпись действия будет выглядеть следующим образом:

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

     return Json(abcObj);
}
10 голосов
/ 30 декабря 2010

Если вы используете MVC 2, вы должны вернуть что-то вроде этого:

return Json(your_object, JsonRequestBehavior.AllowGet);

Я нашел это здесь

Для другого использования, вот мой код.

JQuery:

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

А, С #

public JsonResult GetNames(string date)
 {
   List<Provider> list = new List<Provider>();
   // [...]
   return Json(list, JsonRequestBehavior.AllowGet);
}
2 голосов
/ 02 января 2011

Думая о том, что @ user350374 сказал о создании подписи моего действия JsonResult вместо ActionResult Я немного поработал и изменил свое оригинальное решение, чтобы использовать JsonResult и сделал все проверки / перенаправления в JQuery, а не в действии.

Мое действие изменено на

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

}

И мой 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 - это простой класс для хранения частей

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

Спасибо за отзыв @ user35037, теперь у меня есть 2 способа подойти к этому в будущем.

2 голосов
/ 30 декабря 2010

Ладно, пришло решение, которым я поделюсь, если кто-нибудь придет с похожей проблемой. Вместо использования $. Ajax я переключился на использование $. Post и изменил свой код 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);
            }
        }, "json");
        return false;
    }); 
});

Спасибо всем, кто посмотрел на мой вопрос, и @kerrubin, так как я не знал об этой проблеме.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...