使用jQuery AJAX缩短Web方法中的参数数量

时间:2022-04-29 23:15:38

For this question, I'm using ASP.NET Web Forms in C#, a web service and jQuery. I read this post about using an array to pass in a bunch of parameters to a web method using jQuery AJAX. I'm wondering if it's possible to do the same thing without using indices. The problem with indices is that order matters and making an update is a hassle since it involves updating the client-script and web method's arguments. I'm currently using named arguments, but this is very tedious. My largest web method has 20 arguments! Yuck! I'm looking for a shortcut here without having to care about order. Is this possible?

对于这个问题,我在C#中使用ASP.NET Web Forms,这是一个Web服务和jQuery。我读过这篇关于使用数组将一堆参数传递给使用jQuery AJAX的web方法的帖子。我想知道是否可以在不使用索引的情况下做同样的事情。索引的问题在于订单很重要并且进行更新很麻烦,因为它涉及更新客户端脚本和Web方法的参数。我目前正在使用命名参数,但这非常繁琐。我最大的网络方法有20个参数!呸!我在这里寻找捷径,而不必关心订单。这可能吗?

var obj = {};

// Iterate through each table row and add the editor field data to an object.
$('.addressRow').each(function ()
{
    var row = $(this);
    var addressField = row.find('.addressField');
    var attr = addressField.attr('addressFieldName');
    var val = addressField.val()
    obj[attr] = val;
});

$.ajax(
{
    type: 'POST',
    url: '/WebServices/AddressService.asmx/SaveAddress',
    data: JSON.stringify(obj),
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (response)
    {
        alert('address saved');
    },
    error: function (response)
    {
        alert('error');
    }
});



[WebMethod]
public void SaveAddress(string streetAddress1, string streetAddress2, string apartmentNumber, string city, strng state, string zipCode, string country)
{
    // save address...
}

UPDATE:

更新:

Thanks to all who answered. Using your answers and some other Stack questions, I was finally able to piece together a working demo. I'm pasting my proof of concept code here so anyone stuck with the same problem can see how it's done.

感谢所有回答的人。使用你的答案和其他一些Stack问题,我终于可以拼凑出一个有效的演示了。我在这里粘贴了我的概念证明代码,所以任何坚持相同问题的人都可以看到它是如何完成的。

<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
    <title>Web Service Demo</title>
    <style type="text/css">
        * { font-family: "Segoe UI"; font-size: 12px; color: #444444; }
        #result1 { padding: 10px 0px; }
    </style>
    <script type="text/javascript" src="Scripts/jquery.js"></script>
    <script type="text/javascript">
        $(document).ready(function ()
        {
            $('button').click(function ()
            {
                // NOTE: When using JavaScript objects, the properties MUST match the C# properties EXACTLY (casing and seplling).
                // I.e. in employee.FirstName, FirstName maps EXACTLY to the FirstName in the C# Employee object.

                // Create a employee object using the assigning to properties method.
                var employee1 = {};
                employee1.ID = 5416;
                employee1.FirstName = 'Fred';
                employee1.LastName = 'Baker';
                employee1.BirthDate = '07/18/1982';
                employee1.StreetAddress = '947 River Street';
                employee1.City = 'Somnerville';
                employee1.State = 'AR';
                employee1.ZipCode = '41370';

                // A property has the ability to be a list or complex type. In this example, employee1 uses a list of access codes and employee2 does not.
                employee1.AccessCodes = new Array();
                employee1.AccessCodes[0] = 512;
                employee1.AccessCodes[1] = 887;

                // Create a employee object using the associative array method.
                var employee2 =
                {
                    ID: 3316,
                    FirstName: 'Jason',
                    LastName: 'Masters',
                    BirthDate: '11/19/1980',
                    StreetAddress: '11 South Crane Avenue',
                    City: 'New York',
                    State: 'NY',
                    ZipCode: '01147'

                    // employee2 does no use any access codes. AccessCodes in the C# web method is a list and by excluding it from the JavaScript
                    // object, the C# code defaults the list to the null.
                };

                // In order to pass a complex JavaScript object to a web method as a complex type, the JavaScript object needs to be JSONified.
                // The name of the argument in the C# web method MUST be included here in single quotes EXACTLY (casing and spelling) the same way
                // the argument is specified in the C# code. In this example, the web method is "public string GetEmployeeData(Employee employee)". The
                // complex argument is 'employee'. IT IS VITALLY IMPORTANT that, when using the JSON.stringify() function, the name of the web method
                // argument is included here exactly the same way as specified in the C# code. I know I'm being redundant by repeating myself, but
                // it took me hours to figure out how to do this and the error message from doing this improperly is completely useless!

                var data1 = JSON.stringify({ 'employee': employee1 }); // 'employee' is the web method argument and employee1 is the JavaScript object from above.
                var data2 = JSON.stringify({ 'employee': employee2 }); // 'employee' is the web method argument and employee2 is the JavaScript object from above.

                // Send employee1 to the web method.
                $.ajax(
                {
                    type: 'POST',
                    url: '/WebServices/WebService1.asmx/GetEmployeeData',
                    data: data1,
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    success: function (response)
                    {
                        $('#result1').html(response.d);
                    },
                    error: function (response)
                    {
                        $('#result1').html('web service call failure\n' + response.responseText);
                    }
                });

                // Send employee2 to the web method.
                $.ajax(
                {
                    type: 'POST',
                    url: '/WebServices/WebService1.asmx/GetEmployeeData',
                    data: data2,
                    contentType: 'application/json; charset=utf-8',
                    dataType: 'json',
                    success: function (response)
                    {
                        $('#result2').html(response.d);
                    },
                    error: function (response)
                    {
                        $('#result2').html('web service call failure\n' + response.responseText);
                    }
                });
            });
        });
    </script>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <p>This demo shows how to pass a complex JSON object to a web method and get a reponse back from the web method.</p>
        <p>1) It creates two JavaScript objects.</p>
        <p>2) The JavaScript objects are JSONified and sent to the web method.</p>
        <p>3) The web method receives the complex objects and uses them to create response text.</p>
        <p>4) When the callback function fires, it displays the text returned from the web service.</p>
        <button type="button">Call Web Service</button>
        <div id="result1"></div>
        <div id="result2"></div>            
    </div>
    </form>
</body>
</html>

[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[ToolboxItem(false)]
[ScriptService]
public class WebService1 : WebService
{
    [WebMethod]
    public string GetEmployeeData(Employee employee)
    {
        var output = string.Format("Employee #{0}: {1} {2} lives at {3} in {4}, {5} with a zip code of {6} and was born on {7}.", employee.ID, employee.FirstName, employee.LastName, employee.StreetAddress, employee.City, employee.State, employee.ZipCode, employee.BirthDate.ToShortDateString());

        if (employee.AccessCodes != null)
        {
            output += string.Format(" Employee #{0} has access codes: ", employee.ID);

            foreach (var accessCode in employee.AccessCodes)
            {
                output += accessCode + " , ";
            }

            output = output.Substring(0, output.Length - 2);
        }
        else
        {
            output += string.Format(" Employee #{0} does not have any has access codes.", employee.ID);
        }

        return output; 
    }
}

public class Employee
{
    public int ID { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public DateTime BirthDate { get; set; }
    public string StreetAddress { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string ZipCode { get; set; }
    public List<int> AccessCodes  {get;set;}
}

2 个解决方案

#1


2  

NOTE: this example will not fully keep you from doing work, but you should only have to change a few places if something changes. Change the c# class and change the save method (and the layout perhaps).

注意:此示例不会完全阻止您进行工作,但如果发生更改,您只需更改一些位置即可。更改c#类并更改save方法(可能还有布局)。

Create an "address" class in c# with all the elements, create an array of addresses, then handle that list of addresses (single parameter) in the web method. My example is somewhat construed but should give you a starting place. I have not tested this fully but it should be close.

在c#中创建一个包含所有元素的“地址”类,创建一个地址数组,然后在Web方法中处理该地址列表(单个参数)。我的例子有些解释,但应该给你一个起点。我没有完全测试过,但它应该很接近。

[WebMethod] 
public void SaveAddress(List<Address> Addresses) { 
// save em here
}

public class Address
{
    public Address()
    {
        streetAddress1 = streetAddress2 = apartmentNumber = city = state = zipCode = country = String.Empty;
    }
    public String streetAddress1 { get; set; }
    public String streetAddress2 { get; set; }
    public String apartmentNumber { get; set; }
    public String city { get; set; }
    public String state { get; set; }
    public String zipCode { get; set; }
    public String country { get; set; }
}

With this layout:

有了这个布局:

<div id='Address'>
    <input class='streetAddress1' type='text'>
    <input class='streetAddress2' type='text'>
    <input class='apartmentNumber' type='text'>
    <input class='city' type='text'>
    <input class='state' type='text'>
    <input class='zipCode' type='text'>
    <input class='country' type='text'>
</div>
<div id='Address'>
    <input class='streetAddress1' type='text'>
    <input class='streetAddress2' type='text'>
    <input class='apartmentNumber' type='text'>
    <input class='city' type='text'>
    <input class='state' type='text'>
    <input class='zipCode' type='text'>
    <input class='country' type='text'>
</div>
<button id='savedata'>SaveData</button>

Here is some client code to save:

以下是一些要保存的客户端代码:

function AddressRow(currentAddressRow) {
    this.streetAddress1 = currentAddressRow.find('.streetAddress1').val();
    this.streetAddress2 = currentAddressRow.find('.streetAddress2').val();
    this.apartmentNumber = currentAddressRow.find('.apartmentNumber').val();
    this.city = currentAddressRow.find('.city').val();
    this.state = currentAddressRow.find('.state').val();
    this.zipCode = currentAddressRow.find('.zipCode').val();
    this.country = currentAddressRow.find('.country').val();
}

function AddressRowSet() {
    var addressRows = [];
    var allAddressRows = $('.Address');
    var thisRow = null;
    var currentRowCount = allAddressRows.length;
    var i = 0;
    for (i = 0; i < currentRowCount; i++) {
        thisRow = allAddressRows.eq(i);
        addressRows.push(new AddressRow(thisRow));
    }
    this.AddressRows = addressRows;
}

function SaveCurrentAddresses() {
    var AddressRecords = new AddressRowSet();
    var AddressesData = {
        Addresses: AddressRecords.AddressRows
    };
    SaveAddressData(JSON.stringify(AddressesData));
}

function SaveAddressData(Addresses) {
    $.ajax({
        type: 'POST',
        data: Addresses,
        contentType: 'application/json',
        url: '/WebServices/AddressService.asmx/SaveAddress',
        dataType: 'json',
        success: function(response) {
            alert('address saved');
        },
        error: function(response) {
            alert('error');
        }
    });
}
$('#savedata').click(function() {
    SaveCurrentAddresses();
});

#2


1  

You don't need to use arrays - arrays are specifically for storing a list of related data - i.e. a list of countries or cars etc.

您不需要使用数组 - 数组专门用于存储相关数据列表 - 即国家/地区列表等。

Use an anonymous json blob to define your parameters:

使用匿名json blob定义参数:

var obj = {
    param1: 'stringval1',
    param2: 100, // int value,
    param3: {
        childobjparam1: 'this is a child object in json',
        childobjparam2: true // boolean value
    }
};

Then you can just pass in the json object as follows:

然后你可以按如下方式传入json对象:

$.ajax(
{
    type: 'POST',
    url: '/WebServices/AddressService.asmx/SaveAddress',
    data: obj,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (response)
    {
        alert('address saved');
    },
    error: function (response)
    {
        alert('error');
    }
});

JSON is lovely :)

JSON很可爱:)

#1


2  

NOTE: this example will not fully keep you from doing work, but you should only have to change a few places if something changes. Change the c# class and change the save method (and the layout perhaps).

注意:此示例不会完全阻止您进行工作,但如果发生更改,您只需更改一些位置即可。更改c#类并更改save方法(可能还有布局)。

Create an "address" class in c# with all the elements, create an array of addresses, then handle that list of addresses (single parameter) in the web method. My example is somewhat construed but should give you a starting place. I have not tested this fully but it should be close.

在c#中创建一个包含所有元素的“地址”类,创建一个地址数组,然后在Web方法中处理该地址列表(单个参数)。我的例子有些解释,但应该给你一个起点。我没有完全测试过,但它应该很接近。

[WebMethod] 
public void SaveAddress(List<Address> Addresses) { 
// save em here
}

public class Address
{
    public Address()
    {
        streetAddress1 = streetAddress2 = apartmentNumber = city = state = zipCode = country = String.Empty;
    }
    public String streetAddress1 { get; set; }
    public String streetAddress2 { get; set; }
    public String apartmentNumber { get; set; }
    public String city { get; set; }
    public String state { get; set; }
    public String zipCode { get; set; }
    public String country { get; set; }
}

With this layout:

有了这个布局:

<div id='Address'>
    <input class='streetAddress1' type='text'>
    <input class='streetAddress2' type='text'>
    <input class='apartmentNumber' type='text'>
    <input class='city' type='text'>
    <input class='state' type='text'>
    <input class='zipCode' type='text'>
    <input class='country' type='text'>
</div>
<div id='Address'>
    <input class='streetAddress1' type='text'>
    <input class='streetAddress2' type='text'>
    <input class='apartmentNumber' type='text'>
    <input class='city' type='text'>
    <input class='state' type='text'>
    <input class='zipCode' type='text'>
    <input class='country' type='text'>
</div>
<button id='savedata'>SaveData</button>

Here is some client code to save:

以下是一些要保存的客户端代码:

function AddressRow(currentAddressRow) {
    this.streetAddress1 = currentAddressRow.find('.streetAddress1').val();
    this.streetAddress2 = currentAddressRow.find('.streetAddress2').val();
    this.apartmentNumber = currentAddressRow.find('.apartmentNumber').val();
    this.city = currentAddressRow.find('.city').val();
    this.state = currentAddressRow.find('.state').val();
    this.zipCode = currentAddressRow.find('.zipCode').val();
    this.country = currentAddressRow.find('.country').val();
}

function AddressRowSet() {
    var addressRows = [];
    var allAddressRows = $('.Address');
    var thisRow = null;
    var currentRowCount = allAddressRows.length;
    var i = 0;
    for (i = 0; i < currentRowCount; i++) {
        thisRow = allAddressRows.eq(i);
        addressRows.push(new AddressRow(thisRow));
    }
    this.AddressRows = addressRows;
}

function SaveCurrentAddresses() {
    var AddressRecords = new AddressRowSet();
    var AddressesData = {
        Addresses: AddressRecords.AddressRows
    };
    SaveAddressData(JSON.stringify(AddressesData));
}

function SaveAddressData(Addresses) {
    $.ajax({
        type: 'POST',
        data: Addresses,
        contentType: 'application/json',
        url: '/WebServices/AddressService.asmx/SaveAddress',
        dataType: 'json',
        success: function(response) {
            alert('address saved');
        },
        error: function(response) {
            alert('error');
        }
    });
}
$('#savedata').click(function() {
    SaveCurrentAddresses();
});

#2


1  

You don't need to use arrays - arrays are specifically for storing a list of related data - i.e. a list of countries or cars etc.

您不需要使用数组 - 数组专门用于存储相关数据列表 - 即国家/地区列表等。

Use an anonymous json blob to define your parameters:

使用匿名json blob定义参数:

var obj = {
    param1: 'stringval1',
    param2: 100, // int value,
    param3: {
        childobjparam1: 'this is a child object in json',
        childobjparam2: true // boolean value
    }
};

Then you can just pass in the json object as follows:

然后你可以按如下方式传入json对象:

$.ajax(
{
    type: 'POST',
    url: '/WebServices/AddressService.asmx/SaveAddress',
    data: obj,
    contentType: 'application/json; charset=utf-8',
    dataType: 'json',
    success: function (response)
    {
        alert('address saved');
    },
    error: function (response)
    {
        alert('error');
    }
});

JSON is lovely :)

JSON很可爱:)