I am attempting to incrementally take a legacy application into current technologies. I have a C++ COM+ library using ADO on a server. A VB6 application is using the Recordset from a COM+ object based on the aforementioned library. I want to remove the COM+ layer, so I have created a ReST web service with the ASP.NET Web API project type. I cannot seem to return a Recordset like I would other data types using the HTTP results built into C# (i.e. Ok and BadRequest). I've been trying to accomplish this through Recordset persistence. I save the Recordset as a stream as follows:
ADODB._Recordset rs;string rsString;SomeLibrary sl = new SomeLibrary();rs = (ADODB._Recordset)sl.SomeMethod();Stream stream = new Stream();rs.Save(stream, PersistFormatEnum.adPersistXML);rs.Close();rsString = stream.ReadText();return Ok(rsString);
The C# client tries to take this persisted ADO Recordset and re-create the object like so:
_Recordset ret = null;string strResponse = string.Empty;Does things to call out to the ReST web service...ret = new Recordset();byte[] rsByteArray = Encoding.ASCII.GetBytes(strResponse);ret.Open(new MemoryStream(rsByteArray));
On the last line, I get the following error:
Arguments are of the wrong type, are out of acceptable range, or are in conflict with one another.
The persisted XML looks like the following:
<xml xmlns:s='uuid:BDC6E3F0-6DA3-11d1-A2A3-00AA00C14882' xmlns:dt='uuid:C2F41010-65B3-11d1-A29F-00AA00C14882' xmlns:rs='urn:schemas-microsoft-com:rowset' xmlns:z='#RowsetSchema'><s:Schema id='RowsetSchema'><s:ElementType name='row' content='eltOnly' rs:CommandTimeout='600' rs:ReshapeName='DSRowset1'><s:AttributeType name='ID' rs:number='1'><s:datatype dt:type='int' dt:maxLength='4' rs:precision='10' rs:fixedlength='true' rs:maybenull='false'/></s:AttributeType><s:AttributeType name='c1' rs:name='Some Date' rs:number='2' rs:nullable='true'><s:datatype dt:type='dateTime' rs:dbtype='timestamp' dt:maxLength='16' rs:scale='3' rs:precision='23' rs:fixedlength='true'/></s:AttributeType><s:AttributeType name='Status' rs:number='3' rs:nullable='true'><s:datatype dt:type='ui1' dt:maxLength='1' rs:precision='3' rs:fixedlength='true'/></s:AttributeType><s:AttributeType name='c3' rs:name='File Name' rs:number='4' rs:nullable='true'><s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='2000'/></s:AttributeType><s:AttributeType name='c4' rs:name='User ID' rs:number='5'><s:datatype dt:type='string' rs:dbtype='str' dt:maxLength='32' rs:maybenull='false'/></s:AttributeType><s:extends type='rs:rowbase'/></s:ElementType></s:Schema><rs:data><z:row ID='3319' c1='2017-06-26T08:14:46' Status='2' c3='somefile.XML' c4='domain\\user'/></rs:data></xml>
The objective is to have an ADO Recordset to send back to the VB6 application so that it never knows that the implementation changed other than maybe a new reference to the new C# library instead of the COM+ library.
Is there a bug in what I've written or is this just not possible? If not possible, does anyone know a different path I can take to try to accomplish this task?
EDIT:
The answer on this question was definitely helpful. When I finally got it working, I changed the server to the following:
ADODB.Stream stream = new ADODB.Stream();rs.Save(stream, PersistFormatEnum.adPersistXML);rs.Close();rsString = stream.ReadText();return Ok(rsString);
And the client to the following:
_Recordset ret = null;string strResponse = string.Empty;Does things to call out to the ReST web service...if (!string.IsNullOrEmpty(strResponse)){ strResponse = strResponse.Replace("\\t", "").Replace("\\r\\n", "").Replace("\"", ""); ret = new Recordset(); ADODB.Stream stream = new ADODB.Stream(); stream.Open(); stream.WriteText(strResponse); stream.Position = 0; ret.Open(stream);}return ret;
The VB6 module can now accept data as if it received it from the COM+ object. I hope this helps someone else that needs to update their technology in cheap increments.