如何从Web服务返回多个值?

14

我是一个新手,对于Web服务还不太了解,请多包容。我正在使用.asm文件在Visual Studio 2010中创建一个非常简单的Web服务。

以下是我使用的代码:

namespace MyWebService
{
    [WebService(Namespace = "http://www.somedomain.com/webservices")]
    [WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
    [System.ComponentModel.ToolboxItem(false)]

    public class Service1 : System.Web.Services.WebService
    {
        [WebMethod]
        public string simpleMethod(String str)
        {
            return "Hello " + str;
        }   
    }
}

当我调用此函数并将值"John Smith"作为str参数输入时,它会返回:

<?xml version="1.0" encoding="utf-8"?>
<string xmlns="http://www.somedomain.com/webservices">Hello John Smith</string>

我的问题是,对于一个Web服务方法,返回多个值的最佳实践是什么?如果这些值都是相同的数据类型,我应该使用数组吗?如果这些值包含不同的数据类型,是否需要创建自定义类?


2
在我看来,最好的设计是在你的WSDL中声明一个类并返回它的实例。这样,任何其他框架都可以调用此方法,因为交换的类型是公共的而不是特定于框架的。 - Andre Calil
1
我不会被它是Web服务还是其他形式所困扰。只需返回你需要的数据类型即可。 - Menefee
1
@Baxter 给我1分钟。 - Andre Calil
1
@Baxter,你能否提供一些关于我的答案的反馈?这是你想要的吗? - Andre Calil
1
@Baxter 请查看我在答案中添加的新示例。敬礼。 - Andre Calil
显示剩余3条评论
1个回答

37
我认为最好的设计方法是编写一个类并在您的WSDL上包含它。这将使该类的签名与您服务的描述一起可用。这意味着,客户端无论使用哪种语言,都能够使用该类型的对象。
创建这个类时,请尽量不要使用.NET内置的自定义类型,如DataSet或任何其他类型。尽可能使用基本类型,这将确保您的对象易于序列化和反序列化,并且可以被开发框架不同于.NET的客户端使用。
请查看此问题:How to Declare Complex Nested C# Type for Web Service。它展示了一些代码和小小的建议。
如果您需要进一步的支持,请让我知道。
更新:
假设您想要返回给定Web方法的以下一组数据:
- 学生姓名 - 学生出生日期 - 学生当前分配的课程列表(由其名称表示)
看看服务的签名应该是怎样的:
public class WebService1 : System.Web.Services.WebService
{
    public class Course
    {
        public string Name { get; set; }
    }

    public class Student
    {
        public string Name { get; set; }
        public DateTime BirthDate { get; set; }
        public List<Course> CurrentCourses { get; set; }
    }

    [WebMethod]
    public Student HelloWorld()
    {
        Student Baxter = new Student();

        Baxter.Name = "Baxter";
        Baxter.BirthDate = new DateTime(1986, 04, 22);
        Baxter.CurrentCourses = new List<Course>();
        Baxter.CurrentCourses.Add(new Course() { Name = "SOAP Webservices 101" });
        Baxter.CurrentCourses.Add(new Course() { Name = "Mastering C#" });
        Baxter.CurrentCourses.Add(new Course() { Name = "Why you (and I) suck at Javascript" });

        return Baxter;
    }
}
调用该函数后,这是结果:
<Student xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://tempuri.org/">
    <Name>Baxter</Name>
    <BirthDate>1986-04-22T00:00:00</BirthDate>
    <CurrentCourses>
        <Course>
            <Name>SOAP Webservices 101</Name>
        </Course>
        <Course>
            <Name>Mastering C#</Name>
        </Course>
        <Course>
            <Name>Why you (and I) suck at Javascript</Name>
        </Course>
    </CurrentCourses>
</Student>

最好的是,由于这个类签名是公共的(包含在WSDL中),你可以在不同的项目中通过简单处理WSDL来进行以下操作:

        ServiceReference1.WebService1SoapClient SoapClient = new ServiceReference1.WebService1SoapClient();
        ServiceReference1.Student IsThisBaxter = SoapClient.HelloWorld();

@AndreCalil 我在Visual Studio中复制并部署了那段代码。当我在浏览器中运行它时,它会显示出正确的SOAP 1.1和SOAP 1.2请求/响应,当我点击调用按钮时,它会返回上面列出的响应。 - Baxter
@AndreCalil 你好Andre。非常好的答案。如果我想返回多个学生对象怎么办?比如查询所有6岁的学生后,正确的工作流程是什么?非常感谢。 - David Gidony
1
@DavidGidony 你好!你看到学生有一系列课程的列表了吗?这是同样的想法,你可以创建一个类型,例如 Result,它将拥有一个 List<Student> - Andre Calil
@AndreCalil,嗨,我按照您的要求操作了,但是当我将列表类型作为响应返回时,没有数据显示。 - David Gidony
1
@DavidGidony 你好David,能否将你的代码发布为一个新问题并在此处提供链接?这样帮助起来会更容易。 - Andre Calil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接