【问题标题】:asp consuming a web service, what do do with recordset object?使用 Web 服务的 asp,如何处理记录集对象?
【发布时间】:2010-09-08 11:47:03
【问题描述】:

目前我运行一个经典(旧)ASP 网页,其中记录集对象直接用于糟糕的旧 spagethi 代码风格。

我正在考虑在 asp.net 中实现一个数据层作为 Web 服务以提高可管理性。这也是将网站升级到 asp.net 的第一步。 该网站本身暂时保持 ASP...

谁能推荐一种用 Web 服务兼容类型(如数组或其他东西)替换记录集对象类型的好方法? 下面用什么替换?:

set objRS = oConn.execute(SQL)
while not objRS.eof
   ...
   name = Cstr(objRS(1))
   ...
wend

还有多个记录集可以替换为? 我在说:

 set objRS = objRs.nextRecordset 

有人经历过这个并且可以推荐吗?

@AdditionalInfo - 你要求的 :-)

让我从头开始。 现状: 我有一个旧的 ASP 网站,其中包含通过存储过程从数据库中提取的经典分层内容(标题、部分、小节、内容),并且内容页面也在数据库中(指向 html 文件的链接)。

现在不好的是,ASP 代码遍布在许多 .asp 文件中,所有文件都进行自己的数据库连接、读取、写入(您必须注册内容)。最近我们遇到了 SQL 注入攻击的问题,所以我被要求修复它。

可以去更改所有的 .asp 页面以防止 sql 注入,但这太疯狂了。所以我想建立一个数据层——所有页面都使用这个层来访问数据库。曾经修复和更新数据库访问代码的地方。

做出这个决定,我认为 asp.net 升级还很遥远,为什么不开始使用 asp.net 作为数据层呢?这样在升级站点时可以重复使用它。

这让我想到了上面的问题!

【问题讨论】:

  • 你能给我们更多的例子和信息吗?很难准确理解您在这里尝试做什么。

标签: asp.net web-services asp-classic


【解决方案1】:

可惜我在 2008 年没有看到这个问题。 对我来说,您的网站似乎正在使用 Justa 框架。 简单的方法是修改 Justa 代码以将搜索和数据输入提交到 urlencode。 我做到了,并且完美地为我工作。

其余代码足够安全,可以防止任何类型的 os SQL 注入或其他尝试进入数据库。

【讨论】:

    【解决方案2】:

    应该使用参数化的 sql 查询来处理 Sql 注入。这不仅会消除安全风险,还会显着提高数据库性能,因为它将能够重用执行计划,而不是每次都重新计算它。通过字符串替换来处理它的建议是愚蠢的。 VB 在处理字符串方面很糟糕,那些“替换”语句在性能和内存方面会非常昂贵(而且,你实际上只需要处理 ' 字符)

    将代码移至 .net 并不能让它变得更好。在你的页面中有 db 代码还不错;特别是如果您正在谈论一个只有几个开发人员的小型网站。数以千计的网站使用这种技术来处理数以亿计的交易。现在,未参数化的动态 sql 很糟糕,您应该努力消除它,但这不需要重写应用程序或 .net 即可。我总是很好奇为什么人们将 .net 视为对其应用程序的事实上的改进。 COM 模型中存在的大多数不良代码和不良习惯只是在转换过程中向前传播。

    您要么需要致力于创建一个真正内聚、最小耦合的 OO 设计;要么或者只是保持你正在做的事情,因为它并不是那么糟糕。

    【讨论】:

    • 我同意 - 在我的情况下让 .net 发疯是没有意义的,ASP 工作正常。现在,我在数据层类中对查询进行了参数化以进行集中维护。使用 COM 只会增加我不需要的复杂性。
    【解决方案3】:

    另一种选择是使用 COM 互操作在 .NET 中创建可从经典 ASP 调用的程序集。

    从 Visual Studio 创建 COM 互操作程序集(例如 Microsoft Visual C# 2005 Express Edition):

    • 创建一个新的类库项目
    • 打开项目属性

      • 在 Application 下选择 Assembly Information... 并启用“Make assembly COM-Visible”
      • 在签名下启用对程序集进行签名并创建或选择现有的强名称密钥文件
    • 编写和构建库

      • COM 互操作类必须具有默认构造函数,并且仅发布非静态类和方法
    • 将 .dll 复制到所需的文件夹/机器

    • 使用 RegAsm 为 COM 注册 .dll

    例如(根据需要调整):

    "C:\Windows\Microsoft.NET\Framework\v2.0.50727\RegAsm.exe" "C:\path\to\assembly.dll" /tlb /codebase
    
    • 从 ASP 调用程序集

    例如(根据需要调整):

    Dim obj, returnValue
    Set obj = Server.CreateObject("MyProject.MyClass")
    returnValue = obj.DoSomething(param1, param2)
    

    注意:

    • 程序集在更新时必须通过 RegAsm 重新注册

    另见:

    【讨论】:

      【解决方案4】:

      如果您想坚持使用经典 ASP,那么我建议您通过 ASP 类创建一个数据库处理对象,然后使用该对象来创建记录集。这将集中您的数据库处理代码并使您只需在一个位置处理 SQL 注入攻击。

      一个简单的例子。

      Class clsDatabase
      
          Private Sub Class_Initialize()
              If Session("Debug") Then Response.Write "Database Initialized<br />"
          End Sub
      
          Private Sub Class_Terminate()
              If Session("Debug") Then Response.Write "Database Terminated<br />"
          End Sub
      
          Public Function Run(SQL)
              Set RS = CreateObject("ADODB.Recordset")
              RS.CursorLocation = adUseClient
              RS.Open SQLValidate(SQL), Application("Data"), adOpenKeyset, adLockReadOnly, adCmdText
              Set Run = RS
              Set RS = nothing
          End Function
      
          Public Function SQLValidate(SQL)
              SQLValidate = SQL
              SQLValidate = Replace(SQLValidate, "--", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, ";", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, "SP_", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, "@@", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, " DECLARE", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, "EXEC", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, " DROP", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, " CREATE", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, " GRANT", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, " XP_", "", 1, -1, 1)
              SQLValidate = Replace(SQLValidate, "CHAR(124)", "", 1, -1, 1)
          End Function
      End Class
      

      然后要使用它,您可以将调用更改为:

      Set oData = new clsDatabase
      Set Recordset = oData.Run("SELECT field FROM table WHERE something = another")
      Set oData = nothing
      

      当然你可以扩展基本类来处理参数化的存储过程或什么不是和更多的验证等。

      【讨论】:

      • 嗨天高!这就是我最终做的。坚持使用 ASP 代码并引入一个类来处理与数据库有关的所有事情。谢谢!
      【解决方案5】:

      与其分层思考,不如尝试通过应用程序进行垂直切片并将其转换为 .net。这样,您将获得在 .net 中编码的整个功能,而不是不相交的部分。在不改善用户体验或添加功能的情况下替换完美运行的代码有什么商业价值?

      您还可以考虑使用 Web 服务而不是直接 ado 调用来权衡性能。 Web 服务是解决多个不相交的应用程序/团队访问公共模式问题的一个很好的解决方案;它们不会使单个孤立的应用程序更易于维护,只会更慢和更复杂。

      【讨论】:

      • 感谢您的考虑!我也在考虑这个问题。不幸的是,数据库访问代码分布在许多 .asp 文件中,所以我不得不做很多垂直切片并最终覆盖大部分站点。
      【解决方案6】:

      我建议在您的 ASP 代码中使用 XmlHttp 类。

      假设您在 MyService.asmx 中有一个与此类似的 ASMX Web 服务:

      [WebMethod]
      public string HelloWorld()
      {
        return "Hello World";
      }
      

      你可以在 ASP 中这样称呼它:

      Dim xhr
      
      Set xhr = server.CreateObject("MSXML2.XMLHTTP")
      
      xhr.Open "POST", "/MyService.asmx/HelloWorld", false
      xhr.SetRequestHeader "content-type", "application/x-www-form-urlencoded"
      xhr.Send
      
      Response.Write(xhr.ResponseText)
      

      ResponseText 将是以下的 XML 响应:

      <string>Hello World</string>
      

      假设您的服务返回了一个数据集合,您可以使用 XPath 或任何其他 XML 处理技术/库对其进行迭代。

      谷歌搜索 MSXML2 可能会回答您的任何具体问题,因为它是 ASP 经典版特有的。

      【讨论】:

        【解决方案7】:

        首先我本周最喜欢的建议是:如果您的 Web 服务是本地对象,请不要将其视为本地对象,否则您将付出非常高昂的性能代价。本质上,不要在您的 Web 应用程序中做这样的事情:

        MyDataWebService ws = new MyDataWebService();
        foreach(DataItem item in myData)
        {
            ws.Insert(item);
        }
        

        您应该始终希望尽量减少对您的 Web 服务(和 SQL)的调用:

        MyDataWebService ws = new MyDataWebService();
        ws.Insert(myData); // Let the web service process the whole set at once.
        

        现在,就用于 Web 服务调用的数据类型而言,您基本上有两种选择:

        • 数据集
        • 其他所有内容(数组)

        从 Web 服务返回的大多数集合(如 List)实际上在 Web 服务调用期间转换为数组。请记住,Web 服务不返回对象(数据 + 行为),而只是返回数据结构(或一系列)。因此,List 和 Array 之间几乎没有区别。

        DataSet 是更复杂的类;他们使用自己的自定义序列化程序,并且几乎可以在调用应用程序中完全重新创建。使用这样的 DataSet 需要付出性能成本,因此我通常不建议在大多数情况下使用它。使用数组来回传递数据往往更高效,而且坦率地说,它更容易做到。

        你的情况有点不同;因为您正在转换已使用 ADO 的现有站点,所以 ADO.NET 数据集可能是您最好的升级路径。 ADO.NET 和 ADO 非常相似,因此直接更新可能会更容易。这在某种程度上取决于您的网站是如何构建的。

        对于您问题的最后一部分,DataSet 确实支持类似于 ADO 的 Recordset 的多个记录集。它们被称为数据表。每个 DataSet 至少有一个 DataTable,您可以按任意顺序读取它们。

        祝你好运。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-02-14
          相关资源
          最近更新 更多