Proper way to use AJAX Post in jquery to pass mode

2019-01-01 14:36发布

问题:

I\'m a novice web programmer so please forgive me if some of my \"jargon\" is not correct. I\'ve got a project using ASP.NET using the MVC3 framework.

I am working on an admin view where the admin will modify a list of equipment. One of the functions is an \"update\" button that I want to use jquery to dynamically edit the entry on the webpage after sending a post to the MVC controller.

I presume this approach is \"safe\" in a single admin setting where there is minimal concern of the webpage getting out of sync with the database.

I\'ve created a view that is strongly typed and was hoping to pass the model data to the MVC control using an AJAX post.

In the following post, I found something that is similar to what I am looking at doing: JQuery Ajax and ASP.NET MVC3 causing null parameters

I will use the code sample from the above post.

Model:

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

Controller:

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

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

script in View:

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

I have not had a chance to use the above yet. But I was wondering if this was the \"best\" method to pass the model data back to the MVC control using AJAX?

Should I be concerned about exposing the model information?

回答1:

You can skip the var declaration and the stringify. Otherwise, that will work just fine.

$.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\");
    }
});


回答2:

I found 3 ways to implement this:

C# class:

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

Action:

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

JavaScript you can do it three ways:

1) Query String:

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

Data here is a string.

\"Address1=blah&Address2=blah&City=blah&State=blah&ZipCode=blah&Country=blah\"

2) Object Array:

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

Data here is an array of key/value pairs :

=[{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\'
});

Data here is a serialized JSON string. Note that the name has to match the parameter name in the server!!

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


回答3:

This is the way it worked for me:

$.post(\"/Controller/Action\", $(\"#form\").serialize(), function(json) {       
        // handle response
}, \"json\");

[HttpPost]
public ActionResult TV(MyModel id)
{
    return Json(new { success = true });
}


回答4:

what you have is fine - however to save some typing, you can simply use for your data


data: $(\'#formId\').serialize()

see http://www.ryancoughlin.com/2009/05/04/how-to-use-jquery-to-serialize-ajax-forms/ for details, the syntax is pretty basic.



回答5:

If using MVC 5 read this solution!

I know the question specifically called for MVC 3, but I stumbled upon this page with MVC 5 and wanted to post a solution for anyone else in my situation. I tried the above solutions, but they did not work for me, the Action Filter was never reached and I couldn\'t figure out why. I am using version 5 in my project and ended up with the following action filter:

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\";
    }
}

-- Make note of the using System.Web.Mvc and using System.Web.Mvc.Filters, not the http libraries (I think that is one of the things that changed with MVC v5. --

Then just apply the filter [ValidateJSONAntiForgeryHeader] to your action (or controller) and it should get called correctly.

In my layout page right above </body> I have @AntiForgery.GetHtml();

Finally, in my Razor page, I do the ajax call as follows:

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