468,242 Members | 1,614 Online
Bytes | Developer Community
New Post

Home Posts Topics Members FAQ

Post your question to a community of 468,242 developers. It's quick & easy.

How to use ISAXXMLReader in ATL Server Web Service Project

Hi,

In my current ATL server project, I have to parse the
input in the client application's request to find out
the different combination of parameters, instead of
using SOAP. For this reason, I am not using ATL server
web service project. On client side, I use POST to send
XML to web server. I know I should use ISAXXMLReader in
the server program. I also know that the parser can be
used for many different handlers in the DLL. I found some
example of SAX2 from Microsoft as standalone program.

ISAXXMLReader* pRdr = NULL;
HRESULT hr = CoCreateInstance(
__uuidof(SAXXMLReader),
NULL,
CLSCTX_ALL,
__uuidof(ISAXXMLReader),
(void **)&pRdr);
if(!FAILED(hr))
{
MyContent * pMc = new MyContent();
hr = pRdr->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = pRdr->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
wprintf(L"\nParsing document: %s\n", URL);
hr = pRdr->parseURL(URL);
printf("\nParse result code: %08x\n\n",hr);
pRdr->Release();
delete pMc;
}
This looks like a half COM program. Is this against
ATL Server project? How to make this per thread function?
What should I do to make it safe, thread-safe, no memory
leak, etc. Due to the lack of documents and books, I
cannot find more examples or information. Now, I still
have some trouble in using it in ATL server application.

Coud anyone help?

Thank you very much.

FS Liu

Nov 16 '05 #1
6 4273
Hi

Mostly for SOAP purposes, ATL Server applications already provide a
per-thread ISAXXMLReader.
( You can disable this feature by defining #define ATL_NO_SOAP, but it is ON
by default)
You can access this per-thread ISAXXMLReader in your request handler with
code like below:

CComPtr<ISAXXMLReader> spReader;
HRESULT hRet =
m_spServiceProvider->QueryService(__uuidof(ISAXXMLReader),
__uuidof(ISAXXMLReader), &spReader)

Hope this helps,

--
--
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. It is for newsgroup
purposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:0d****************************@phx.gbl...
Hi,

In my current ATL server project, I have to parse the
input in the client application's request to find out
the different combination of parameters, instead of
using SOAP. For this reason, I am not using ATL server
web service project. On client side, I use POST to send
XML to web server. I know I should use ISAXXMLReader in
the server program. I also know that the parser can be
used for many different handlers in the DLL. I found some
example of SAX2 from Microsoft as standalone program.

ISAXXMLReader* pRdr = NULL;
HRESULT hr = CoCreateInstance(
__uuidof(SAXXMLReader),
NULL,
CLSCTX_ALL,
__uuidof(ISAXXMLReader),
(void **)&pRdr);
if(!FAILED(hr))
{
MyContent * pMc = new MyContent();
hr = pRdr->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = pRdr->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
wprintf(L"\nParsing document: %s\n", URL);
hr = pRdr->parseURL(URL);
printf("\nParse result code: %08x\n\n",hr);
pRdr->Release();
delete pMc;
}
This looks like a half COM program. Is this against
ATL Server project? How to make this per thread function?
What should I do to make it safe, thread-safe, no memory
leak, etc. Due to the lack of documents and books, I
cannot find more examples or information. Now, I still
have some trouble in using it in ATL server application.

Coud anyone help?

Thank you very much.

FS Liu

Nov 16 '05 #2

Hi, Bogdan,

Thank you so much for the example. I still have a problem
about the use of content handler class, MyContent. All the
Microsoft examples use
MyContent * pMc = new MyContent();
I defined a content handler that has member variables for
pairs of node and value. After running spReader->parse(),
I use the resultant pairs in the rest of the program. Is
it a better idea to use
CComPtr<MyContent> pMc;
in ATL Server application project for easier memory
management? To do so, is there any special requirement to
define the content handler MyContent? Here is my code:
CComHeapPtr<CHAR> m_RequestBuffer;// buffer for
client POST data.
CComPtr<ISAXXMLReader> spReader;
HRESULT hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader)
if(!FAILED(hr))
{
CComPtr<MyContent> pMc;
if (!pMc)
return S_ERROR;
hr = spReader->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = spReader->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
VARIANT MyVariant;
MyVariant.vt = VT_BSTR;
MyVariant.bstrVal =
(BSTR)m_RequestBuffer;// ERROR HERE!
hr = spReader->parse(MyVariant);
spReader->Release();//Do we need this here?
ATLTRACE("Node: %s Value:%d\n",pMc->Name,
pMc->Value);
}
On the other hand, given m_RequestBuffer as a dynamically
allocated memory according to the data length of client
POST, I have trouble in packing m_RequestBuffer into a
VARIANT to pass to parse(), because the compiler cannot
convert m_RequestBuffer from CHAR to BSTR (Please read the
comment in the program.) Is there an efficient way (e.g.
data type or class) to get client POST data and pass it to
spReader->parse() directly, without converting from WCS to
MBS or vice versa. Finally, do I have to do clean up
with "spReader->Release();" for the per-thread spReader?

Thank you very much.

-----Original Message-----
Hi

Mostly for SOAP purposes, ATL Server applications already provide aper-thread ISAXXMLReader.
( You can disable this feature by defining #define ATL_NO_SOAP, but it is ONby default)
You can access this per-thread ISAXXMLReader in your request handler withcode like below:

CComPtr<ISAXXMLReader> spReader;
HRESULT hRet =
m_spServiceProvider->QueryService(__uuidof(ISAXXMLReader),
__uuidof(ISAXXMLReader), &spReader)

Hope this helps,

--
--
--
This posting is provided "AS IS" with no warranties, and confers no rights.Please do not send email directly to this alias. It is for newsgrouppurposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:0d****************************@phx.gbl...
Hi,

In my current ATL server project, I have to parse the
input in the client application's request to find out
the different combination of parameters, instead of
using SOAP. For this reason, I am not using ATL server
web service project. On client side, I use POST to send
XML to web server. I know I should use ISAXXMLReader in
the server program. I also know that the parser can be
used for many different handlers in the DLL. I found some example of SAX2 from Microsoft as standalone program.

ISAXXMLReader* pRdr = NULL;
HRESULT hr = CoCreateInstance(
__uuidof(SAXXMLReader),
NULL,
CLSCTX_ALL,
__uuidof(ISAXXMLReader),
(void **)&pRdr);
if(!FAILED(hr))
{
MyContent * pMc = new MyContent();
hr = pRdr->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = pRdr->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
wprintf(L"\nParsing document: %s\n", URL);
hr = pRdr->parseURL(URL);
printf("\nParse result code: %08x\n\n",hr);
pRdr->Release();
delete pMc;
}
This looks like a half COM program. Is this against
ATL Server project? How to make this per thread function? What should I do to make it safe, thread-safe, no memory
leak, etc. Due to the lack of documents and books, I
cannot find more examples or information. Now, I still
have some trouble in using it in ATL server application.

Coud anyone help?

Thank you very much.

FS Liu

.

Nov 16 '05 #3
Please see inlines (look for [Bogdan Crivat])
Hope this helps, let me know if you run into any other issues

--
--
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. It is for newsgroup
purposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:07****************************@phx.gbl...

Hi, Bogdan,

Thank you so much for the example. I still have a problem
about the use of content handler class, MyContent. All the
Microsoft examples use
MyContent * pMc = new MyContent();
I defined a content handler that has member variables for
pairs of node and value. After running spReader->parse(),
I use the resultant pairs in the rest of the program. Is
it a better idea to use
CComPtr<MyContent> pMc;
in ATL Server application project for easier memory
management? To do so, is there any special requirement to
define the content handler MyContent? Here is my code:
[Bogdan Crivat] -- Yes, this should be a smart pointer. The SAX Reader will
AddRef and Release the handler repeatedly. CComPtr is the right way of
ensuring the
life span of the handler object

CComHeapPtr<CHAR> m_RequestBuffer;// buffer for
client POST data.
CComPtr<ISAXXMLReader> spReader;
HRESULT hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader)
if(!FAILED(hr))
{
CComPtr<MyContent> pMc;

[Bogdan Crivat] -- Based on my understanding of your code, I guess a
CreateInstance should appear here. I might be wrong, though
Also, below, you might want to have your own implementation of
ISAXErrorHandler (which can be included in your SAX Handler class)
This would allow you to collect the error and decide later what to do (how
to send the information back to the client).
I might be wrong, as I am not familiar with the SAXErrorHandlerImpl
if (!pMc)
return S_ERROR;
hr = spReader->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = spReader->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
VARIANT MyVariant;
MyVariant.vt = VT_BSTR;
MyVariant.bstrVal =
(BSTR)m_RequestBuffer;// ERROR HERE!
hr = spReader->parse(MyVariant);
spReader->Release();//Do we need this here?
ATLTRACE("Node: %s Value:%d\n",pMc->Name,
pMc->Value);
}
On the other hand, given m_RequestBuffer as a dynamically
allocated memory according to the data length of client
POST, I have trouble in packing m_RequestBuffer into a
VARIANT to pass to parse(), because the compiler cannot
convert m_RequestBuffer from CHAR to BSTR (Please read the
comment in the program.) Is there an efficient way (e.g.
data type or class) to get client POST data and pass it to
spReader->parse() directly, without converting from WCS to
MBS or vice versa.
[Bogdan Crivat]
The Client POST data does not have to be copied. It is available as a stream
interface and
can be passed directly to the SAXXMLReader. See the following code snippet
for an example:

// Create a stream wrapper on top of the HTTP Server Context
CStreamOnServerContext s(m_pRequestInfo->pServerContext);
// Now create a variant that will contain the IUnknown of the IStream object
above
CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
HRESULT hr = spReader->parse(varStream);
If posible, please try to take a look at the atlsoap.h file coming with VS.
That file (the ATL Server SOAP implementation)
has to solve problems similar to the ones you have

Finally, do I have to do clean up
with "spReader->Release();" for the per-thread spReader? [Bogdan Crivat]
No, you don't have to call an extra release. Basically, your code should
look like:
{
CComPtr<ISAXXMLReader> spReader;
m_spServiceProvider->QueryService(..., &spReader);
...
spReader->putContentHandler(...)
...
spReader->parse()
...
}
Let's assume that initially the ref count for the per-thread reader is 1.
QueryService will make it 2.
The destructor of the spReader smart pointer will call Release once and make
it back to 1, therefore ready for being used again on the same thread, with
different
data



Thank you very much.

-----Original Message-----
Hi

Mostly for SOAP purposes, ATL Server applications already

provide a
per-thread ISAXXMLReader.
( You can disable this feature by defining #define

ATL_NO_SOAP, but it is ON
by default)
You can access this per-thread ISAXXMLReader in your

request handler with
code like below:

CComPtr<ISAXXMLReader> spReader;
HRESULT hRet =
m_spServiceProvider->QueryService(__uuidof(ISAXXMLReader),
__uuidof(ISAXXMLReader), &spReader)

Hope this helps,

--
--
--
This posting is provided "AS IS" with no warranties, and

confers no rights.
Please do not send email directly to this alias. It is

for newsgroup
purposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:0d****************************@phx.gbl...
Hi,

In my current ATL server project, I have to parse the
input in the client application's request to find out
the different combination of parameters, instead of
using SOAP. For this reason, I am not using ATL server
web service project. On client side, I use POST to send
XML to web server. I know I should use ISAXXMLReader in
the server program. I also know that the parser can be
used for many different handlers in the DLL. I found some example of SAX2 from Microsoft as standalone program.

ISAXXMLReader* pRdr = NULL;
HRESULT hr = CoCreateInstance(
__uuidof(SAXXMLReader),
NULL,
CLSCTX_ALL,
__uuidof(ISAXXMLReader),
(void **)&pRdr);
if(!FAILED(hr))
{
MyContent * pMc = new MyContent();
hr = pRdr->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = pRdr->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
wprintf(L"\nParsing document: %s\n", URL);
hr = pRdr->parseURL(URL);
printf("\nParse result code: %08x\n\n",hr);
pRdr->Release();
delete pMc;
}
This looks like a half COM program. Is this against
ATL Server project? How to make this per thread function? What should I do to make it safe, thread-safe, no memory
leak, etc. Due to the lack of documents and books, I
cannot find more examples or information. Now, I still
have some trouble in using it in ATL server application.

Coud anyone help?

Thank you very much.

FS Liu

.

Nov 16 '05 #4
Hi, Bogdan,

Thank you very much for the valuable message. After I
declare
CComPtr <MyContent> pContent;
pContent is NULL. Yes, you are right. I should
CreateInstance after this line. So, I change my program
as (a simplified version):
CComPtr <ISAXXMLReader> spReader;
hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader);
CComPtr <MyContent> pContent;
//pContent = new MyContent();
//hr = pContent.CoCreateInstance(
// __uuidof(MyContent), NULL,
// CLSCTX_INPROC_SERVER);
hr = spReader->putContentHandler(pContent);
CStreamOnServerContext s(m_pRequestInfo-
pServerContext); CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
ATLTRACE((char *)(varStream.bstrVal));
hr = spReader->parse (varStream);

When I use
pContent = new MyContent();
to create the instance, VS.NET compiler reports a message
saying "cannot instanciate the class" (I am using a
Japanese version. I don't know the exact wording of the
message in English). Does this mean that I have to include
some header files from VS.NET, such as msxml2.h or
something else? When I use
hr = pContent.CoCreateInstance(__uuidof
(MyContent), NULL, CLSCTX_INPROC_SERVER);
the compiler also complains: there is no associated GUID.
I read atlsoap.h and found the parseFault() function. It
is similar to the above code, except the creation of
content handler. I tried several ways to create an
instance, but failed.

I feel I just have one step further to clearify this
issue, but cannot find enough document. Could you help? By
the way, "ATLTRACE((char *)(varStream.bstrVal));" does
not print the XML string. Do you know why?

Thank you very much.

FS Liu

-----Original Message-----
Please see inlines (look for [Bogdan Crivat])
Hope this helps, let me know if you run into any other issues
--
--
--
This posting is provided "AS IS" with no warranties, and confers no rights.Please do not send email directly to this alias. It is for newsgrouppurposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:07****************************@phx.gbl...

Hi, Bogdan,

Thank you so much for the example. I still have a problem about the use of content handler class, MyContent. All the Microsoft examples use
MyContent * pMc = new MyContent();
I defined a content handler that has member variables for pairs of node and value. After running spReader->parse (), I use the resultant pairs in the rest of the program. Is
it a better idea to use
CComPtr<MyContent> pMc;
in ATL Server application project for easier memory
management? To do so, is there any special requirement to define the content handler MyContent? Here is my code:
[Bogdan Crivat] -- Yes, this should be a smart pointer.

The SAX Reader willAddRef and Release the handler repeatedly. CComPtr is the right way ofensuring the
life span of the handler object

CComHeapPtr<CHAR> m_RequestBuffer;// buffer for
client POST data.
CComPtr<ISAXXMLReader> spReader;
HRESULT hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader)
if(!FAILED(hr))
{
CComPtr<MyContent> pMc;

[Bogdan Crivat] -- Based on my understanding of your

code, I guess aCreateInstance should appear here. I might be wrong, thoughAlso, below, you might want to have your own implementation ofISAXErrorHandler (which can be included in your SAX Handler class)This would allow you to collect the error and decide later what to do (howto send the information back to the client).
I might be wrong, as I am not familiar with the SAXErrorHandlerImpl

if (!pMc)
return S_ERROR;
hr = spReader->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = spReader->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
VARIANT MyVariant;
MyVariant.vt = VT_BSTR;
MyVariant.bstrVal =
(BSTR)m_RequestBuffer;// ERROR HERE!
hr = spReader->parse(MyVariant);
spReader->Release();//Do we need this here?
ATLTRACE("Node: %s Value:%d\n",pMc->Name,
pMc->Value);
}
On the other hand, given m_RequestBuffer as a dynamically allocated memory according to the data length of client
POST, I have trouble in packing m_RequestBuffer into a
VARIANT to pass to parse(), because the compiler cannot
convert m_RequestBuffer from CHAR to BSTR (Please read the comment in the program.) Is there an efficient way (e.g.
data type or class) to get client POST data and pass it to spReader->parse() directly, without converting from WCS to MBS or vice versa.
[Bogdan Crivat]
The Client POST data does not have to be copied. It is

available as a streaminterface and
can be passed directly to the SAXXMLReader. See the following code snippetfor an example:

// Create a stream wrapper on top of the HTTP Server ContextCStreamOnServerContext s(m_pRequestInfo->pServerContext);
// Now create a variant that will contain the IUnknown of the IStream objectabove
CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
HRESULT hr = spReader->parse(varStream);
If posible, please try to take a look at the atlsoap.h file coming with VS.That file (the ATL Server SOAP implementation)
has to solve problems similar to the ones you have

Finally, do I have to do clean up
with "spReader->Release();" for the per-thread spReader?[Bogdan Crivat]
No, you don't have to call an extra release. Basically,

your code shouldlook like:
{
CComPtr<ISAXXMLReader> spReader;
m_spServiceProvider->QueryService(..., &spReader);
...
spReader->putContentHandler(...)
...
spReader->parse()
...
}
Let's assume that initially the ref count for the per- thread reader is 1.QueryService will make it 2.
The destructor of the spReader smart pointer will call Release once and makeit back to 1, therefore ready for being used again on the same thread, withdifferent
data



Thank you very much.

>-----Original Message-----
>Hi
>
>Mostly for SOAP purposes, ATL Server applications already
provide a
>per-thread ISAXXMLReader.
>( You can disable this feature by defining #define

ATL_NO_SOAP, but it is ON
>by default)
>You can access this per-thread ISAXXMLReader in your

request handler with
>code like below:
>
>CComPtr<ISAXXMLReader> spReader;
>HRESULT hRet =
>m_spServiceProvider->QueryService(__uuidof
(ISAXXMLReader), >__uuidof(ISAXXMLReader), &spReader)
>
>Hope this helps,
>
>--
>--
>--
>This posting is provided "AS IS" with no warranties, and confers no rights.
>Please do not send email directly to this alias. It is

for newsgroup
>purposes only.
>
>thanks,
>bogdan
>
>
>
>
>"FS Liu" <fa***********@hotmail.com> wrote in message
>news:0d****************************@phx.gbl...
>> Hi,
>>
>> In my current ATL server project, I have to parse the
>> input in the client application's request to find out
>> the different combination of parameters, instead of
>> using SOAP. For this reason, I am not using ATL

server >> web service project. On client side, I use POST to send >> XML to web server. I know I should use ISAXXMLReader in >> the server program. I also know that the parser can be >> used for many different handlers in the DLL. I found

some
>> example of SAX2 from Microsoft as standalone program.
>>
>> ISAXXMLReader* pRdr = NULL;
>> HRESULT hr = CoCreateInstance(
>> __uuidof(SAXXMLReader),
>> NULL,
>> CLSCTX_ALL,
>> __uuidof(ISAXXMLReader),
>> (void **)&pRdr);
>> if(!FAILED(hr))
>> {
>> MyContent * pMc = new MyContent();
>> hr = pRdr->putContentHandler(pMc);
>> SAXErrorHandlerImpl * pEc =
>> new SAXErrorHandlerImpl();
>> hr = pRdr->putErrorHandler(pEc);
>> static wchar_t URL[1000];
>> mbstowcs( URL, argv[1], 999 );
>> wprintf(L"\nParsing document: %s\n", URL);
>> hr = pRdr->parseURL(URL);
>> printf("\nParse result code: %08x\n\n",hr);
>> pRdr->Release();
>> delete pMc;
>> }
>> This looks like a half COM program. Is this against
>> ATL Server project? How to make this per thread

function?
>> What should I do to make it safe, thread-safe, no memory >> leak, etc. Due to the lack of documents and books, I
>> cannot find more examples or information. Now, I still >> have some trouble in using it in ATL server application. >>
>> Coud anyone help?
>>
>> Thank you very much.
>>
>> FS Liu
>>
>
>
>.
>

.

Nov 16 '05 #5
Hello,
For the construction issue
//hr = pContent.CoCreateInstance(
// __uuidof(MyContent), NULL,
// CLSCTX_INPROC_SERVER);
hr = spReader->putContentHandler(pContent);
This will work only if your class is a registered COM server (and you will
have to pass the GUID of the registered server in CoCreate)

Assuming you wrote a C++ class,

class MyContent : public ISAXContentHandler
{
virtual HRESULT startElement(.....)
.....
}
your code while handling request should look like one of the following:

1. {
MyContent content;
hr = spReader->putContentHandler((ISAXContentHandler*)&content );
...
spReader->parse(...)
...
hr = spReader->putContentHandler(NULL); // disable the reference to
the content handler
}

(or 2.)
{
CComPtr< ISAXContentHandler> spHandler;
GetAHandler(&spHandler)
hr = spReader->putContentHandler(spHandler);
...
spReader->parse(...)
...
hr = spReader->putContentHandler(NULL); // disable the reference to
the content handler
}
HRESULT GetAHandler( ISAXContentHandler** out_ppHandler)
{
MyContent * pNew = new MyContent;
*out_ppHandler = pNew;
return S_OK
}
In this latter case, make sure that Release on MyContent calls "delete
this" when the ref count reaches 0.


On the second issue: CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
ATLTRACE((char *)(varStream.bstrVal)); This will not work for a few reasons:
1 -
assigning an IUnknown* to a CComVariant will invoke CComVariant& operator
=(IUnknown* pSrc );
After this, the type of the variant is VT_UNKNOWN, so using
varStream.bstrVal in a trace is incorrect (and might lead to an access
violation)

2 -
varStream is a stream, that is an IStream implementationm which is
forward-only (can only be read once). ISAXXMLReader->parse will do this
If you would be able to trace the IStream, then ISAXXMLReader will start
parsing at the end of the stream and will find no content
The advantage of the stream approach is that the content is only read once
from the Server context (which means, from the client) and is not copied in
intermediary buffers.

If you want to do the trace, you have at least 3 options:
- (for a complete ATL trace) -- instead of using the stream copy everything
into a BSTR. Trace the BSTR then parse the BSTR to the ISAXXMLReader (the
way
you were initially handling the content). This will create at least one
supplementary copy of the content and might be slow, especially if the
content to be parsed is big

- (IMO, the best and simplest solution) Derive your own class from
CStreamOnServerContext, override the Read virtual with code like:

HRESULT __stdcall Read(void* pDest, ULONG nMaxLen, ULONG* pnRead)
{
HRESULT hRet =__super::Read( pDest, nMaxLen, pnRead);
if( SUCCEEDED(hRet) )
{
char* buff = new char[*pnRead + 1];
strncpy( buff, (char*)pDest, *pnRead);
buff[*pnRead] = 0;
ATLTRACE((char*)pDest);
}
return hRet;
}
- you could write an ISAPI filter that traces the content before getting to
your ISAPI DLL. See the ISAPIFilter sample coming with ATL Server for a
templatye of an ISAPI filter
Hope it work fine for you

--
--
--
This posting is provided "AS IS" with no warranties, and confers no rights.
Please do not send email directly to this alias. It is for newsgroup
purposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:05****************************@phx.gbl... Hi, Bogdan,

Thank you very much for the valuable message. After I
declare
CComPtr <MyContent> pContent;
pContent is NULL. Yes, you are right. I should
CreateInstance after this line. So, I change my program
as (a simplified version):
CComPtr <ISAXXMLReader> spReader;
hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader);
CComPtr <MyContent> pContent;
//pContent = new MyContent();
//hr = pContent.CoCreateInstance(
// __uuidof(MyContent), NULL,
// CLSCTX_INPROC_SERVER);
hr = spReader->putContentHandler(pContent);
CStreamOnServerContext s(m_pRequestInfo-
pServerContext);

CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
ATLTRACE((char *)(varStream.bstrVal));
hr = spReader->parse (varStream);

When I use
pContent = new MyContent();
to create the instance, VS.NET compiler reports a message
saying "cannot instanciate the class" (I am using a
Japanese version. I don't know the exact wording of the
message in English). Does this mean that I have to include
some header files from VS.NET, such as msxml2.h or
something else? When I use
hr = pContent.CoCreateInstance(__uuidof
(MyContent), NULL, CLSCTX_INPROC_SERVER);
the compiler also complains: there is no associated GUID.
I read atlsoap.h and found the parseFault() function. It
is similar to the above code, except the creation of
content handler. I tried several ways to create an
instance, but failed.

I feel I just have one step further to clearify this
issue, but cannot find enough document. Could you help? By
the way, "ATLTRACE((char *)(varStream.bstrVal));" does
not print the XML string. Do you know why?

Thank you very much.

FS Liu

-----Original Message-----
Please see inlines (look for [Bogdan Crivat])
Hope this helps, let me know if you run into any other

issues

--
--
--
This posting is provided "AS IS" with no warranties, and

confers no rights.
Please do not send email directly to this alias. It is

for newsgroup
purposes only.

thanks,
bogdan


"FS Liu" <fa***********@hotmail.com> wrote in message
news:07****************************@phx.gbl...

Hi, Bogdan,

Thank you so much for the example. I still have a problem about the use of content handler class, MyContent. All the Microsoft examples use
MyContent * pMc = new MyContent();
I defined a content handler that has member variables for pairs of node and value. After running spReader->parse (), I use the resultant pairs in the rest of the program. Is
it a better idea to use
CComPtr<MyContent> pMc;
in ATL Server application project for easier memory
management? To do so, is there any special requirement to define the content handler MyContent? Here is my code:


[Bogdan Crivat] -- Yes, this should be a smart pointer.

The SAX Reader will
AddRef and Release the handler repeatedly. CComPtr is the

right way of
ensuring the
life span of the handler object

CComHeapPtr<CHAR> m_RequestBuffer;// buffer for
client POST data.
CComPtr<ISAXXMLReader> spReader;
HRESULT hr = m_spServiceProvider->QueryService(
__uuidof(ISAXXMLReader), &spReader)
if(!FAILED(hr))
{
CComPtr<MyContent> pMc;

[Bogdan Crivat] -- Based on my understanding of your

code, I guess a
CreateInstance should appear here. I might be wrong,

though
Also, below, you might want to have your own

implementation of
ISAXErrorHandler (which can be included in your SAX

Handler class)
This would allow you to collect the error and decide

later what to do (how
to send the information back to the client).
I might be wrong, as I am not familiar with the

SAXErrorHandlerImpl


if (!pMc)
return S_ERROR;
hr = spReader->putContentHandler(pMc);
SAXErrorHandlerImpl * pEc =
new SAXErrorHandlerImpl();
hr = spReader->putErrorHandler(pEc);
static wchar_t URL[1000];
mbstowcs( URL, argv[1], 999 );
VARIANT MyVariant;
MyVariant.vt = VT_BSTR;
MyVariant.bstrVal =
(BSTR)m_RequestBuffer;// ERROR HERE!
hr = spReader->parse(MyVariant);
spReader->Release();//Do we need this here?
ATLTRACE("Node: %s Value:%d\n",pMc->Name,
pMc->Value);
}
On the other hand, given m_RequestBuffer as a dynamically allocated memory according to the data length of client
POST, I have trouble in packing m_RequestBuffer into a
VARIANT to pass to parse(), because the compiler cannot
convert m_RequestBuffer from CHAR to BSTR (Please read the comment in the program.) Is there an efficient way (e.g.
data type or class) to get client POST data and pass it to spReader->parse() directly, without converting from WCS to MBS or vice versa.


[Bogdan Crivat]
The Client POST data does not have to be copied. It is

available as a stream
interface and
can be passed directly to the SAXXMLReader. See the

following code snippet
for an example:

// Create a stream wrapper on top of the HTTP Server

Context
CStreamOnServerContext s(m_pRequestInfo->pServerContext);
// Now create a variant that will contain the IUnknown of

the IStream object
above
CComVariant varStream;
varStream = static_cast<IUnknown*>(&s);
HRESULT hr = spReader->parse(varStream);
If posible, please try to take a look at the atlsoap.h

file coming with VS.
That file (the ATL Server SOAP implementation)
has to solve problems similar to the ones you have

Finally, do I have to do clean up
with "spReader->Release();" for the per-thread spReader?

[Bogdan Crivat]
No, you don't have to call an extra release. Basically,

your code should
look like:
{
CComPtr<ISAXXMLReader> spReader;
m_spServiceProvider->QueryService(..., &spReader);
...
spReader->putContentHandler(...)
...
spReader->parse()
...
}
Let's assume that initially the ref count for the per-

thread reader is 1.
QueryService will make it 2.
The destructor of the spReader smart pointer will call

Release once and make
it back to 1, therefore ready for being used again on the

same thread, with
different
data



Thank you very much.
>-----Original Message-----
>Hi
>
>Mostly for SOAP purposes, ATL Server applications already provide a
>per-thread ISAXXMLReader.
>( You can disable this feature by defining #define
ATL_NO_SOAP, but it is ON
>by default)
>You can access this per-thread ISAXXMLReader in your
request handler with
>code like below:
>
>CComPtr<ISAXXMLReader> spReader;
>HRESULT hRet =
>m_spServiceProvider->QueryService(__uuidof (ISAXXMLReader), >__uuidof(ISAXXMLReader), &spReader)
>
>Hope this helps,
>
>--
>--
>--
>This posting is provided "AS IS" with no warranties, and confers no rights.
>Please do not send email directly to this alias. It is
for newsgroup
>purposes only.
>
>thanks,
>bogdan
>
>
>
>
>"FS Liu" <fa***********@hotmail.com> wrote in message
>news:0d****************************@phx.gbl...
>> Hi,
>>
>> In my current ATL server project, I have to parse the
>> input in the client application's request to find out
>> the different combination of parameters, instead of
>> using SOAP. For this reason, I am not using ATL server >> web service project. On client side, I use POST to send >> XML to web server. I know I should use ISAXXMLReader in >> the server program. I also know that the parser can be >> used for many different handlers in the DLL. I found
some
>> example of SAX2 from Microsoft as standalone program.
>>
>> ISAXXMLReader* pRdr = NULL;
>> HRESULT hr = CoCreateInstance(
>> __uuidof(SAXXMLReader),
>> NULL,
>> CLSCTX_ALL,
>> __uuidof(ISAXXMLReader),
>> (void **)&pRdr);
>> if(!FAILED(hr))
>> {
>> MyContent * pMc = new MyContent();
>> hr = pRdr->putContentHandler(pMc);
>> SAXErrorHandlerImpl * pEc =
>> new SAXErrorHandlerImpl();
>> hr = pRdr->putErrorHandler(pEc);
>> static wchar_t URL[1000];
>> mbstowcs( URL, argv[1], 999 );
>> wprintf(L"\nParsing document: %s\n", URL);
>> hr = pRdr->parseURL(URL);
>> printf("\nParse result code: %08x\n\n",hr);
>> pRdr->Release();
>> delete pMc;
>> }
>> This looks like a half COM program. Is this against
>> ATL Server project? How to make this per thread
function?
>> What should I do to make it safe, thread-safe, no memory >> leak, etc. Due to the lack of documents and books, I
>> cannot find more examples or information. Now, I still >> have some trouble in using it in ATL server application. >>
>> Coud anyone help?
>>
>> Thank you very much.
>>
>> FS Liu
>>
>
>
>.
>

.

Nov 16 '05 #6
Thank you so much. It starts to work.

Best regards.

FS Liu
Nov 16 '05 #7

This discussion thread is closed

Replies have been disabled for this discussion.

Similar topics

1 post views Thread by Maansi Gupta | last post: by
4 posts views Thread by Developer | last post: by
reply views Thread by kermitthefrogpy | last post: by
By using this site, you agree to our Privacy Policy and Terms of Use.