【问题标题】:Proper way to use AJAX Post in jquery to pass model from strongly typed MVC3 view在 jquery 中使用 AJAX Post 从强类型 MVC3 视图传递模型的正确方法
【发布时间】:2011-05-12 15:24:08
【问题描述】:

我是一名新手网络程序员,所以如果我的一些“行话”不正确,请原谅我。 我有一个使用 MVC3 框架的 ASP.NET 项目。

我正在处理管理员视图,管理员将在其中修改设备列表。其中一个功能是“更新”按钮,我想在向 MVC 控制器发送帖子后使用 jquery 动态编辑网页上的条目。

我认为这种方法在单一管理设置中是“安全的”,在这种设置中,网页与数据库不同步的担忧微乎其微。

我创建了一个强类型视图,并希望使用 AJAX 帖子将模型数据传递给 MVC 控件。

在下面的帖子中,我发现了一些类似于我正在做的事情: JQuery Ajax and ASP.NET MVC3 causing null parameters

我将使用上面帖子中的代码示例。

型号:

public class AddressInfo 
{
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public string Country { get; set; }
}

控制器:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View();
    }

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
}

视图中的脚本:

<script type="text/javascript">
var ai = {
    Address1: "423 Judy Road",
    Address2: "1001",
    City: "New York",
    State: "NY",
    ZipCode: "10301",
    Country: "USA"
};

$.ajax({
    url: '/home/check',
    type: 'POST',
    data: JSON.stringify(ai),
    contentType: 'application/json; charset=utf-8',
    success: function (data.success) {
        alert(data);
    },
    error: function () {
        alert("error");
    }
});
</script>

我还没有机会使用上述内容。但我想知道这是否是使用 AJAX 将模型数据传回 MVC 控件的“最佳”方法?

我应该担心暴露模型信息吗?

【问题讨论】:

    标签: asp.net-mvc-3 jquery


    【解决方案1】:

    我找到了 3 种方法来实现这一点:

    C#类:

    public class AddressInfo {
        public string Address1 { get; set; }
        public string Address2 { get; set; }
        public string City { get; set; }
        public string State { get; set; }
        public string ZipCode { get; set; }
        public string Country { get; set; }
    }
    

    行动:

    [HttpPost]
    public ActionResult Check(AddressInfo addressInfo)
    {
        return Json(new { success = true });
    }
    

    JavaScript 你可以通过三种方式实现:

    1) 查询字符串:

    $.ajax({
        url: '/en/Home/Check',
        data: $('#form').serialize(),
        type: 'POST',
    });
    

    这里的数据是一个字符串。

    "Address1=blah&amp;Address2=blah&amp;City=blah&amp;State=blah&amp;ZipCode=blah&amp;Country=blah"

    2) 对象数组:

    $.ajax({
        url: '/en/Home/Check',
        data: $('#form').serializeArray(),
        type: 'POST',
    });
    

    这里的数据是一个键/值对数组:

    =[{name: 'Address1', value: 'blah'}, {name: 'Address2', value: 'blah'}, {name: 'City', value: 'blah'}, {name: 'State', value: 'blah'}, {name: 'ZipCode', value: 'blah'}, {name: 'Country', value: 'blah'}]
    

    3) JSON:

    $.ajax({
          url: '/en/Home/Check',
          data: JSON.stringify({ addressInfo:{//missing brackets
              Address1: $('#address1').val(),
              Address2: $('#address2').val(),
              City: $('#City').val(),
              State: $('#State').val(),
              ZipCode: $('#ZipCode').val()}}),
          type: 'POST',
          contentType: 'application/json; charset=utf-8'
    });
    

    这里的数据是一个序列化的 JSON 字符串。请注意,名称必须与服务器中的参数名称匹配!!

    ='{"addressInfo":{"Address1":"blah","Address2":"blah","City":"blah","State":"blah", "ZipCode", "blah", "Country", "blah"}}'
    

    【讨论】:

    • 刚刚遇到这个伟大而彻底的答案,它解决了我还不知道的问题。 +1,谢谢!
    • #2 是我想要的。这应该是答案。
    • 编辑:我的工作必须使用data: $('input, textarea, select').serialize(),
    • 嘿Jazaret!如何使用第三种方法将日期传递给模型??
    • 抱歉耽搁了@GuruprasadRao 要传递日期,您可以将日期和时间作为 javascript 代码中的字符串,MVC 会将其转换为 DateTime 对象。
    【解决方案2】:

    您可以跳过 var 声明和 stringify。否则,它会工作得很好。

    $.ajax({
        url: '/home/check',
        type: 'POST',
        data: {
            Address1: "423 Judy Road",
            Address2: "1001",
            City: "New York",
            State: "NY",
            ZipCode: "10301",
            Country: "USA"
        },
        contentType: 'application/json; charset=utf-8',
        success: function (data) {
            alert(data.success);
        },
        error: function () {
            alert("error");
        }
    });
    

    【讨论】:

    • 感谢您指出细微的调整。从安全角度公开模型结构是否有任何顾虑?
    • 对我来说没有什么明显的安全问题。但是,如果您真的很担心,您可以随时在 mvc 端制作自定义模型绑定器。
    • 这对我来说失败了。我必须使用 JSON.stringify( { ... } ) 调用才能在 MVC5 中工作。
    • 我注意到在使用 API 控制器时我必须这样做。不过,这个答案是 4 年前写的,那时 API 控制器还没有出现。
    • 天哪,我有 dataType 而不是 contentType,那个总是能得到我!
    【解决方案3】:

    这就是它为我工作的方式:

    $.post("/Controller/Action", $("#form").serialize(), function(json) {       
            // handle response
    }, "json");
    
    [HttpPost]
    public ActionResult TV(MyModel id)
    {
        return Json(new { success = true });
    }
    

    【讨论】:

      【解决方案4】:

      您所拥有的一切都很好 - 但是为了节省一些输入,您可以简单地用于您的数据

      数据:$('#formId').serialize()

      详见http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/,语法非常基础。

      【讨论】:

      • 为了使用序列化功能,我的理解是类的每个成员都需要在一个表单对象中使用。如果这是正确的,我可能是 SOL。
      • 啊是啊..如果不是你就不能使用序列化。不过,您始终可以操作 DOM 并使用这些元素创建一个表单并对其进行序列化 - 但是......然后手动输入字段可能会更干净。
      • @TahaRehmanSiddiqui serialize 确实可以在 IE 中使用,什么不起作用?你有错误吗?
      • 我的模型的每个属性都是空的
      • @TahaRehmanSiddiqui 表单字段的“名称”是否与模型属性的名称匹配?
      【解决方案5】:

      如果使用 MVC 5,请阅读此解决方案!

      我知道专门针对 MVC 3 提出的问题,但我偶然发现了 MVC 5 的这个页面,并想为我遇到的其他任何人发布一个解决方案。我尝试了上述解决方案,但它们对我不起作用,从未达到动作过滤器,我不知道为什么。我在我的项目中使用了第 5 版,最终得到了以下操作过滤器:

      using System;
      using System.Collections.Generic;
      using System.Linq;
      using System.Web;
      using System.Web.Mvc;
      using System.Web.Mvc.Filters;
      
      namespace SydHeller.Filters
      {
          public class ValidateJSONAntiForgeryHeader : FilterAttribute, IAuthorizationFilter
          {
              public void OnAuthorization(AuthorizationContext filterContext)
              {
                  string clientToken = filterContext.RequestContext.HttpContext.Request.Headers.Get(KEY_NAME);
                  if (clientToken == null)
                  {
                      throw new HttpAntiForgeryException(string.Format("Header does not contain {0}", KEY_NAME));
                  }
      
                  string serverToken = filterContext.HttpContext.Request.Cookies.Get(KEY_NAME).Value;
                  if (serverToken == null)
                  {
                      throw new HttpAntiForgeryException(string.Format("Cookies does not contain {0}", KEY_NAME));
                  }
      
                  System.Web.Helpers.AntiForgery.Validate(serverToken, clientToken);
              }
      
              private const string KEY_NAME = "__RequestVerificationToken";
          }
      }
      

      -- 记下 using System.Web.Mvcusing System.Web.Mvc.Filters,而不是 http 库(我认为这是 MVC v5 改变的事情之一。--

      然后只需将过滤器[ValidateJSONAntiForgeryHeader] 应用于您的操作(或控制器),它应该会被正确调用。

      &lt;/body&gt; 正上方的布局页面中,我有@AntiForgery.GetHtml();

      最后,在我的 Razor 页面中,我执行 ajax 调用如下:

      var formForgeryToken = $('input[name="__RequestVerificationToken"]').val();
      
      $.ajax({
        type: "POST",
        url: serviceURL,
        contentType: "application/json; charset=utf-8",
        dataType: "json",
        data: requestData,
        headers: {
           "__RequestVerificationToken": formForgeryToken
        },
           success: crimeDataSuccessFunc,
           error: crimeDataErrorFunc
      });
      

      【讨论】:

      • 您是否手动检索所有表单值?为什么不data: $("#the-form").serialize()
      • @Sinjai 我将不得不再次查看我的代码,但我相信我也在其中进行了一些其他处理。如果您只需要输入值,“.serialize()”也可以使用
      • 别担心,我只是好奇。
      猜你喜欢
      • 2013-07-28
      • 1970-01-01
      • 2011-10-11
      • 1970-01-01
      • 2012-05-05
      • 1970-01-01
      • 2018-12-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多