.NET Forum / ASP.NET / Web Services / December 2004
Asynchronous Web Service Method Failure
|
|
Thread rating:  |
Turbo - 10 Dec 2004 21:13 GMT Greetings to all
I have a set of web services that create reports upon request. These reports can take the form of XML Spreadsheets or dynamically generated .pdf files. I call the create report methods async to give the user the opportunity to cancel a long running report. However, any create report method that opens a stream reader (in order to import some XML for a spreadsheet) or writer (in order to generate the XML spreadsheet file) cannot be run async. They run fine synchronously, but for some reason, opening an IO.Stream causes a "there was an error during async processing" error. The interesting thing is, this error is given in a message box, not a typical ASP.NET error page. Any thoughts?
Dan Rogers - 13 Dec 2004 20:44 GMT Some questions,
When you say async - do you mean you have created a one-way SOAP method? (this is the right way to think about async for web services). When you have a one-way method, you don't get to write a response. In other words, async server side methods have a "void" signature always. If you try marking a non-void method with the one way soap attribute, that is an error.
That aside, you should consider using SOAP with attachments if you are returning files (no longe async methods).
I hope this helps
Dan Rogers Microsoft Corporation --------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTe/QkQd8iqbozvTCKTbAiYn3Wy0A== [quoted text clipped - 17 lines] >Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA03.phx.gbl >Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27146
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > >Greetings to all > >I have a set of web services that create reports upon request. These >reports can take the form of XML Spreadsheets or dynamically generated pdf
>files. I call the create report methods async to give the user the >opportunity to cancel a long running report. However, any create report [quoted text clipped - 4 lines] >interesting thing is, this error is given in a message box, not a typical >ASP.NET error page. Any thoughts? Turbo - 15 Dec 2004 19:43 GMT Here is the procedure. I call an asynchronous web service method for a particular report. I don't pass any files, just parameters for the report, such as start date and end date. The web service methods don't return any files, just URL's to the files so I can execute a response.redirect when the web service is done creating the report. Some of my reports are XML spreadsheets, so to avoid have to create the XML from scratch, I use existing files and then add the necessary data elements to them. Within the web service method that is creating the report, I open a streamreader or use the XMLDocument Load method in order to get the static XML loaded into the XMLDocument. When I'm done, I use a streamwriter to create an XmlTextWriter to save the document. These methods work fine when done synchronously, but fail when done async. Only methods that use objects derived from streamreaders and writers fail when run async. I hope I'm making myself clear. The error message box that pops up only occurs during development. It isn't a client issue.
> Some questions, > [quoted text clipped - 52 lines] > >interesting thing is, this error is given in a message box, not a typical > >ASP.NET error page. Any thoughts? Dan Rogers - 16 Dec 2004 19:24 GMT I'm still confused about what you mean by async. How are you invoking them a) when it works, and b) when it doesn't work. Since you are returning values to the caller, I am pretty sure that these are not async server side operations, but you are referring to the non-blocking (beginMethodXX) on the caller side as "async".
is this the case? If so, there is no difference in the way the call is dispatched and handled on the server side - so again, my confusion as to why the stream reader thinks the thread is async.
Something in the description here (topology - e.g. what code are you trying to invoke on what side of a web service method call) is eluding me.
Dan --------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTi3k4zag4FdGNeSzOsg9ucQ1yLug== >X-WBNR-Posting-Host: 65.118.1.233 >From: "=?Utf-8?B?VHVyYm8=?=" <Turbo@discussions.microsoft.com> >References: <4F6A0DC8-92A1-4BB9-9E07-43123A799944@microsoft.com> <00lXKSV4EHA.3388@cpmsftngxa10.phx.gbl>
>Subject: RE: Asynchronous Web Service Method Failure >Date: Wed, 15 Dec 2004 11:43:09 -0800 [quoted text clipped - 13 lines] >Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA03.phx.gbl >Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27228
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > [quoted text clipped - 70 lines] >> >interesting thing is, this error is given in a message box, not a typical >> >ASP.NET error page. Any thoughts? Turbo - 17 Dec 2004 00:31 GMT Let's say I have a web service called wsReportGenerator that has a method called CreateReport. This method will create a .pdf or XML spreadsheet and return the URL of the file created.
Class wsReportGenerator Inherits System.Web.Services.WebService <WebMethod()> Public Function CreateReport() as String
create report logic is here and the file (either .pdf or XML spreadsheet) is is saved to the hard drive somewhere on the server.
return "\ReportFolder\ReportName.pdf" ' virtual location of report
End Function End Class
So, when I call this method where appropriate, it's
dim ws as new wsReportGenerator() or using the proxy from a web reference, ProxyReportGenerator() dim URL as string = wsReportGenerator.CreateReport() Response.Redirect(URL, True)
Because the CreateReport method can take a while to run, I call it asynchronously using a proxy so it looks more like
dim ws as new ProxyReportGenerator() ws.BeginCreateReport(callback, ws)
Obviously I need to check to see if it's finished every now and then so in my callback procedure I have dim URL as string = ws.EndCreateReport(iAsyncResult) I save the URL in a session variable so the next time I check, it's there and I can redirect.
When I call a method that opens stream readers or writers somewhere within, I have no problem running them using the first way, which is synchronous. They fail when I use the Proxy/Begin method, which invokes the method asynchronously. Methods that don't open streams run either way with no problem.
I appreciate you taking the time to look at this. I'm having trouble explaining it. When I say async in this case, I mean using the Proxy.BeginMethodName where Proxy would be derived from System.Web.Services.Protocols.SoapHttpClientProtocol, the class generated from setting a web reference to a service.
> I'm still confused about what you mean by async. How are you invoking them > a) when it works, and b) when it doesn't work. Since you are returning [quoted text clipped - 122 lines] > typical > >> >ASP.NET error page. Any thoughts? Dan Rogers - 20 Dec 2004 23:23 GMT Hi,
Where does this fail - on the caller, or on the service implementation?
The tricky part is that the service implementation (on some far away server) has no clue that it was called via a delegate. So if it is failing on the server, I'm at a loss to understand why.
You mentioned that you can call it directly or call it via the proxy. If you are calling it directly, well, then yes, I can see how the server might know. What is the fault that you are receiving? Can you provide the stack trace?
The message box part is still confusing to me. This isn't something you would see on a web service implementation since there is no logged in winstation to display a dialog box through.
I'm pretty sure that something in the description of the topology you are seeing is still not clear to me.
There are several things that I can think of that would make IO on a stream and async run afoul. The first would be two threads operating on the same stream simultaneously. But I can't see your implementation, so it isn't clear to me if you are somehow sharing a stream between two threads. My own imagined implementation of your report writer is that it opens a file, writes to it, and then closes it. Is there any chance that you're encountering two requests hitting the same file name at the same time?
Dan
--------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTjz7CGUISXN6yDRvuJPaoyQ6gWjg== >X-WBNR-Posting-Host: 68.74.70.108 >From: "=?Utf-8?B?VHVyYm8=?=" <Turbo@discussions.microsoft.com> >References: <4F6A0DC8-92A1-4BB9-9E07-43123A799944@microsoft.com> <00lXKSV4EHA.3388@cpmsftngxa10.phx.gbl> <E3D1275E-5CE8-4DCE-8145-0BAA1A0BE8EB@microsoft.com> <DUddYT64EHA.1964@cpmsftngxa10.phx.gbl>
>Subject: RE: Asynchronous Web Service Method Failure >Date: Thu, 16 Dec 2004 16:31:03 -0800 [quoted text clipped - 13 lines] >Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA03.phx.gbl >Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27255
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > [quoted text clipped - 45 lines] >System.Web.Services.Protocols.SoapHttpClientProtocol, the class generated >from setting a web reference to a service. Turbo - 17 Dec 2004 16:10 GMT In clarification of my previous post, I have found that I cannot call web service methods through a proxy if the method opens a stream reader or stream writer. If I call the CreateReport method using the proxy, it will timeout. If I call the BeginCreateReport method, it fails when attempting the use the stream. The only way I can get the method to run successfully is to create an instance of the web service directly, without using a proxy.
> I'm still confused about what you mean by async. How are you invoking them > a) when it works, and b) when it doesn't work. Since you are returning [quoted text clipped - 122 lines] > typical > >> >ASP.NET error page. Any thoughts? Dan Rogers - 20 Dec 2004 23:59 GMT This could be a security issue. Because the request is originating thru the web service (asp.net), the permissions granted to the thread are indeed sandboxed. If you are calling the class dirctly, you are not encountering the sand box. Have you tried treating this as a permissions thing? For instance, if you only try to write to the services directory, and not to a root qualified path, do you have better luck? I should have thought of this possibility since it is such a common case.
If you try to over-write an existing file in the local service directory, and you've explicitely granted permissions to the ASPNET_IIS web service account to that file, does it work any better? WS that write files are indeed problematic because they are so tightly sand boxed. If you think about it, the potential under high load to knock your server over when the disk is full is extremely likely. A common attack scenario involves web exposed calls that save files.
Dan --------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTkUwPdMeARkT8bTT+WHDnZWsK+gg== >X-WBNR-Posting-Host: 65.118.1.233 >From: "=?Utf-8?B?VHVyYm8=?=" <Turbo@discussions.microsoft.com> >References: <4F6A0DC8-92A1-4BB9-9E07-43123A799944@microsoft.com> <00lXKSV4EHA.3388@cpmsftngxa10.phx.gbl> <E3D1275E-5CE8-4DCE-8145-0BAA1A0BE8EB@microsoft.com> <DUddYT64EHA.1964@cpmsftngxa10.phx.gbl>
>Subject: RE: Asynchronous Web Service Method Failure >Date: Fri, 17 Dec 2004 08:11:07 -0800 [quoted text clipped - 13 lines] >Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA03.phx.gbl >Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27277
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > [quoted text clipped - 131 lines] >> typical >> >> >ASP.NET error page. Any thoughts? Turbo - 21 Dec 2004 16:11 GMT You're probably right, and it's something I should have thought of myself. Here are the steps involved:
When a session begins, I create a folder for that session in a virtual directory that is set up for that and nothing else. Let's call it the application file cache. It is not in the c:\inetpub\wwwroot folder. The resulting folder looks like \application file caches\sessionid\ so each session has a temporary disk space where the reports are created. This folder is removed when the session ends.
When the user requests a report, sometimes a stream is opened to load some xml that I would need for the report. To open a stream, I use server.mappath(\application root\subfolder\textfilename).
When the report is completed, a file is created in his/her specific session folder using server.mappath(\application file caches\sessionid\filename) and the URL of the file is returned by the web service method. If I use a streamwriter, the method fails. The error is generated when I try to make the call to EndCreateReport(IAsyncResult) and this is where the message box comes up. The real rub is that I don't know if the error occurs when opening the streams, reading from them, or writing to them. The error is not caught in the Try/Catch block.
Anyway, I'll look at the security thing.
> This could be a security issue. Because the request is originating thru > the web service (asp.net), the permissions granted to the thread are indeed [quoted text clipped - 194 lines] > >> typical > >> >> >ASP.NET error page. Any thoughts? Dan Rogers - 21 Dec 2004 18:33 GMT Here's the part that confuses me. You aren't calling the Endxxx method more than once are you? That call would normally be made by the event handler that you specify when you call the Beginxxx method. So you shouldn't call it on your own to check progress, as the thread would be in the wrong state. Also, you call that from the client side, not the server side, yes?
The way you describe this topology just seems out of wack with how it works in my mind. The message box has to be happening on the client side, yes? On the server side, it's not a background thread any more than any other IIS thread is (I mean to say, they are all background threads). If you call the web service from a standard "add-web-reference" proxy and don't call the beginXX methods on the proxy, does the error occur? Does the file get written? Again, I'm not sure yet if we're talking about making a call thru a proxy and using the proxy side "non-blocking call" behavior, or if you are using server side async implementation (which is another matter entirely!).
In general, writing a file outside of the current vroot is going to cause problems. You just don't have the right permissions by default - have you thought about writing your file to a database as a blob? This would eliminate the sandbox issues from the equation. In general writing to disk is bad juju, and the IIS worker thread is given very restricted permissions as far as directly accessing system resources such as the local disk.
--------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTnd7LM+hDENbb1So2lC3FcKjjToA== >X-WBNR-Posting-Host: 65.118.1.233 >From: "=?Utf-8?B?VHVyYm8=?=" <Turbo@discussions.microsoft.com> >References: <4F6A0DC8-92A1-4BB9-9E07-43123A799944@microsoft.com> <00lXKSV4EHA.3388@cpmsftngxa10.phx.gbl> <E3D1275E-5CE8-4DCE-8145-0BAA1A0BE8EB@microsoft.com> <DUddYT64EHA.1964@cpmsftngxa10.phx.gbl> <79A48C7F-F977-4764-9037-78B1ECE7565B@microsoft.com> <fiOsdAv5EHA.2680@cpmsftngxa10.phx.gbl>
>Subject: RE: Asynchronous Web Service Method Failure >Date: Tue, 21 Dec 2004 08:11:16 -0800 [quoted text clipped - 13 lines] >Path: cpmsftngxa10.phx.gbl!TK2MSFTNGXA03.phx.gbl >Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27327
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > [quoted text clipped - 221 lines] >> >> typical >> >> >> >ASP.NET error page. Any thoughts? Turbo - 21 Dec 2004 20:27 GMT I'm calling the Endxxx method just once from the callback procedure. It fails on both the Proxy.Beginxxx call and on the Proxy.xxx call. The message box only occurs when I start the app from VS.NET. It is the same message box that pops up if the proxy can't reconcile the web method parameters. The message says "Error occured during async processing." If I browse to the page, like an end user would do, it simply hangs up IE.
I am using the non blocking web method call from the proxy, not starting a separate thread in the middle of my web method procedure.
Blobs were an option that I considered, and I will revisit that.
I use the "report cache" folder because it allowed me to be very specific in the security settings without messing around in the c:\inetpub\wwwroot folder and it allows me to have multiple apps share the report cache folder. Also, I cannot return a .pdf document object from a web service method because the proxy cannot serialize it. I'm using the CETE Dynamic PDF Generator.
Once again, I very much appreciate your help in this matter.
> Here's the part that confuses me. You aren't calling the Endxxx method > more than once are you? That call would normally be made by the event [quoted text clipped - 305 lines] > >> >> typical > >> >> >> >ASP.NET error page. Any thoughts? Dan Rogers - 21 Dec 2004 21:25 GMT You very much can return a file, via a SOAP attachment (e.g. DIME). This is supported by the WSE 2.0 SP1 toolkit.
One more thing (looked at your other post)... I don't think the response.redirect call will work. Unless, this is an ASP page calling the web service. What is the page doing while it is waiting for the async call to complete? The thread must still be alive for this to work, otherwise I would expect your results to be completely unpredictable. Since it's waiting anyway, and you could not have completed painting the response back to the calling browser, why not just make the page call the service directly?
--------------------
>Thread-Topic: Asynchronous Web Service Method Failure >thread-index: AcTnm21caeIQZdU9R5SF8vY2Aslcgg== >X-WBNR-Posting-Host: 65.118.1.233 >From: "=?Utf-8?B?VHVyYm8=?=" <Turbo@discussions.microsoft.com> >References: <4F6A0DC8-92A1-4BB9-9E07-43123A799944@microsoft.com> <00lXKSV4EHA.3388@cpmsftngxa10.phx.gbl> <E3D1275E-5CE8-4DCE-8145-0BAA1A0BE8EB@microsoft.com> <DUddYT64EHA.1964@cpmsftngxa10.phx.gbl> <79A48C7F-F977-4764-9037-78B1ECE7565B@microsoft.com> <fiOsdAv5EHA.2680@cpmsftngxa10.phx.gbl> <BDBC174C-B0EA-45A9-9699-4EAB74E1739D@microsoft.com> <oY6xCu45EHA.3512@cpmsftngxa10.phx.gbl>
>Subject: RE: Asynchronous Web Service Method Failure >Date: Tue, 21 Dec 2004 12:27:01 -0800 [quoted text clipped - 12 lines] >NNTP-Posting-Host: TK2MSFTNGXA03.phx.gbl 10.40.1.29 >Path: cpmsftngxa10.phx.gbl!TK2MSFTFEED01.phx.gbl!TK2MSFTNGP08.phx.gbl!TK2MSFTNGXA0 3.phx.gbl
>Xref: cpmsftngxa10.phx.gbl microsoft.public.dotnet.framework.aspnet.webservices:27336
>X-Tomcat-NG: microsoft.public.dotnet.framework.aspnet.webservices > [quoted text clipped - 328 lines] >> >> >> typical >> >> >> >> >ASP.NET error page. Any thoughts? Bruce Johnson - 21 Dec 2004 22:09 GMT Dan hit upon something that has been bugging me about this scenario for a while. Check out the following link for a very cogent description of what I now suspect you're running in to.
http://www.odetocode.com/Articles/112.aspx
Bruce Johnson [.NET MVP] http://www.objectsharp.com/blogs/bruce
Turbo - 21 Dec 2004 22:43 GMT The response.redirect call works fine. I call the createreport method from within a web form (aspx) and then the web form displays a message that the report is being generated. A java script submits the form on the page every so often so it can check a session variable. My actual code is thus:
Private Sub ReportCompleted(ByVal IAResult As IAsyncResult)
If IAResult.IsCompleted() Then Dim ws As wsReportGenerator = IAResult.AsyncState Dim s As String = ws.EndPrintReport(IAResult) ' do some error checking with s here Session("ReportURL") = s End If
End Sub
This way, the next time the form is submitted by the javascript, it can check the Session("ReportURL") variable for a value. If there is one, it redirects to the report file.
> You very much can return a file, via a SOAP attachment (e.g. DIME). This > is supported by the WSE 2.0 SP1 toolkit. [quoted text clipped - 430 lines] > >> >> >> typical > >> >> >> >> >ASP.NET error page. Any thoughts? Bruce Johnson - 21 Dec 2004 18:47 GMT Oooo. Session ids and web services.
I have to ask. Have you enabled sessions for your web service. If memory serves, this is done by setting EnableSession to true in the WebMethod attribute. And 'false' is the default, as using sessions in a web service is tricky.
Also, does your client persist the cookies returned by each of the web methods and pass them along to subsequent ones. This is not the 'default' behavior of the proxy class that WSDL.exe generates, for example. I strongly suspect that WSDL.exe is not alone in it's default. But it means that every web method call will appear to be in a different session.
Finally, the exception you're getting is probably being through by the method that is manipulating the stream. In async called, any exceptions through by the 'remote' method are held onto until the End... method is called.
Bruce Johnson [.NET MVP] http://www.objectsharp.com/blogs/bruce
Turbo - 21 Dec 2004 20:43 GMT I'm not using a session, but I pass the session id to the web service method as the first parameter so that I know where to create the report file. I use the standard Beginxxx for calling the method:
dim ws as new wsReportGenerator dim cb as new AsnycCallback(AddressOf Me.ReportCompleted) dim r as IAsnycResult = ws.BeginCreateReport(Session.SessionID, cb, ws)
When the callback function is called, I execute:
private sub ReportCompleted(ByVal IAResult As IAsyncResult)
dim ws as wsReportGenerator = CType(IAResult.AsyncState, wsReportGenerator) dim s as string = ws.EndCreateReport()
Response.Redirect(s, True)
end sub
Thank you very much for your help.
> Oooo. Session ids and web services. > [quoted text clipped - 20 lines] > *** Sent via Developersdex http://www.developersdex.com *** > Don't just participate in USENET...get rewarded for it! Bruce Johnson - 13 Dec 2004 20:49 GMT The fact that you're getting the error message in a message box means that the client side of the process is catching and processing the exception. You might want to try getting some information closer to the actual call to see if you see anything useful.
Also, how large are the files that you're moving back and forth. I seem to recall some default limit of around 4MB for request/response sizes in ASP.NET.
Bruce Johnson [.NET MVP] http://www.objectsharp.com/blogs/bruce
Free MagazinesGet these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...
|
|
|