ASP消耗Web服务,记录集对象怎么办?

时间:2020-03-05 18:51:04  来源:igfitidea点击:

目前,我运行的是一个经典的(旧的)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用于数据层呢?这样,可以在升级站点时重新使用它。

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

解决方案

回答

首先,这是本周我最喜欢的建议:如果是本地对象,请不要像对待Web Service那样对待它,否则我们将付出非常高的性能价格。本质上,请勿在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 <MyData>)实际上在Web Service调用期间转换为Array。请记住,Web服务不会返回对象(数据+行为),而只会返回数据结构(或者序列)。因此,列表和数组之间几乎没有区别。

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

情况有所不同;因为要转换已经使用ADO的现有站点,所以ADO.NET数据集可能是最佳的升级路径。 ADO.NET和ADO非常相似,因此直接更新可能会更容易。这取决于网站的构建方式。

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

祝你好运。

回答

我建议在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经典。

回答

与其分层次思考,不如尝试通过应用程序获取垂直切片并将其转换为.net。这样,我们将获得用.net编码的全部功能,而不是不连贯的部分。在不改善用户体验或者添加功能的情况下替换完美工作的代码有何商业价值?

我们可能还会考虑要通过直接ado调用放弃Web Service的性能之间的权衡。 Web服务是一个很好的解决方案,可以解决多个不相交的应用程序/团队访问一个通用模式的问题。它们不会使单个隔离的应用程序更易于维护,而只会变得更慢,更复杂。

回答

如果我们想坚持使用经典ASP,那么我建议我们通过ASP类创建数据库处理对象,然后仅使用该对象创建记录集即可。这将集中数据库处理代码并使之集中,以便我们仅需在单个位置处理SQL Injection攻击。

一个简单的例子。

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

当然,我们可以扩展基本类来处理参数化的存储过程,或者不进行处理以及更多验证等。

回答

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

要从Visual Studio(例如Microsoft Visual C2005 Express Edition)创建COM Interop程序集,请执行以下操作:

  • 创建一个新的类库项目
  • 在"签名"下,启用对程序集签名并创建或者选择现有的强名称密钥文件
  • 将.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重新注册

也可以看看:

  • 将.NET Framework组件暴露给COM(MSDN)
  • CodeProject:从ASP页面调用.NET组件

回答

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

将代码移至.net并不能使其更好。在页面中添加数据库代码还不错。特别是在id的情况下,我们所谈论的只是一个只有几个开发人员的小型网站。成千上万的站点使用该技术来处理数十亿美元的交易。现在,未参数化的动态sql不好,我们应该消除这种情况,但这不需要重写应用程序或者.net即可。我总是很好奇为什么人们将.net视作对他们应用程序的实际改进。 COM模型中存在的大多数不良代码和不良习惯只是在转换过程中向前传播。

我们或者需要致力于创建一个真正有凝聚力的,最少耦合的OO设计;或者或者只是继续前进,因为那还不算太糟。