Question

I have an asp repeater which sets a generichandler (.ashx) parameter differently for each entry. This is used to create comments that are posted by users and display the avatar of the user posting by fetching it from a database. If there is only one post, it works fine, but as soon as there are two or more posts I get a crash in the "GetIdFromUserName" method on the line "connection.Open()" (code provided below) saying "The connection was not closed, the connections current state is open". Bearing in mind this only happens when more than one comment exists, I have no idea what causes this.

One thing I have found out, though: if I make the asp:image object not use the "Eval" (so it only shows the same image for every post regardless of ) it works, but beyond that I have no idea. Eval does work fine if there's only one post to show, though, like mentioned earlier.

If anyone have any idea how to fix this I'd be super grateful.

ASP code:

        <asp:Repeater ID="CommentsRepeater" runat="server" OnItemDataBound="CommentsRepeater_ItemDataBound">
            <ItemTemplate>
                <div class="comment">
                    <div class="commentInfo">
                        <strong>
                            <asp:Image ID="Avatar" ImageUrl='<%# "CommentsAvatarHandler.ashx?id=" + Eval("UserName") %>' runat="server" Height="100px" Width="100" />
                            <asp:LinkButton ID="CommentName" Text='<%# Eval("UserName") %>' CommandArgument='<%# Eval("UserId") %>' CausesValidation="false" runat="server"></asp:LinkButton></strong> @ 
                        <asp:Label ID="CommentDate" Text='<%# Eval("PostedDate") %>' runat="server"></asp:Label>
                        <div class="commentVote">
                            <asp:LinkButton ID="VoteUp" CommandArgument='<%# Eval("CommentId") %>' OnClick="VoteUpClick" CausesValidation="false" runat="server"><img src="images/pluss2.png" /></asp:LinkButton>
                            <asp:LinkButton ID="VoteDown" CommandArgument='<%# Eval("CommentId") %>' OnClick="VoteDownClick" CausesValidation="false" runat="server"><img src="images/minus2.png" /></asp:LinkButton>
                            <strong>(<asp:Label ID="CommentVote" Text='<%# Eval("Vote") %>' runat="server"></asp:Label>)</strong>
                        </div>
                    </div>
                    <div class="commentText">
                        <asp:Label ID="CommentText" Text='<%# Eval("Comment") %>' runat="server"></asp:Label>
                    </div>
                </div>
            </ItemTemplate>
            <SeparatorTemplate>
                <br />
            </SeparatorTemplate>
        </asp:Repeater>

Relevant bit:

   <asp:Image ID="Avatar" ImageUrl='<%# "CommentsAvatarHandler.ashx?id=" + Eval("UserName") %>' runat="server" Height="100px" Width="100" />

Here's the handler:

public class CommentsAvatarHandler : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        String userName = context.Request.QueryString["id"];
        Gamez.Sql.GetAvatarOfUser(context, userName);
    }

    public bool IsReusable
    {
        get
        {
            return false;
        }
    }
}

the method used by the handler:

    public static void GetAvatarOfUser(HttpContext context, String userName)
    {
        SqlDataReader reader;

        try
        {
            Guid id = GetIdFromUserName(userName);
            command.CommandText = "SELECT Avatar FROM UserAttributes WHERE UserId = @id";
            command.Parameters.AddWithValue("@id", id);

            connection.Open();
            reader = command.ExecuteReader();
            while (reader.Read())
            {
                try
                {
                    context.Response.ContentType = "image/jpg";
                    context.Response.BinaryWrite((byte[])reader["Avatar"]);
                }
                catch { }
            }
            if (reader != null)
                reader.Close();

        }
        finally
        {
            if (connection != null)
            {
                connection.Close();
            }
        }

    }

The GetIdFromUserName method:

    public static Guid GetIdFromUserName(String name)
    {
        command.Parameters.Clear();
        command.CommandText = "SELECT UserId FROM aspnet_Users WHERE UserName = @UserName";
        command.Parameters.AddWithValue("@UserName", name);
        connection.Open();  // <---- DESCRIBED CRASH HAPPENS HERE
        Guid id = (Guid)command.ExecuteScalar();
        connection.Close();
        return id;
    }

GetAvatarFromUser and GetIdFromUserName are in the same library and have access to the same SQLCommand (command) and SQLConnection (connection) objects.

Was it helpful?

Solution

From your code it looks like you are using the same instance of connection and command for each request. I am assuming both of these are page level variables?

Create a separate instance of both of these variable for each sql request.

Additionally, you should wrap your Connection and Command initializations in a using block. This will take care of closing and disposing of both resources correctly and using best practices. Something like this:

using (SqlConnection conn = [CONNECTION INITIALIZATION])
   {
   using (SqlCommand command = new SqlCommand(conn))
      {
      ...
         using (SqlDataReader reader = command.ExecuteReader())
         {
            .....
         }
      }
   }

Currently, the way you have it set up, you are asking for trouble.

EDIT

Your code fails when there is a second post because you are sharing your connection object across multiple requests. So while the first post's information is retrieved (opening the connection), you are attempting to retrieve another post (again, trying to open the same connection).

Does that make sense?

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top