I found out the hard way that when using the trace on an ASP.Net page, the interaction of the trace observer is not totally separate from the page. I am working on a page where performance is a big issue, so I have been using Trace extensively to find the weak spots and shore them up. Essentially the page is searching both the Indexing Service and an Oracle database and finding where the two datasets intersect. Because the results are a grid of links, the user can click the links and then use the Back button to return to the results. Of course I was getting the dreaded “Warning: Page has Expired” message after using the back button. The page with the grid is the result of an HTTP post, so the post has expired. Clicking the Refresh button was the only way to get the data back initially. This is bad, as the page already was having performance problems, so rendering it again was not really an option. So I tried setting the page caching options to this:
<%@ OutputCache Duration=”120″ VaryByParam=”None” Location=”Client”%>
This should cause the page to cache on the client. No dice. No matter what I set, the http_cache_control header always reported “no-cache” in the trace results. I tried making the header changes in code. Again, no change. Still reporting “no-cache”. The simple solution to the problem is to turn off tracing on the page. Well, it turns out that with Trace=”true” in the @Page directive, the http_cache_control header is set to “no-cache” no matter what. When the Tracing is off, the “Warning: Page has Expired” message disappears and the page is back in control of setting the headers.
Also, a related tidbit I discovered when trying to solve this is that the page timeout is essentially set to infinity when compiling in debug mode.
As I am continuing to migrate our ASP app to ASP.Net, it has finally come time to address the Indexing Service search. It’s a big feature in the application, and the transition of this piece needs to be seamless. We want to stick with Ixsso for the Indexing Service as opposed to using the Oledb driver. Ixsso is considered to be the faster of the two technologies, even using COM interop (See various of Hilary Cotter’s comments in microsoft.public.inetserver.indexserver). Code snippets for using Ixsso with ASP.Net are pretty sparse compared to using Oledb, so I figured I should post mine. First, I used the IDE to create a reference to the ixsso Control Library dll and let the IDE make the .Net wrapper for the COM object (christened Cisso by the IDE).
Private Function GetIndexResults(ByVal Query As String) As DataTable
Dim Q As New CissoQueryClass
Dim util As CissoUtilClass
Dim da As New OleDbDataAdapter
Dim ds As New DataSet(“IndexServerResults”)
Q.Query = Query
Q.SortBy = “rank[d]”
Q.Columns = “filename, rank, write”
Q.Catalog = “query://DocumentServer/Resumes”
Q.MaxRecords = 1000
util.AddScopeToQuery(Q, “\”, “deep”)
Q.LocaleID = util.ISOToLocaleID(“EN-US”)
Dim impContext As WindowsImpersonationContext = impersonateAnonymous()
da.Fill(ds, Q.CreateRecordset(“nonsequential”), “IndexServerResults”)
Q = Nothing
util = Nothing
The impersonateAnonymous function is described in a previous post of mine. In our case the anonymous user on the machine has appropriate privledges to query the remote Indexing Service, but the ASP.Net worker process does not so impersonation is in order for the function. That part is probably optional depending on the situation. The rest of it is not very tricky. I tried to fill the DataTable directly without the DataAdapter, but that didn’t work. The CreateRecordset function of the CissoQueryClass returns an ADO recordset and I couldn’t find a cast that worked. The DataAdapter seems to be doing the casting work during the call to Fill.