【问题标题】:Returning Json object from controller action to jQuery将 Json 对象从控制器操作返回到 jQuery
【发布时间】:2010-12-30 16:29:51
【问题描述】:

我正在尝试使其正常工作(现在 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 的帮助下加载

【问题讨论】:

    标签: asp.net-mvc json jquery controller


    【解决方案1】:

    您的操作签名如下所示:

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

    【讨论】:

    • 感谢您的提示,但我将其命名为 ActionResult,因为如果它是有效登录名,那么我会重定向到一个视图。
    • 好吧,您可以从服务器返回任何一种类型,我认为 Json 是最好的,因为您可以将您的部分视图序列化为 json 并将其发送回客户端,并可能将 isValid 属性附加到json 基于您选择要在页面上呈现的 wat。
    • 另外,如果这不是您不想考虑的事情,您可以做的是,如果用户登录成功,您会触发另一个获取部分视图的调用 frm js
    【解决方案2】:

    如果您使用的是 MVC 2,则必须返回如下内容:

    return Json(your_object, JsonRequestBehavior.AllowGet);
    

    我找到了here

    对于不同的用法,这是我的代码。

    jQuery :

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

    和 C#

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

    【讨论】:

    • 谢谢 Kerrubin,它不仅适用于 MVC2,它适用于 MVC 3,4 和 5
    【解决方案3】:

    好的,我想出了一个解决方案,我想我会在这里分享,以防有人遇到类似的问题。我没有使用 $.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,因为我不知道这个问题。

    【讨论】:

      【解决方案4】:

      考虑@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 的提示,现在我有两种方法可以解决这个问题。

      【讨论】:

      • @psycho 我在这里遇到了同样的问题。除了通过 jQuery 调用时重定向为 ActionResult 不起作用的事实之外,您的第一个代码返回“json 文件”的主要原因是因为您在提交函数中没有 return false;,因此,返回JSON 作为“文件”。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-23
      相关资源
      最近更新 更多