Running ReportViewer Control on Windows 2000

I’ve been working on an interesting project where we had reporting considerations. I hadn’t been very involved with it. There were some folks creating the reports, some others telling those folks what to do, and still others trying to figure out how to deploy the thing. Needless to say, there were issues with it. So I was asked to come in and see what I could do.

Microsoft has a handy ReportViewer control that really is quite cool. I came from a background where we used Actuate and the report delivery mechanism was a little clunky (probably mostly due to our implementation) and not really integrated at all. So to have this control that basically puts the reports in an IFRAME is kind of cool. It looks integrated at least.

Our environment is a little messed up. I develop on my own W2K3 server workstation and deploy to another W2K3 server. I knew that I had to impersonate a domain user in order to access the required reports. So I followed the instructions I learned here. It all worked fine, until I deployed the solution to an old W2K server, which is our public test machine (don’t ask). I could not for the life of me get it to work.

After many hours trying this that and the other, I finally figured that I *must* be doing something wrong in the impersonation. That’s the only thing that makes sense. So then I came across this. And the solution was so obvious that I felt a little sheepish in announcing my find to others. I don’t know enough about the internals to figure out why it’s happening, but I do know that I’ll consider that I need to grant the “Act as part of the operating system” privilege for the ASPNET user when running on Windows 2000. Hopefully that scenario won’t present itself again.

Strangeness in GridView’s HyperLinkField

Today I got an email from a client who I do some work for. He has an existing application that uses a GridView, probably in much the same way that many others do. There are a few BoundFields and a HyperLinkField. The HyperLinkField looked a little like this:


Pretty standard, right? We see this all the time. And it worked all the time, until we had a “Buyer” who happened to have a colon (:) in her username. It wouldn’t work. There was no error displayed on the page. But there was also no hint of a hyperlink.

I found an article that mentioned this behavior. Apparently it’s to keep your app more secure, so there isn’t malicious stuff thrown in there. In other words, it’s “by design.” So this is what I came up with in its place (the code thing isn’t parsing this properly, no matter what hackery I try):

            
                
                    `>
                
            

Another interesting thing is that you have to either remove the EnableSortingAndPagingCallbacks or set it to false. It makes some sense, I suppose, though I won’t pretend to know the exact reason why.

Calling Oracle Packages from C#

I’ve been working on a number of projects that required calling into an Oracle database to get various bits of data. Most of the information was related to product or customer in an ecommerce and/or ERP system. For the longest time, we’ve been relying on an old java listener that just sits there sends and receives sockets. No one is sure how it works, nor are they sure if they even have the latest source code. Everyone is scared that if we pull the latest from VSS and compile it that we’ll have a non-functioning system. They’re probably also wondering if it will even compile.

So here we are in the last few weeks of 2007 and we’re just starting to get going with .NET web services and .NET 2.0. Maybe we’ll even get rid of our old VB6 ecommerce platform (that’s a whole different story). So I found myself needing to create these web services that would call into Oracle and get what I needed. I searched a few places and didn’t find exactly what I needed, so I started with a little trial and error. My packages included CLOBs, so it was a little different. Here’s what I came up with. ProcedureInfo is just an object that holds information about the procedure that I’m calling and my connection to it.

        public static string SendDBRequest(ProcedureInfo pi)
        {
            OracleConnection con = GetPooledConnection(connectionString);
            OracleCommand cmd = con.CreateCommand();

            string clobString = pi.InMessage;

            byte[] clobContents = System.Text.ASCIIEncoding.Unicode.GetBytes(clobString);

            // Get our temporary clob
            OracleClob tempClob = new OracleClob(con);
            tempClob.Write(clobContents, 0, clobContents.Length);

            // Clear the parameters from the command object
            cmd.Parameters.Clear();

            // Set the name of the procedure
            cmd.CommandText = pi.Procedure;
            cmd.CommandType = CommandType.StoredProcedure;

            cmd.Parameters.Add("result_", OracleDbType.Varchar2, 8000);
            cmd.Parameters[0].Direction = ParameterDirection.Output;
            cmd.Parameters[0].Value = string.Empty;

            cmd.Parameters.Add("result_text_", OracleDbType.Varchar2, 8000);
            cmd.Parameters[1].Direction = ParameterDirection.Output;
            cmd.Parameters[1].Value = string.Empty;

            cmd.Parameters.Add("out_message_", OracleDbType.Clob);
            cmd.Parameters[2].Direction = ParameterDirection.Output;

            // In params
            cmd.Parameters.Add("in_message_", OracleDbType.Clob);
            cmd.Parameters["in_message_"].Value = tempClob;
            cmd.Parameters["in_message_"].Direction = ParameterDirection.Input;

            cmd.Parameters.Add("command_", OracleDbType.Varchar2);
            cmd.Parameters["command_"].Value = pi.Command;
            cmd.Parameters["command_"].Direction = ParameterDirection.Input;

            cmd.ExecuteNonQuery();

            string detailText = cmd.Parameters["result_text_"].Value.ToString();

            // Get the response from the clob
            OracleClob rtrnClob;
            string clobMsg = string.Empty;

            try
            {
                rtrnClob = (OracleClob)cmd.Parameters["out_message_"].Value;
                clobMsg = rtrnClob.Value.ToString();
            }
            catch (Exception exc)
            {
                clobMsg = exc.Message;
            }

            cmd.Dispose();
            con.Dispose();

        }