I am using a generic handler for loading Image from data bases. Its work fine when when I hardcode the ImageID in the query string when call handler. But it's giving error of different type when I dynamically pass value from query string (from datatable):
ExecuteReader requires an open and available Connection. The connection's current state is open.
OR
Invalid operation. The connection is closed.
Here is the code of handler
public void ProcessRequest(HttpContext context)
{
Int64 id = Convert.ToInt64(context.Request.QueryString["adid"]);
dt = GetRecpDetailsByID(id);
if (dt.Rows.Count > 0)
{
//context.Response.ContentType = "image/jpeg";
context.Response.BinaryWrite((byte[])dt.Rows[0][2]);
}
}
public DataTable GetRecpDetailsByID(Int64 reid)
{
try
{
obj_DB.Open();
obj_sqlcmd = new SqlCommand("GetRecpDetailsByID", obj_DB.GetDBConnection());
obj_sqlcmd.CommandType = CommandType.StoredProcedure;
obj_sqlcmd.Parameters.Add(new SqlParameter("#rid", reid));
obj_sqlda = new SqlDataAdapter();
obj_dt = new DataTable();
obj_sqlda.SelectCommand = obj_sqlcmd;
obj_sqlda.Fill(obj_dt);
return obj_dt;
}
finally
{
obj_DB.Close();
}
}
And here is the HTML and server-side code on ASPX page of call handler
<img id="img2" alt="Image" runat="server" src='<%#"ImageReqHAndler.ashx?adid="+Eval("Reid")%>' width="179" height="148" />
This is shown when a connection object's open method is not called
u need something like:
SqlConnection conn = (SqlConnection)obj_DB.GetDBConnection();
conn.Open();
Related
I am trying to select a single row on a gridview and have that selection take me to a separate edit page with the data populated. I have the idea of using a session variable to hold the row id and then retrieving the data on page load and populating the text boxes. My question is whether or not this is the best method to go about doing this? I would prefer to not use the inline edit option in gridview as I have too many columns that would require scrolling horizontally. Here is my page load method using the session variable:
if (Session["editID"] != null)
{
dbCRUD db = new dbCRUD();
Recipe editRecipe = new Recipe();
var id = Convert.ToInt32(Session["editID"]);
Session.Remove("editID");
editRecipe = db.SelectRecord(id);
addName.Text = editRecipe.Name;
}
Here is the SelectRecord method that is used to retrieve the row:
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
var dbConn = new SqlConnection(connString);
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.Add("#ID", SqlDbType.Int).Value = id;
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
dbConn.Close();
return returnedResult;
}
I'm probably not utilizing the SQLDataReader appropriately, but my result is no data in the reader therefore no returned data when calling the method. Any help is appreciated - thanks in advance!
Few things you should be aware of here:
1.
You should use while (reader.HasRows) in case your stored procedure returns multiple resultsets. In that case you have to iterate through the result sets. See Retrieving Data Using a DataReader. So, if selectRecipe returns multiple resultsets (I am assuming this is not the case), change your code to this:
while (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
reader.NextResult();
}
2.If selectRecipe returns single result set, change the while loop to if(){}:
if(reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
3. I would probably use using to manage the connection better (using Statement) :
public Recipe SelectRecord(int id)
{
Recipe returnedResult = new Recipe();
using (SqlConnection dbConn = new SqlConnection(connString))
{
var dbCommand = new SqlCommand("dbo.selectRecipe", dbConn);
dbCommand.CommandType = CommandType.StoredProcedure;
dbCommand.Parameters.AddWithValue("#ID", id);
dbConn.Open();
SqlDataReader reader = dbCommand.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
returnedResult.Name = reader["Name"].ToString();
}
}
reader.Close();
}
return returnedResult;
}
This is my table in database :
And I read the database like :
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.First(p => p.username == User.Identity.Name);
So, thisuser.picture is a handle to the image. But how can I show it in asp:image control on my page ?
Edit
I save the picture with this code :
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.First(p => p.username == User.Identity.Name);
byte[] filebyte = FileUpload1.FileBytes;
System.Data.Linq.Binary fileBinary = new System.Data.Linq.Binary(filebyte);
thisuser.picture = fileBinary;
db.SubmitChanges();
is there something wrong ?
The ASP.NET Image control loosely represents an <img> tag in HTML. As a result you can only get an image into an HTML doocument by setting the URL to the image content you want to embed in the page.
<img src="images/picture.png" />
This means that you need a mechanism to take an HTTP request asking for an image resource, and return a response containing the image binary data.
With ASP.NET Web API this becomes a trivial operation to implement:
public HttpResponseMessage GetImage(string username)
{
DataClassesDataContext db = new DataClassesDataContext();
usertable thisuser = db.usertables.FirstOrDefault(
p => p.username == username);
if (thisuser == null)
{
return new HttpResponseMessage(HttpStatusCode.NotFound));
}
// Create a stream to return to the user.
var stream = new MemoryStream(thisuser.picture.ToArray());
// Compose a response containing the image and return to the user.
var result = new HttpResponseMessage();
result.Content = new StreamContent(stream);
result.Content.Headers.ContentType =
new MediaTypeHeaderValue("image/jpeg");
return result;
}
If you can't use Web API, you'll have to implement an HTTP Handler to do the same job.
In your ASP.NET page, you will have to set the property ImageUrl to the address configured for your controller/handler, including the username as part of the URL.
<asp:Image ImageUrl='<%# GetImage(Eval("IMG_DATA")) %>' />
Above we tell the ASPX engine that we want to take value of column [IMG_DATA], and pass it into method GetImage of the page, which should return a valid image. So, let's implement the method inside our page class:
public string GetImage(object img)
{
return "data:image/jpg;base64," + Convert.ToBase64String((byte[])img);
}
You'll need to create generic handler - lets call it ImageHandler.ashx, and it will be in the root of your web app.
public class ImageHandler : IHttpHandler {
public void ProcessRequest(HttpContext context) {
// here is the tricky part - you don't store image type anywhere (you should)
// assuming jpeg
context.Response.ContentType = "image/jpeg";
DataClassesDataContext db = new DataClassesDataContext();
if (HttpContext.Current.User != null && HttpContext.Current.User.Identity != null) {
var thisuser = db.usertables.First(p => p.username == HttpContext.Current.User.Identity.Name);
if (thisuser != null) {
byte[] buffer = thisuser.picture.ToArray();
context.Response.OutputStream.Write(buffer, 0, buffer.Length);
}
}
}
public bool IsReusable {
get { return false; }
}
}
Then in the page, add:
<asp:Image runat="server" ImageUrl="~/ImageHandler.ashx" />
Few notes:
you should consider caching of the image
you should switch from image sql type to varbinary (http://msdn.microsoft.com/en-us/library/ms187993.aspx)
you should store image mimetype somewhere (if it is jpeg, png, bmp) - preferably in the same table, and server the correct mimetype in the handler
-
if thisuser.picture has a proper path to your image, you can try something like this:
Image im = new Image();
im.ID = "myImg";
im.ImageUrl = thisuser.picture.toString();
this.Controls.Add(im);
I am assuming that you are using web forms (I don't think it makes a difference).
Also, this might require a page refresh. The 'this' is referring to the Page object (in my case).
You can't render it directly using the ASP.NET Image control (or at least not that I'm immediately aware of). Quickly of the top of my head:
Solution 1:
You need some HttpHandler for your images. In your asp:image tag you need an ImageUrl that will be picked up by this specific HttpHandler. There you can write out the image content from the database as bytes using the right MIME type and headers.
Solution 2:
Take a look into embedding data in URLs, perhaps you can write out your image like this and add it to the asp:image ImageUrl like that: https://en.wikipedia.org/wiki/Data_URI_scheme
create ashx page. On it use somthing like this
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "image/jpeg";
Stream strm = new MemoryStream(GetImage(ID));
long length = strm.Length;
byte[] buffer = new byte[length];
int byteSeq = strm.Read(buffer, 0, 2048);
while (byteSeq > 0)
{
context.Response.OutputStream.Write(buffer, 0, byteSeq);
byteSeq = strm.Read(buffer, 0, 2048);
}
}
ON get image method
public static byte[] GetImage(string ImageId)
{
byte[] img = null;
DataTable dt = new DataTable();
SqlCommand cmd = new SqlCommand();
cmd.CommandType = CommandType.StoredProcedure;
cmd.CommandText = "USP_SELECT_GLOBAL_METHOD";
cmd.Parameters.AddWithValue("#EVENT", 5);
cmd.Parameters.AddWithValue("#CODE", ImageId);
cmd.Connection = DL_CCommon.Connection();
SqlDataReader dr = null;
dr = cmd.ExecuteReader();
if (dr.Read())
{
img = (byte[])dr[0];
}
dr.Close();
return img;
}
this method return returns the image as ur ID.
on your aspx page..
Image1.ImageUrl = "somthing.ashx?ID="+userImageID;
I hope it will work. as i have found it worked in my own. Thank you
I am trying to write a httphandler to retrieve image url and later display it on a image control i am using this code but its not working
OleDbConnection mDB = new OleDbConnection(
ConfigurationManager.ConnectionStrings["AccessConnection"].ConnectionString);
mDB.Open();
OleDbCommand cmd = new OleDbCommand("select pProductId from Products where pProductId=" + context.Request.QueryString["ImageID"], mDB);
OleDbDataReader rdr = cmd.ExecuteReader();
rdr.Read();
context.Response.BinaryWrite((byte[])rdr[0]);
mDB.Close();
context.Response.End(); */
sorry that i caused a confusion earlier in the SELECT statement the pProductId does not contain the URL of the image instead pProductImage is the field that contain the URL. i am using the Id to identify which image to display accordingly.
this is my expected output:
<img src="ImgHandler.ashx?pProductId=2" alt="" />
i cant place image this is the link to my error msg:http://imgur.com/Cix67
This is a two steps answer.
In the page, you can do something like this:
using (OleDbConnection mDB = new OleDbConnection(ConfigurationManager.ConnectionStrings["AccessConnection"].ConnectionString))
{
mDB.Open();
using (OleDbCommand cmd = new OleDbCommand("select pProductId from Products where pProductId=" + context.Request.QueryString["ImageID"], mDB))
{
using (OleDbDataReader rdr = cmd.ExecuteReader())
{
rdr.Read();
context.Response.Write("<img src=\"ImgHandler.ashx?pProductId=");
context.Response.Write((int)rdr[0]); // I suppose pProductId is an int, adapt accordingly
context.Response.Write("\" />");
}
}
}
and in the HTTP handler implicitly triggered, something like this:
public class MyHandler : IHttpHandler
{
public bool IsReusable
{
get { return true; }
}
public void ProcessRequest(HttpContext context)
{
using (OleDbConnection mDB = new OleDbConnection(ConfigurationManager.ConnectionStrings["AccessConnection"].ConnectionString))
{
mDB.Open();
// select the file data (I put pData here as a placeholder, and assume it will be a byte[])
using (OleDbCommand cmd = new OleDbCommand("select pData from Products where pProductId=" + context.Request.QueryString["ImageID"], mDB))
{
using (OleDbDataReader rdr = cmd.ExecuteReader())
{
rdr.Read();
context.Response.ContentType = "image/png";// put the content type here
context.Response.BinaryWrite((byte[])rdr[0]);
}
}
}
}
}
Note the using pattern which ensures proper resources cleanup once used. Also, ideally you could cache the data on the client using proper cache HTTP headers (like if-modified-since) but this is another story ...
How to an image which is retrieved from MYSQL database.
To display a text in textbox we use textbox.TEXT --> We use .TEXT to display text
Likewise how to display an Image retrieved from MYSQL database??
Image1.[___] = dr[0].[_____];
What to be filled in the above blanks??...
I used blob to store image.
You can do it by creating a controller to serve up your image like and then in your view you can just add the call inline:
<img src='<%= Url.Action( "GetImage", "Image", new { id = yourImageIdHere } ) %>' />
public class ImageController
{
public ActionResult GetImage(int id)
{
var image = GetTheRawBinaryImageFromTheDB();
return File(image, "image/jpg" );
}
}
Add a Generic Handler to your Web Forms application and in the ProcessRequest method, you need to query the database for the relevant file/binary data. You would pick the right image via a querystring, usually. The following code shows how you can query the database and return the binary data:
using (DbConnection conn = new DbConnection(connect))
{
if (context.Request.QueryString["id"] != null)
{
DbCommand cmd = new DbCommand(qry, conn);
cmd.Parameters.AddWithValue("", context.Request.QueryString["id"]);
conn.Open();
using (DbDataReader rdr = cmd.ExecuteReader())
{
if (rdr.HasRows)
{
rdr.Read();
context.Response.AddHeader("content-disposition", "attachment; filename=" + rdr["FileName"]);
context.Response.ContentType = rdr["MimeType"].ToString();
context.Response.BinaryWrite((byte[])rdr["Blob"]);
}
}
}
}
You need to change the DbConnection, DbCommand and DbDataReader to the type that your provider likes (Odbc or MySql) and then point the ImageUrl property of your Image control to the HttpHandler:
Image1.ImageUrl = "MyHandler.ashx?id=" + whatever the image id is.
I have a generic method to call a stored Procedure in ASP.NET:
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlDataReader iReader;
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
iReader = sql.ExecuteReader(CommandBehavior.CloseConnection);
sql.Dispose();
return iReader;
}
Even though I am calling CommandBehavior.CloseConnection the connection is not closing. I can get the data fine the first time I request a page. On reload I get the following error:
The connection was not closed. The
connection's current state is open.
Description: An unhandled exception
occurred during the execution of the
current web request. Please review the
stack trace for more information about
the error and where it originated in
the code.
Exception Details:
System.InvalidOperationException: The
connection was not closed. The
connection's current state is open.
Source Error:
Line 35: Line 36: } Line
37: sql.Connection.Open();
Line 38: iReader =
sql.ExecuteReader(CommandBehavior.CloseConnection);
Line 39: sql.Dispose();
Finally if I put sql.Connection.Close(); before sql.Dispose(); I get an error that iReader is not readable because it's been closed already.
Obviously I am closing my connection incorrectly, can someone point me in the right direction?
When you return a DataReader, the underlying connection must remain open. It's the consumer's responsibility to properly clean up resources.
public SqlDataReader ExecuteStoredProc(string sprocName, SqlParameter[] SqlP)
{
SqlCommand sql = new SqlCommand();
sql.CommandText = sprocName;
sql.CommandType = CommandType.StoredProcedure;
sql.Connection = ConnStr;
if (SqlP != null)
{
foreach (SqlParameter p in SqlP)
{
sql.Parameters.Add(p);
}
}
sql.Connection.Open();
return sql.ExecuteReader(CommandBehavior.CloseConnection);
}
public void ConsumingMethod()
{
using(SqlDataReader reader = ExecuteStoredProc("MyProc", params))
{
while(reader.Read())
{
//work with your reader
}
}
}
I would suggest wrap the sql connection with a "using" statement, and that will take care of most sql connection issue.
using (var conn = new SqlConnection("..."))
{
conn.Open();
using (var cmd = conn.CreateCommand())
{
cmd.CommandText = "...";
using (var reader = cmd.ExecuteReader())
{
while (reader.Read())
{
// ...
}
}
}
}
The idea is to do a Connection.Close(); after you've finished with the SqlReader, so basically instead of placing the close() statement before the SqlReader.Dispose() command, you should place it below.
This is my preferred way to process IDataReader. Let the caller creates SqlConnection instance and passes to methods.
It's expensive to create SqlConnection instance. And you’ll end up code call the same ExecuteStoredProc method multiple times in different situation.
Thus, I refactor ExecuteStoredProc method by adding SqlConnection instance as part of the parameter.
using (SqlConnection conn = new SqlConnection())
{
conn.ConnectionString = // Connection String;
conn.Open();
using (IDataReader reader = foo.ExecuteStoredProc(conn, sprocName, SqlP))
{
// Process IDataReader
}
}