фон:Метод вызова из ASP .NET в COM не удается
У меня есть устаревшие приложения, написанные на ASP (VBScript), который называют COM-компоненты, написанные в VB6. Мы обновляемся поэтапно и должны сначала обновить COM-компоненты до .NET, поддерживая совместимость с ASP.
Ситуация:
- Я создал образец класса .NET и подвергал его COM системы, используя различные атрибуты согласно документации MSDN
- Я могу создать экземпляр класса
- Я могу чтобы вызвать нужный метод на классе
Проблема:
- Значения аргументов не отправляются методу COM. например все числовые типы имеют значение 0 внутри метода; все ссылочные типы имеют нулевое значение внутри метода. Литеральные строки передаются правильно методу. Однако строковые переменные не передаются.
- Такая же проблема с возвращаемым значением. Независимо от значения, возвращаемого методом, переменная ASP имеет значение по умолчанию (0 или null в зависимости от ситуации).
COM Код
<ComVisible(True)>
<InterfaceType(ComInterfaceType.InterfaceIsIDispatch)>
Public Interface IClass1
Function Triple(ByVal input As String) As Integer
End Interface
<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ClassInterface(ClassInterfaceType.None)>
Public Class Class1
Inherits ServicedComponent
Implements IClass1
Public Sub New()
' needed for COM
End Sub
Public Function Triple(input As String) As Integer Implements IClass1.Triple
IO.File.WriteAllText("C:\TestCOM.Class1_Triple.log", String.Format("[{0:s}] Input: {1}", Date.Now, input)) ''' this file is updated; so I know method is being called.
Return 97
End Function
End Class
Alternate COM код
<ComVisible(True)>
<ProgId("TESTCOM.Class1")>
<ComClass("E26FE8A0-8AC7-4824-9776-30ECDD473AA3")>
Public Class Class1
'Inherits ServicedComponent
'Implements IClass1
Public Sub New()
' needed for COM
End Sub
Private Const LogMessageFormat As String = "[{0:s}] Input: {1}, {2}" + vbCrLf
Public Function Triple(csinput As String, nInput As Integer) As Integer 'Implements IClass1.Triple
IO.File.AppendAllText("C:\TestCOM.Class1_Triple.log",
String.Format(LogMessageFormat, Date.Now, if(csinput isnot Nothing, csinput, "**NULL**"), nInput))
Return 97
End Function
End Class
ASP код
dim testNETCOM
set testNETCOM = Server.CreateObject("TESTCOM.Class1")
' ** use this to check if there was any error during instantiation
If Err.Number <> 0 Then
Response.Redirect("http://"&Err.Description&"/")
'Response.Write (Err.Description& "<br><br>")
else
'Response.Redirect("http://no-error/")
End If
' ** use this to check if object is actually instantiated
if testNETCOM is nothing then
Response.Redirect("http://no-com/")
else
'Response.Redirect("http://yes-com/")
end if
dim nInput
set nInput = 41
dim nOutput
set nOutput = -1
set nOutput = CLng(testNETCOM.Triple("test message")) ' this string is received in the method
set nOutput = CLng(testNETCOM.Triple(CStr(nInput))) ' this string is not received in the method
' ** use this to check if return value is what we expected
if nOutput <> 0 then
Response.Redirect("http://test/")
else
Response.Redirect("http://notest/") ''' **this happens**
end if
Опасайтесь, что тип VB6 Long .Net Тип System.Int32 или VB Integer. Кроме того, компилятор VB.Net поможет вам создать свой COM-класс, не требуя создания интерфейсов, если вы примените [ComClassAttribute] (https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.comclassattribute (v = vs.110) .aspx # Примеры) для класса. – TnTinMn
Хороший вопрос о разных типах данных.Однако я обновил код, проблема остается. – bigbyte
Моей главной задачей было дать возможность компилятору разоблачить ваш класс в COM, поскольку я верю, что больше, чем я, с этим материалом. В любом случае, я думаю, что все, что вам нужно сделать, это применить уникальный атрибут для вашего класса, а также интерфейс. Используйте VS-инструмент для этого, чтобы сделать его простым. Инструменты Меню-> Создать GUID-> выбрать формат 6 (под VS 2013) -> копировать. Затем вставьте в класс, повторите для интерфейса. – TnTinMn