There may be times when you need to call a library in order to get the data you desire. In my situation, I needed to call an external dll that would return data to OWS from a secure web service and doing a simple SOAP request would not cut it. Anyway , talk is cheap, lets get started..
To begin create a new Class Library in visual studio and name it (For this example I named mine DDC.OWS.QueryWebService), From here you'll want to ad references to the external dll you will be calling as well as r2i.OWS.Engine, R2i.OWS.Framework and System.Xml dlls.
Now lets start writing some code:
Open up your class and add these to your imports:
Imports System.Xml
Imports System.Xml.XPath
Imports r2i.OWS.Utilities
Imports r2i.OWS
Imports r2i.OWS.Queries
Write your class in the 'Queries' Namespace and Inherit the QueryBase class from the r2i.OWS.Queries class.
Namespace Queries
Public Class DDCQuery
Inherits QueryBase
This next part is Very Important! (well everything’s important here to get this to work, but you get the idea) This property is how OWS knows to call your dll, and change 'R2IQUERY' to whatever you wish.
Public Overrides ReadOnly Property QueryTag() As String
Get
Return "<R2IQUERY>"
End Get
End Property
Our next property will give OWS the XML format we will make our queries in. Include here any parameters you will give the query
Public Overrides ReadOnly Property QueryStructure() As String
Get
Dim s As String = ""
s &= "<R2IQUERY>" & vbCrLf
s &= " <METHODNAME></METHODNAME>" & vbCrLf
s &= " <USERID></USERID>" & vbCrLf
s &= " <CLASSID></CLASSID>" & vbCrLf
s &= "</R2IQUERY>"
Return s
End Get
End Property
As you can see our query takes a Method name, UserId, and ClassId as parameters. Now for our first function, we will create a method that will return a sorted list; this will read our parameters and store them into one location we can easily access.
Private Function GetData_XML_Method(ByRef Source As String) As SortedList
Dim srt As New SortedList
Dim strUserId As String = XMLPropertyParse_Quick(Source, "userid")
If Not strUserId Is Nothing Then
srt.Add("userId", Integer.Parse(strUserId))
End If
Dim strClassId As String = XMLPropertyParse_Quick(Source, "classid")
If Not strClassId Is Nothing Then
srt.Add("classId", Integer.Parse(strClassId))
End If
Return srt
End Function
With these parts out of the way we can now create our handler that returns our data. Add this method and make the changes to the case statement to call your dll function.
Public Overrides Function Handle_GetData(ByRef Caller As Engine, ByVal isSubQuery As Boolean, ByVal Query As String, ByVal FilterField As String, ByVal FilterText As String, ByRef DebugWriter As Framework.Debugger, ByVal isRendered As Boolean, Optional ByVal timeout As Integer = -1, Optional ByVal CustomConnection As String = Nothing, Optional ByRef IsSuccessful As Boolean = True, Optional ByRef FailureMessage As String = Nothing) As System.Data.DataSet
Dim debug As Boolean = False
Dim traceDebug As Boolean = Caller.xls.enableQueryDebug_Log
Dim errorDebug As Boolean = Caller.xls.enableQueryDebug_ErrorLog
Dim thrownError As Boolean = False
Dim ds As New DataSet
Dim errorStr As String = Nothing
IsSuccessful = True
If Not DebugWriter Is Nothing Then
debug = True
Else
If traceDebug Then
If DebugWriter Is Nothing Then
DebugWriter = New r2i.OWS.Framework.Debugger
End If
End If
End If
Try
Dim strDebug As String = ""
Dim strMethod As String = XMLPropertyParse_Quick(Query, "methodname")
Dim settings As SortedList = GetData_XML_Method(Query)
Select Case strMethod.ToLower
Case "MethodName"
If settings.ContainsKey("userId") Then
Dim userId As Integer = CType(settings("userId"), Integer)
Handlers.DDCAssignStudentToSection.HandleRequest(userId)
End If
Case " MethodName"
If settings.ContainsKey("userId") Then
Dim userId As Integer = CType(settings("userId"), Integer)
ds = Handlers.DDCGetAddressListByUserId.HandleRequest(userId)
End If
End Select
Catch ex As Exception
EngineSingleton.Instance(Caller.Context).SortStatus(Caller.ModuleID, Caller.UserID) = Nothing
errorStr = ex.ToString
errorStr = "Error getting Dataset, DDCQUERY: " + errorStr
FailureMessage = errorStr
End Try
If Not errorStr Is Nothing Then
thrownError = True
IsSuccessful = False
If thrownError AndAlso (debug OrElse (errorDebug AndAlso thrownError) OrElse traceDebug) AndAlso DebugWriter Is Nothing Then
DebugWriter = New r2i.OWS.Framework.Debugger
End If
Try
If debug OrElse (errorDebug AndAlso thrownError) OrElse traceDebug Then
DebugWriter.AppendBlock(Caller.ModuleID, "Error", "error", False, errorStr, True)
End If
Catch ex As Exception
End Try
Else
Try
FailureMessage = ""
If debug OrElse traceDebug Then
DebugWriter.AppendHeader(Caller.ModuleID, "Tables", "tables", False)
Try
Dim dbgX As New Text.StringBuilder
Dim tbl As DataTable
For Each tbl In ds.Tables
dbgX.Append(tbl.TableName & " - <i> Rows:</i> <b>" & tbl.Rows.Count & "</b> <i>Columns:</i> <b>" & tbl.Columns.Count & "</b><br><ul>")
Dim col As DataColumn
For Each col In tbl.Columns
dbgX.Append("<li><b>" & col.ColumnName & "</b> <i>" & col.DataType.ToString & "</i></li>")
Next
dbgX.Append("</ul><br>")
Next
DebugWriter.Append(dbgX.ToString)
Catch ex As Exception
End Try
DebugWriter.AppendFooter(False)
End If
Catch ex As Exception
End Try
End If
If Not isSubQuery Then
Try
'Handle custom paging if required here
If Not ds Is Nothing AndAlso ds.Tables.Count > 0 Then
If Caller.xls.enableCustomPaging = True Then
'CHECK FOR TABLE 1 COLUMN 0 ROW 0
If ds.Tables.Count > 1 Then
'WE HAVE OUR TABLE
If ds.Tables(1).Rows.Count > 0 Then
'WE HAVE OUR ROW
Try
If Not IsDBNull(ds.Tables(1).Rows(0).Item(0)) Then
Caller.TotalRecords = ds.Tables(1).Rows(0).Item(0)
Else
Caller.TotalRecords = ds.Tables(0).Rows.Count
End If
Catch ex As Exception
End Try
Else
Caller.TotalRecords = ds.Tables(0).Rows.Count
End If
Else
Caller.TotalRecords = ds.Tables(0).Rows.Count
End If
Else
Caller.TotalRecords = ds.Tables(0).Rows.Count
End If
'VERSION: 1.8.1 - Now sets the TotalPages value
If Caller.TotalRecords > 0 Then
If Caller.RecordsPerPage > 0 Then
Caller.TotalPages = Math.Ceiling(CDbl(Caller.TotalRecords) / CDbl(Caller.RecordsPerPage))
Else
Caller.TotalPages = 1
End If
Else
Caller.TotalPages = 0
End If
Else
Caller.TotalRecords = 0
Caller.TotalPages = 0
End If
Catch ex As Exception
thrownError = True
If thrownError AndAlso (debug OrElse (errorDebug AndAlso thrownError) OrElse traceDebug) AndAlso DebugWriter Is Nothing Then
DebugWriter = New r2i.OWS.Framework.Debugger
End If
If debug OrElse errorDebug OrElse traceDebug Then
DebugWriter.AppendBlock(Caller.ModuleID, "Exception", "exception", False, ex.ToString, True)
End If
End Try
End If
Try
If (errorDebug AndAlso thrownError) OrElse traceDebug Then
If Not debug Then
DebugWriter.AppendHeader(Caller.ModuleID, "Statistics", "statistics", False)
DebugWriter.Append("<ul>")
DebugWriter.Append("<li><b>ModuleId</b> <i>" & Caller.ModuleID & "</i></li>")
DebugWriter.Append("<li><b>TabId</b> <i>" & Caller.TabID & "</i></li>")
DebugWriter.Append("<li><b>TabModuleId</b> <i>" & Caller.TabModuleID & "</i></li>")
DebugWriter.Append("<li><b>Filter</b> <i>" & Caller.xls.filter & "</i></li>")
DebugWriter.Append("<li><b>Filter Field</b> <i>" & FilterField & "</i></li>")
DebugWriter.Append("<li><b>Filter Text</b> <i>" & FilterText & "</i></li>")
DebugWriter.Append("<li><b>Current Page</b> <i>" & (Caller.PageCurrent + 1) & "</i></li>")
DebugWriter.Append("<li><b>Page Size</b> <i>" & Caller.RecordsPerPage & "</i></li>")
DebugWriter.Append("<li><b>Total Records</b> <i>" & Caller.TotalRecords & "</i></li>")
DebugWriter.Append("<li><u>Form</u><br><ol>" & Caller.ShowForm("<li>", "</li>") & "</ol></li>")
DebugWriter.Append("<li><u>Session</u><br><ol>" & Caller.ShowSession("<li>", "</li>") & "</ol></li>")
DebugWriter.Append("<li><u>Cookies</u><br><ol>" & Caller.ShowCookies("<li>", "</li>") & "</ol></li>")
DebugWriter.Append("<li><u>ViewState</u><br><ol>" & Caller.ShowViewState("<li>", "</li>") & "</ol></li>")
DebugWriter.Append("</ul>")
DebugWriter.AppendFooter(False)
If (errorDebug AndAlso thrownError) OrElse traceDebug Then
If traceDebug Then
'Controller.AddLog(Caller.ConfigurationID, Caller.UserID, "Automated Debug - Trace", DebugWriter.ToString, Caller.Session.SessionID)
ElseIf (errorDebug AndAlso thrownError) Then
'Controller.AddLog(Caller.ConfigurationID, Caller.UserID, "Automated Debug - Query Error", DebugWriter.ToString, Caller.Session.SessionID)
End If
If Not debug Then
DebugWriter.Close()
DebugWriter = Nothing
End If
End If
End If
End If
Catch ex As Exception
End Try
Return ds
End Function
Now also note that your dll MUST return data in a dataset if you are expecting back data. Otherwise it is completely fine to have method calls that don’t return data.
At this point you can build your library and add this wrapper to the bin folder in dnn. From here remember what the dll’s name is, we need to edit the openwebstudio.config file.
Find the Queries node in this document and Add this:
<run name="R2iQuery" type="DDC.OWS.QueryWebService.Queries.DDCQuery, DDC.OWS.QueryWebService" />
Where R2IQuery is the root node of the xml query call,
DDC.OWS.QueryWebSrvice.Queries.DDCQuery is the path to the class with the query,
And DDC.OWS.QueryWebService is the dll name.
Save the config file.
Now whenever you want to use this and call your library in OWS, do a query template or a simple query and include parameters in your query structure:
<R2IQUERY>
<METHODNAME></METHODNAME>
<USERID></USERID>
<CLASSID></CLASSID>
</R2IQUERY>
That’s it!