简体   繁体   中英

How to pass multidimensional list or tuple to C# Web Service

I'm working on a web service that needs to accept a collection with three values of different types. The values are

SkuNumber (integer), FirstName (string), LastName (string)

I want the web service to accept a list of 100 instances of these values but am not sure how to go about it. Do I use a multidimensional list or array? Maybe a tuple? Or can I just create a simple class structure and accept a list of that class?

This is all simple enough in a normal application, I'm just not sure how the app calling the web service would pass the data with any of the given options.

Can someone give me some pointers?

Create a class and accept a list of that class. Be sure to mark it as [Serializable].

[Serializable]   
public class Whatever
{
    public int SkuNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

Best practice would be to define the class in an assembly that can be accessed by both the service and the project that calls it.

The trouble with a tuple or a multi-dimensional array is that the data you send doesn't have an inherent identity: you could stick any old thing in there. If you have a class, you are indicating that you are sending an Order or an Inquiry or a Coupon or whatever it is you are tracking. There's a level of meaning that goes along with it.

If a shared assembly is not feasible, you can always go with good ol' XML. It may not be the optimal solution and I'm sure plenty of users here will balk at the idea, but it is easy to support and relatively quick to implement, so it really depends on your individual situation and the skill level of the developers responsible for supporting the application.

The benefit to using XML here, is that the calling application can be written in almost any language on almost any platform, as long as it adheres to the XML structure.

The XML string should be easy enough to generate in the calling application, but the biggest downside here is that if you have a ton of data, the processing may take longer than desired -- on both ends of the service.

Here is a working sample if you want to give it a try:

 public class Whatever
    {
        public int SkuNumber { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    [WebMethod]
    public void HelloWorld(string xmlString)
    {
        //make all the node names + attribute names lowercase, to account for erroneous xml formatting -- leave the values alone though
        xmlString = Regex.Replace(xmlString, @"<[^<>]+>", m => m.Value.ToLower(),RegexOptions.Multiline | RegexOptions.Singleline);

        var xmlDoc = LoadXmlDocument(xmlString);


        var listOfStuff = new List<Whatever>();

        var rootNode = xmlDoc.DocumentElement;
        foreach(XmlNode xmlNode in rootNode)
        {
            var whatever = new Whatever
                               {
                                   FirstName = xmlNode["first_name"].InnerText,
                                   LastName = xmlNode["last_name"].InnerText,
                                   SkuNumber = Convert.ToInt32(xmlNode["sku_number"].InnerText)
                               };
            listOfStuff.Add(whatever);
        }
    }

    public static XmlDocument LoadXmlDocument(string xmlString)
    {
        //some extra stuff to account for URLEncoded strings, if necessary
        if (xmlString.IndexOf("%3e%") > -1)
            xmlString = HttpUtility.UrlDecode(xmlString);

        xmlString = xmlString.Replace((char)34, '\'').Replace("&", "&amp;").Replace("\\", "");

        var xmlDocument = new XmlDocument();
        xmlDocument.PreserveWhitespace = false;
        xmlDocument.LoadXml(xmlString);

        return xmlDocument;
    }

Your XML would look like this:

<stuff_to_track>
<whatever>
    <sku_number>1</sku_number>
    <first_name>jimi</first_name>
    <last_name>hendrix</last_name>
</whatever>
<whatever>
    <sku_number>2</sku_number>
    <first_name>miles</first_name>
    <last_name>davis</last_name>
</whatever>
<whatever>
    <sku_number>3</sku_number>
    <first_name>david</first_name>
    <last_name>sanborn</last_name>
</whatever>
<whatever>
    <sku_number>4</sku_number>
    <first_name>john</first_name>
    <last_name>coltrane</last_name>
</whatever>
</stuff_to_track>

I also recommend validating the incoming XML, for both schema and data.

Just send what you want:

public class Whatever
{
    public int SkuNumber { get; set; }
    public string FirstName { get; set; }
    public string LastName { get; set; }
}

[WebMethod]
public void TakeList(List<Whatever> theList)
{
    foreach (var w in theList)
    {
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM