简体   繁体   English

帮助理解Web服务和REST

[英]Helping to Understand Web Services and REST

I've been longing to ask this question, but only found the time to do so now. 我一直想问这个问题,但现在才有时间这样做。

Anyways, there has been much of a discussion on Web Services (yeah, those traditional SOAP-XML response services) and RESTful services (which a lot of devs are into right now). 无论如何,关于Web服务(是的,那些传统的SOAP-XML响应服务)和RESTful服务(很多开发人员现在都在讨论)有很多讨论。

I feel that although I understand the concepts of REST in general, I need to learn more. 我觉得,尽管我大致了解REST的概念,但我需要学习更多。 I think one best way to totally embrace it is to show that it really is better (emphasis on ** as better is a subjective word) as what was being done currently. 我认为完全拥抱它的一种最佳方法是证明它确实当前正在做的更好 (强调**是主观用词)。

Consider the following simple traditional codes: (This one is copied from an enterprise app with Oracle as backend. The database pretty much I think won't matter as you could readily switch between SQL Server or Oracle or any DB for that matter). 考虑以下简单的传统代码:(此代码是从以Oracle为后端的企业应用程序复制而来的。我认为数据库几乎没有关系,因为您可以随时在SQL Server或Oracle或任何数据库之间进行切换)。

myWebService.asmx.cs myWebService.asmx.cs

namespace MyApplication
{
    public class myWebService : System.Web.Services.WebService
    {
        private classEmployee _emp = new classEmployee();

        [WebMethod]
        public string GetEmployees()
        {
            string EmployeeData = string.Empty;
            EmployeeData = _emp.GetEmployees();
            return EmployeeData;
        }
    }
}

classEmployee.cs classEmployee.cs

using System;
using System.Collections.Generic;
using System.Data;
using System.Globalization;
using System.Data.OracleClient;

namespace MyApplication.App_Code
{
    public class classEmployee
    {
        private DataAccess _da;

        public string GetEmployees()
        {
            string employeeData = string.Empty;
            string cmd = string.Empty;
            OracleCommand oraCmd = new OracleCommand();
            DataSet ds = new DataSet();

            try
            {
                 cmd = "SELECT * FROM Employees";

                oraCmd.CommandType = CommandType.Text;
                oraCmd.CommandText = cmd;
                ds = (DataSet)_da.ExecSQLQueryCmd(oraCmd, DataAccess.ResultType.DataSet);
                employeeData = ds.GetXml
                ds.Dispose();
            }
            catch (Exception ex)
            {
                employeeData = "Error: " + "Getting Employees [GetEmployees]" + Environment.NewLine + "Details: " + Environment.NewLine + ex.Message;
            }

            return employeeData;
        }
    }
}

DataAccess.cs DataAccess.cs

using System;
using System.Collections;
using System.Configuration;
using System.Data;
using System.Data.OracleClient;

namespace MyApplication.App_Code
{
    public class DataAccess
    {
        private OracleConnection oraConn;
        private String connString;

        public enum ResultType
        {
            DataReader = 0,
            DataSet = 1,
            DataTable = 2
        }

        public DataAccess()
        {
            connString = System.Configuration.ConfigurationManager.ConnectionStrings["AppConnectionString"].ConnectionString;
        }

        public object ExecuteSQLCommand(OracleCommand oraCommand, ResultType ReturnType, string TableName = "")
        {
            OracleDataAdapter oraDataAdapter = new OracleDataAdapter(oraCommand);
            oraConn = new OracleConnection(sConnectionString);

            try
            {
                oraConn.Open();
                oraCmd.Connection = oraConn;
                oraCmd.CommandType = CommandType.Text;

                switch (ReturnType)
                {
                    case ResultType.DataReader:
                        OracleDataReader oraDataReader = null;
                        oraDataReader = oraCmd.ExecuteReader();
                        return oraDataReader;

                    case ResultType.DataSet:
                        DataSet ds = new DataSet();
                        oDataAdapter.Fill(ds);
                        oraConn.Close();
                        oraConn.Dispose();
                        return ds;

                    case ResultType.DataTable:
                        DataTable dt = new DataTable();

                        if (!string.IsNullOrEmpty(TableName))
                            dt.TableName = TableName;
                        oDataAdapter.Fill(dt);
                        oraConn.Close();
                        oraConn.Dispose();
                        return dt;
                }
            }
            catch (OracleException oException)
            {
                throw oException;
            }
            finally
            {
                oDataAdapter.Dispose();
                oDataAdapter = null;
                oraCmd.Dispose();
            }

            return null;
        }

        public int ExecuteSQLNonQueryCommand(OracleCommand oraCommand)
        {
            // This will execute any NON-QUERY command.
            //Trimmed for Brevity purposes..
        }
    }
}

The above code is quite self explanatory. 上面的代码很容易解释。 Invoke the web service and the get the resulting data in XML format. 调用Web服务并获取XML格式的结果数据。 To execute non-query commands, simply replace the command string passed in the command object and call the necessary method in the DataAccess.cs class. 要执行非查询命令,只需替换命令对象中传递的命令字符串,然后在DataAccess.cs类中调用必要的方法。

I am overwhelmed already with the different opinions on why the above should at least be avoided and instead go for RESTful service type calls. 对于为什么至少应避免使用上述内容,而选择进行RESTful服务类型调用,我已经感到不知所措。 But I have not seen anything that at least helps convert this code to somewhat at least embrace the RESTful architecture. 但是我没有看到任何至少有助于将这段代码转换为至少某种程度上包含RESTful体系结构的东西。

I am pretty sure that a lot of people use this (mind you, I still use a lot of this currently) based on the reason that: 我很确定有很多人基于以下原因使用此功能(请注意,我目前仍在使用很多此功能):

  1. It works. 有用。
  2. Easy to implement, maintain and manage. 易于实施,维护和管理。
  3. People doing database driven development are so much into SQL commands that being able to use those SQL chops that we use in the SQL editor easily into the application is a big sigh of relief. 从事数据库驱动开发的人们对SQL命令的了解是如此之多,以至于能够轻松地将我们在SQL编辑器中使用的那些SQL Chop轻松地用于应用程序中。 Why would you use an ORM when you can simply implement all your multiple queries (including Stored Procedures) using the above example. 当您可以使用上述示例简单地实现所有多个查询(包括存储过程)时,为什么要使用ORM。
  4. Most code examples available for data related apps show the same pattern as above (Dataset being populated from an Command object, and returned as DataSet or XML, etc..). 可用于数据相关应用程序的大多数代码示例都显示与上述相同的模式(从Command对象填充数据集,并以DataSet或XML等形式返回)。

For one to accept what people terms as "Best Practice" in this area of coding, one should show why it is better, and how it is far easier to do such thing over the one that has been tried and tested to work. 为了使人们接受在此编码领域中被人们称为“最佳实践”的人,应该表明为什么它更好,并且与经过尝试和测试的人相比,做这种事情要容易得多。

If I may ask our fellow expert devs here to show me how to convert it, and some explanation on why the conversion to REST would be better (through the code), then I would be more than grateful for that. 如果我想请我们的专家开发人员向我展示如何进行转换,并解释一下为什么更好地(通过代码)转换为REST,那么我将不胜感激。

Appreciate your inputs. 感谢您的投入。 Thanks. 谢谢。

Additional: I just want to point out that, although this is correct, I started to have some doubts whether this approach is the best after reading this article: 另外:我只想指出,尽管这是正确的,但在阅读本文后,我开始怀疑这种方法是否是最佳方法:

http://www.codeproject.com/Feature/WeirdAndWonderful.aspx?msg=4324770#xx4324770xx http://www.codeproject.com/Feature/WeirdAndWonderful.aspx?msg=4324770#xx4324770xx

The article above, as one commented on said - "Found this in a web service I'm upgrading. It's hard to find anything NOT wrong with this." 上面一篇评论中提到的文章说:“在我要升级的Web服务中找到了它。很难找到没有错的东西。”

I am trying to establish as well what REALLY is wrong with this as I am in a bind. 我也试图建立一个真正的问题是什么,因为我处于困境中。

Let me give you some situations: 让我给你一些情况:

  1. Client/Customer asks that you provide an app that queries the information stored on the database. 客户/客户要求您提供一个查询数据库中存储的信息的应用程序。
  2. You come up with the solution using the above method. 您可以使用上述方法提出解决方案。 Requirements asked by the customer is provided. 提供了客户要求的要求。 The solution is reliable, fast and maintainable. 该解决方案可靠,快速且可维护。

So in essence, the other question which I long to ask, is that, WHAT's really wrong with the code above? 因此,从本质上讲,我想问的另一个问题是,上面的代码到底有什么问题?

To convert it, though this is off the top of my head, it would look something like this. 要转换它,尽管这不是我的头上想,但它看起来像这样。

namespace MyApplication 
{ 
    public class myWebService : System.Web.Services.WebService 
    { 
        private classEmployee _emp = new classEmployee(); 

        [HttpGet]
        public string GetEmployees() 
        { 
            string EmployeeData = string.Empty; 
            EmployeeData = _emp.GetEmployees(); 
            return EmployeeData; 
        } 
    } 
}

And you could return that string in anything that is easily convertable by the consumer. 而且,您可以使用消费者可以轻松转换的任何形式返回该字符串。 If it's JavaScript then I would recommend JSON since it's native. 如果是JavaScript,则建议使用JSON,因为它是本机的。

Let's talk about ReST for a minute. 让我们谈论一下ReST The part I find the most amusing about ReST is that the old fashioned ASMX services were ReSTful. 我觉得最有趣的左右部分ReST是老式的ASMX服务是基于REST的。 But, since the IT industry has a problem with accepting the fact that an older technology may have been more correct all along they had to name it something fresh and new. 但是,由于IT行业在接受这样一个事实方面存在问题,那就是旧技术可能一直以来都更加正确,因此他们不得不给它起一个新的名字。

They did this with the term Client/Server as well. 他们也使用“ Client/Server ”一词来做到这一点。 IBM was doing Client/Server operations years before Microsoft came around and said hey, we need to bring everything down to the PC. IBM是做客户端/服务器业务多年以来,微软走过来,说,嘿,我们需要把一切都到电脑前。 Well, when that started becoming less popular because deployment was a nightmare they realized, oh man, we need to go back to doing what IBM has been doing all along. 好吧,当这种方法由于部署是一场噩梦而开始变得不那么流行时,他们意识到,哦,天哪,我们需要回到IBM一直以来所做的事情。 Big servers, dumb clients, and simple deployments. 大型服务器,笨拙的客户端和简单的部署。 But, they couldn't call it that because the industry wouldn't have accepted that and Microsoft didn't want that, so they called it The Cloud (insert bum, bum, bum music here) . 但是,他们不能这样称呼,因为业界不会接受这一点,而微软也不希望这样,所以他们称其为The Cloud (在此处插入流浪汉,流浪汉,流浪汉音乐)

So, fast-forward to SOAP. 因此,快进到SOAP。 People wanted to be able to transfer complex objects over the wire and not have to deserialize them and they wanted flexibility of protocol. 人们希望能够通过电线传输复杂的对象, 不必对它们进行反序列化因此他们希望协议具有灵活性。 Well, SOAP gave you both, Microsoft generates the client representation and deserialization and the WCF layer allows real flexibility of protocol, whereas ReST can only be transmitted over HTTP because it uses the standard verbs. 嗯,SOAP给了你们两个,Microsoft生成了客户端表示和反序列化并且WCF层提供了协议的真正灵活性,而ReST 只能通过HTTP传输,因为它使用了标准动词。

So, the real answer to your question is, what do you need? 因此,您问题的真正答案是,您需要什么?

  1. SOAP is heavier and often less performant on very large data sets than ReST because it's not a native operation for the browser and the envelope is large. SOAP比ReST更大,并且在非常大的数据集上的性能通常较差,因为它不是浏览器的本机操作, 并且信封很大。 But then again, how much data should you really be transferring to the client?!? 但是话又说回来,您真正应该向客户机传输多少数据?
  2. Do you want the one click generation of the client-side model? 您是否需要一键式生成客户端模型? Then use SOAP. 然后使用SOAP。
  3. Do you want to make the API more accessable to other programming paradigms? 您是否想使API更易于访问其他编程范例? Then use ReST. 然后使用ReST。
  4. Do you want to go down the way of the rest of the industry at the moment? 您现在是否要沿途其他行业? Then use ReST. 然后使用ReST。

There is so much more discussion to be had but that should get you started. 还有更多的讨论要讨论,但这应该可以帮助您入门。 ReST is not better than SOAP, it's different, and it solves a different set of problems. ReST并不比SOAP 更好 ,它与众不同,并且解决了一系列不同的问题。 Do not let yourself, or others talk you into, Law of the instrument . 不要让自己或其他人说服乐器定律

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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