65.9K
CodeProject 正在变化。 阅读更多。
Home

创建供互联设备通过互联网使用的 Web 服务

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.96/5 (9投票s)

2014 年 11 月 12 日

CPOL

12分钟阅读

viewsIcon

63294

downloadIcon

1226

本文概述了如何创建一个 .NET WCF Web 服务项目,该项目可供通过互联网连接的 Web 应用程序或设备使用。

引言

本文旨在提供一个概述和示例,介绍如何创建自己的 Web 服务,以便连接到互联网的设备能够相互通信,将数据集中存储,集中访问和管理整个数据库,并执行各种任务。

物联网(Internet of Things)是一个概念和现象,用于通过我们钟爱的通信连接“互联网”连接您的房屋或办公室硬件。本文将为您提供一个概述,教您如何创建自己的 Web 服务,并创建和管理客户端,这些客户端将是向您的服务发送数据的设备。允许它们将数据发送到您的服务,然后管理数据,保存数据或根据数据执行任何其他服务。

最终,您将能够创建一个简单的(甚至可以是企业级的,如果您能理解并愿意创建一个系统的话)Web 服务,该服务可以运行连接到它的互联网设备,无论哪个设备正在调用该服务,以及以什么协议调用该服务,服务器都会响应,您的服务也会被调用并运行。

物联网服务

物联网为我们提供了一些服务,可以根据发送给我们的数据来管理和执行各种任务。您可以将一项服务想象成“在早上 6:00 启动灯泡”。听起来不错吧?

物联网执行着许多类似的各种任务。物联网本身就是一个将设备(更像是家用电器)通过通用网络“互联网”相互连接的概念。从那里,它们相互发送/接收数据并执行分配给它们的任务。在上面的例子中,如果时钟指向早上 6:00,就会向灯泡发送消息以点亮灯泡。我承认这有点夸张。

创建服务

您创建一个服务,告诉设备在接收到命令时执行某项任务。通常,一个通用的中心或主机进行控制,每个设备将数据发送到中心,然后中心决定做什么以及从哪些设备获取工作。中心充当服务器,接受请求,发送响应,然后客户端(设备)执行其任务。因此,一切似乎都在“魔法般”地工作。

由于只有一个中心充当服务器,因此服务安装在中心上。每个设备都连接到它以传输数据,中心处理数据并执行服务。该服务连接到任何已连接的设备,因此该设备会获得其任务的触发器。

Web服务

Web 服务是一种服务(服务可以是方法),它被定义为在通过互联网相互连接的多个设备之间执行。这是一种控制网络中连接设备工作的方法。

不仅是家庭、办公室,许多大型企业也正在使用这项服务来控制他们来自每个设备的数据。这提供了一种更好的方法来控制每个设备执行的数据和功能。您可以将其视为公司中的安全服务。“如果指纹图案正确,则开门”。这是一项服务,取决于人们如何应用它。

交互

设备之间可以通过多种协议和机制进行交互。您可以使用 SOAP、HTML 等来发送数据和命令给设备。您也可以以 XML 格式发送数据。

WCF 是微软提供的一项新技术,它允许设备通过 HTML、SOAP、WSDL、XML Schema 和 WS-Policy 进行通信和发送元数据。REST 服务和 JSON 也可用。

安全

重要的是,Web 服务必须是安全的,这样任何未经授权的访问都可以被禁止,只有授权的设备和客户端才能与中心通信。SSL 和其他一些标准可用于为设备设置安全性。

自定义

最好的软件服务是您可以随时更改并使其适合您需求的软件。如果软件无法更改和定制以使其更安全、更高效,那么该软件就毫无价值。

响应

Web 服务必须响应发送给它的每一个请求。

WCF 是 Web 服务领域的新基础之一,由 Mirosoft 推出。它可以托管在控制台应用程序或 IIS 中,并通过控制台应用程序、WPF 应用程序甚至网站进行访问。这使其非常适合当今的需求。在本文中,我们将创建一个 Web 服务,该服务将托管在控制台应用程序中,并通过网站使用该服务来概述“互联网”连接的概念。

Web Services

创建 Web 服务

第一步是创建一个 Web 服务。Web 服务实际上只是一堆方法和函数,每当客户端访问并要求服务执行某项操作或获取某项内容时,这些方法和函数就会被执行。不要被“Web 服务”这个花哨的名称所迷惑,它只是一堆方法。与网站或软件类似,您将能够创建函数、属性、类和对象。

我们的 Web 服务:一项为用户提供接口的服务,用户可以在其中向服务输入数据,服务将保存该数据。服务还会查找任何现有数据,如果数据存在,则显示出来,否则不显示任何内容,而是显示一个用于输入数据的表单。

您可以使其更复杂,并添加更多功能,以创建企业级的 Web 服务,使其能够完全执行任务。

服务模板

服务需要是一个接口,为什么?因为当您需要从客户端调用服务时,您不需要告诉客户端您正在经历的每一步以及您执行的每一项任务。以您去您的求职公司并提交申请为例,公司只会告诉您“申请正在审查中”,而底层进程,例如“老板等待申请”、“老板正在审查它”、“老板叫秘书打电话给员工”等等。

因此,您只需要创建实际服务的签名,以便在将其传递给客户端后,客户端只会要求您“我想找一份工作”,然后期望得到“已获得工作”或“不够格”等结果。

在 Visual Studio 中创建一个类库,并将其命名为 WebServices_Interfaces,添加所需的库引用。完成后,将以下代码添加到其中。ISaveData 是一个接口。

// Add the references; must also be added to the Project
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Required and added
using System.ServiceModel;
using System.Runtime.Serialization;

// Name of this Class Library Project = WebServices_Interfaces
namespace WebServices_Interfaces
{
    // Following are the ServiceContracts
    [ServiceContract]
    public interface ISaveData
    {
        [OperationContract]
        void AddData(Data s);

        [OperationContract]
        Data[] GetCurrentData();
    }
    
    // DataContracts for the Web Service
    [DataContract]
    public class Data
    {
        private string text;

        [DataMember]
        public string DataLabel
        {
            set { this.text = value; }
            get { return this.text; }
        }
    }
}

创建数据源

当然,如果您愿意,可以一直运行服务在其环境中,并将附加到它的数据保存在内存中,或者,如果您愿意,可以使用您的存储设备来存储进入服务和离开服务的数据。集中在一个地方。

创建一个新的库,这次将其命名为 WebServices_DataSources,添加库的引用,并添加一个名为“DataSource”的新类文件。完成后,您的文件中将包含以下代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// Add this reference, for working with Files
using System.IO;

namespace WebServices_DataSources
{
    public class DataSource
    {
        // Get the current users MyDocuments folder
        static string directory = System.Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
        // Our File Name. You can change it in your project.
        static string fileName = "/myServiceFile.txt";

        // static variable
        // Will contain the content, for accessing and saving the data
        static List<string> currentData = File.ReadAllLines(directory + fileName).ToList();

        // This method saves the Data sent
        public void Save(string dataLabel)
        {
            currentData.Add(dataLabel);
            Directory.CreateDirectory(directory);
            File.Create(directory + fileName).Close();

            File.WriteAllLines(directory + fileName, currentData);
        }

        // Gets the current list.
        public List<string> GetDataList()
        {
            return currentData;
        }
    }
}

在您的应用程序中实现服务

下一步是在一个应用程序中实现该服务,该应用程序可以使用并且将包含您的实际 Web 服务的实现方法。您可以看到接口只包含 Web 服务的签名。这将作为实际的 Web 服务,并且每次设备需要保存数据时都会访问它。

创建一个新的库,添加对 WebServices_InterfacesWebServices_DataSources 的引用,这些是您的 Web 服务需要使用的。将此库项目命名为 WebServices_Service,此类将实现 ISaveData 接口,以便您可以为接口的签名添加正文。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// add the projects in this project
using WebServices_DataSources;
using WebServices_Interfaces;


namespace WebServices_Service
{
    // Implements the ISaveData
    public class WebService : ISaveData
    {
        // Adds the Body to the methods
        public void AddData(Data d)
        {
            DataSource ds = new DataSource();
            ds.Save(d.DataLabel);
        }

        public Data[] GetCurrentData()
        {
            DataSource sd = new DataSource();
            List<string> dataList = sd.GetDataList();
            Data[] dataArray = new Data[dataList.Count];
            for (int i = 0; i < dataList.Count; i++)
            {
                Data s = new Data();
                s.DataLabel = dataList[i];
                dataArray[i] = s;
            }
            return dataArray;
        }
    }
}

您可以看到,此代码包含服务的实际工作,当您调用 AddData 时,您可以看到它实际上是将数据添加到 DataSource 中,并在调用 GetCurrentData 时,它从 DataSource 获取数据并将其返回给用户。然后用户可以使用它来执行其他任务。

托管您的 Web 服务

您已经创建了应用程序,很好。但是,当您不为其设置任何位置时,其他人将如何使用它?把它想象成一个钱袋,但您不知道它在哪里。

您可以将 Web 服务托管在几乎任何应用程序中,从控制台到 Web 应用程序。但由于本文旨在提供概述,我将使用一个将持续运行并托管应用程序的控制台应用程序来介绍此主题。控制台将接受所有发出的请求,您可以为资源设置一个 Uri,控制台将在该位置充当服务器。

创建一个控制台应用程序,添加对我们三个库的引用,然后将以下代码添加到应用程序中创建的 Program.cs 文件中。命名

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

// add the references to the libraries required.
using WebServices_Interfaces;
using WebServices_Service;
using WebServices_DataSources;
using System.ServiceModel;
using System.ServiceModel.Description;

namespace WebServices_HostingAndRunning
{
    class Program
    {
        static void Main(string[] args)
        {
            // the Uri for this Web Service.
            Uri baseAddress = new Uri("https://:8080/My_WebService");

            // Create the ServiceHost.
            using (ServiceHost host = new ServiceHost(typeof(WebService), baseAddress))
            {
                // Enable metadata publishing. 
                ServiceMetadataBehavior smb = new ServiceMetadataBehavior();
                smb.HttpGetEnabled = true;
                smb.MetadataExporter.PolicyVersion = PolicyVersion.Policy15;
                host.Description.Behaviors.Add(smb);

                // Open the ServiceHost to start listening for messages. Since
                // no endpoints are explicitly configured, the runtime will create
                // one endpoint per base address for each service contract implemented
                // by the service.
                host.Open();

                Console.WriteLine("The service is ready at {0}", baseAddress);
                Console.WriteLine("Press <Enter> to stop the service.");
                Console.ReadLine();

                // Close the ServiceHost.
                host.Close();
            }
        }
    }
}

注意:以上代码是通过 MSDN 的文档捕获的。该文档包含更多用于在托管应用程序中托管应用程序的代码。

配置您的 Web 服务服务器

您的控制台应用程序有一个 App.Config 文件,可用于配置其属性并设置一些属性。编辑它,或将其替换为以下代码,

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
  <!-- Server Configuration is as following -->
  <system.serviceModel>
    <services>
      <service name="WebServices_Service.WebService">
        <!-- baseAddress and the Interface of the Service is added.  -->
        <endpoint
                address="https://:8080/My_WebService" 
                binding="wsHttpBinding" 
                contract="WebServices_Interfaces.ISaveData" />
      </service>
    </services>
  </system.serviceModel>
</configuration>

您可以运行您的应用程序,大多数情况下您会收到一个错误,说它无法获取 Uri http://+:8080 之类的信息。不用担心,只需关闭 Visual Studio,以管理员模式重新运行 Visual Studio,然后再次运行应用程序,这次它将运行并显示消息,说明服务正在 {baseAddress} 上运行。您可以随时更改应用程序的 baseAddress。

元数据的服务也很重要,请勿删除该代码。如果您删除该部分,服务将无法使用。

Service Running

创建客户端

客户端是使用您创建的服务(消耗服务)的设备或程序。您可以使用网站作为服务客户端,或者使用控制台或 Windows Forms 开发的应用程序作为客户端来消耗您的 Web 服务并与其他设备通信。

在我们的项目中,我们将创建一个网站来消耗 Web 服务。该网站将为用户提供一个界面,用户可以在其中输入数据(文本)并提交以添加数据,还可以查看当前添加到存储设备的数据。

创建网站

您应该首先创建一个网站,您无需担心使用 MVC、Win Forms 等创建网站或 Web 应用程序。只需创建一个网站,我使用了 ASP.NET StarterSite (Empty CSHTML) 网站。

要使用该服务,您需要添加对您服务的引用。但首先,添加对 System.ServiceModel 的引用。完成后,添加对您库的引用。

在这里添加对服务的引用是一个棘手的部分,您需要右键单击 App_WebReferences 文件夹(所有服务引用都存在于此处);如果该文件夹不存在,请创建它,因为它最初不会被创建,然后选择 Add Service Reference。将会弹出一个窗口,要求您输入服务的 Uri。在此阶段,在继续之前,您需要确保您的服务正在运行(您需要确保控制台应用程序正在运行,并且显示“Web 服务正在 {baseAddress} 上运行”的消息)。您可以输入 Uri,然后继续。它将自动找到 Web 服务并添加使用服务所需的代码和文件。

Adding reference (Website)

现在您的文件夹将具有如下层次结构的文件夹,

Folder of Web Service reference

创建登陆页

现在,当所有这些完成后,您可以创建一个外观精美的首页来欢迎用户(客户端)。在那里,用户将能够找到一个用于将数据发送到服务的表单。

请记住:服务必须正在运行,否则将引发异常,提示找不到要捕获请求的内容。

此页面仅用于让用户理解界面,如果您为设备创建服务应用程序,并且不想创建任何表单。您可以直接从设备发出的请求中获取数据,并获取与请求相关联的数据。

@using System.ServiceModel;
@using WebServices_Interfaces;

@{
    List<string> currentData = new List<string>();
    // Enroll the student
    
    if (IsPost)
    {
        using (ChannelFactory<ISaveData> myServiceProxy =
        new ChannelFactory<ISaveData>("My_WebService_EndPoint"))
        {
            myServiceProxy.Open();
            ISaveData saveDataService = myServiceProxy.CreateChannel();
            // Create the Instance...
            Data s = new Data();
            
            // Get the Text
            s.DataLabel = Request["text"];
            saveDataService.AddData(s);
            myServiceProxy.Close();
        }
    }

    // Load the data from the Server
    using (ChannelFactory<ISaveData> myServiceProxy =
    new ChannelFactory<ISaveData>("My_WebService_EndPoint"))
    {
        myServiceProxy.Open();
        
        // Create the Channel for the Client to work from
        ISaveData getDataService = myServiceProxy.CreateChannel();
        
        // Get the current Data
        Data[] savedData = getDataService.GetCurrentData();
        
        // Work on Each of the Data
        foreach (Data data in savedData)
        {
            // Add the data to the List (Look in the first line)
            currentData.Add(data.DataLabel);
        }
        // Close the service proxy
        myServiceProxy.Close();
    }
}

@{
    Layout = "~/_SiteLayout.cshtml";
    Page.Title = "Home Page";
}

<ul>
    @if (currentData.Count > 0)
    {
        <p>Current data in the file is as: </p>
        // if there is any content present, then
        foreach (string str in currentData)
        {
            // Write those data.
            <li>@str</li>
        }
    }
</ul>

<div>
    <p>Use the following form to add the content.</p>
    <form method="post">
        <input type="text" name="text" />
        <input type="submit" value="Submit" />
    </form>
</div>

最初,页面将不包含任何内容,只有表单,因为我们当前的文件后端没有数据。using 用于在使用任何资源时,触发 .NET 的功能来清理和刷新资源。

Form input only

当用户触发提交时会发生什么

当用户单击提交按钮时,网站会向 Web 服务(当前正在控制台应用程序中托管和运行;并且必须正在运行)发出请求,并执行保存数据的函数。这仅在请求是 POST HTTP 请求时才存在。当用户提交表单时,表单及其文本数据将提交到服务器(Web 服务),然后在那里执行函数以保存数据(在 .txt 文件中)。

如果请求不是 POST,而是一个简单的请求,那么上面的代码块将不会执行,也不会保存任何内容。但是,GET 函数仍然会执行,导致 Web 服务返回存储介质中当前可用的数据。

因此,如果存在任何数据,页面将如下所示。

HTML page with some data

文件中的数据如下所示,

Data in the txt file

关注点

WCF 是创建 Web 服务时的最佳方法,它运行在您的 Windows 操作系统上,因为它是在 .NET 框架上开发的。您可以使用 SOAP、REST 等发送请求并获取响应。它支持 XML、JSON 和其他语法。您可以将此服务托管在任何应用程序中,并让任何设备作为其客户端。

历史

第一篇帖子

© . All rights reserved.