How to bind a MemoryStream to asp:image control? - asp.net

Is there a way to bind a MemoryStream to asp:image control?

Best bet is to create an HttpHandler that would return the image. Then bind the ImageUrl property on the asp:Image to the url of the HttpHandler.
Here is some code.
First create the HttpHandler:
<%# WebHandler Language="C#" Class="ImageHandler" %>
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Web;
public class ImageHandler : IHttpHandler
{
public void ProcessRequest (HttpContext context)
{
context.Response.Clear();
if (!String.IsNullOrEmpty(context.Request.QueryString["id"]))
{
int id = Int32.Parse(context.Request.QueryString["id"]);
// Now you have the id, do what you want with it, to get the right image
// More than likely, just pass it to the method, that builds the image
Image image = GetImage(id);
// Of course set this to whatever your format is of the image
context.Response.ContentType = "image/jpeg";
// Save the image to the OutputStream
image.Save(context.Response.OutputStream, ImageFormat.Jpeg);
}
else
{
context.Response.ContentType = "text/html";
context.Response.Write("<p>Need a valid id</p>");
}
}
public bool IsReusable
{
get
{
return false;
}
}
private Image GetImage(int id)
{
// Not sure how you are building your MemoryStream
// Once you have it, you just use the Image class to
// create the image from the stream.
MemoryStream stream = new MemoryStream();
return Image.FromStream(stream);
}
}
Next, just call it inside your aspx page where you are using the asp:Image.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="Default.aspx.cs" Inherits="_Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Image ID="myImage" ImageUrl="~/ImageHandler.ashx?id=1" runat="server" />
</div>
</form>
</body>
</html>
And that is it.

A handler can accept a url parameter like any other request. So instead of linking your <asp:image/> to image.ashx you'd set it to image.ashx?ImageID=[Your image ID here].

I am assuming you need to generate dynamic images from asp.net
You might be in luck
http://www.codeplex.com/aspnet/Release/ProjectReleases.aspx?ReleaseId=16449
Hanselman blogged about it recently
http://www.hanselman.com/blog/ASPNETFuturesGeneratingDynamicImagesWithHttpHandlersGetsEasier.aspx

#Will and Ben Griswald: instead of "image.aspx" use "image.ashx".
It's more light-weight than a full ASP.Net Page, and it's specifically designed to handle content-types other than text/html.

While Databinding a MemoryStream to a Image is not possible, it could be possible to use a Label/GenericControl, some Code and the data URI scheme to embed Images in Pages, but there are severe issues with that approach:
Disadvantages
Embedded content must be extracted and decoded before changes may be made, then re-encoded and re-embedded afterwards.
Cookies are not supported.
Information that is embedded more than once is redownloaded as part of the containing file, and thus does not benefit from the browser's cache.
Browsers may limit URI lengths, creating an effective maximum data size. For example, URIs in previous versions of Opera had limits of 4kB, and 32kB for IE8 Beta 1[citation needed]
Data is included as a simple stream, and many processing environments (such as web browsers) may not support using containers (such as multipart/alternative or message/rfc822) to provide greater complexity such as metadata, data compression, or content negotiation.
Microsoft's Internet Explorer, through version 7 (some 70% of the market as of 2008 Q2), lacks support.
The better Approach is to use a separate "Image.aspx" Page which takes and outputs your MemoryStream, kinda like I did in my Photo Album software that i've created when I started learning ASP.net:
(Don't laugh, that was my first attempt at ASP.net :-)
Edit: Agreed on ASHX, the code above is just to show one sample implementation. When I come around to update the Photo Album, it will use ASHX for that.

You can use Telerik's BinaryImage control for ASP.net.
More info in here:
http://www.telerik.com/products/aspnet-ajax/binaryimage.aspx

Nope.
But you can create a special page to stream that image out. First, you set the URL of the image to the page that performs the streaming, including some url parameters that let you know where to get the image:
<img src="GetImage.aspx?filename=foo" ... />
in GetImage.aspx, you get the filename (or whatever) from the URL, load the image in your MemoryStream, and then write the content of that memory stream directly to the HttpResponse:
response.Expires = 0;
response.Buffer = false;
response.Clear();
response.ClearHeaders();
response.ClearContent();
response.ContentType = "image/jpeg";
response.BinaryWrite(stream);
response.Flush();
response.Close();

For me it was necessary to add "buffer="false" to the #Page. Otherwise I would keep getting the same picture all the time...

Related

ASP equivalent of Ajax?

Weird question. I need to use a JavaScript array with ID's in it, to fetch additional information from a database, using the ID's as the row ID.
I need to then use this additional information and send it to another file (aspx) using Ajax, which will then use this information to rotate images.
Unless I can use ASP Classic, and ASP.NET (C#) in the same file?
- Or can I use the more or less same ASP code to access my database?
rotate script
<%# Page Language="C#" Debug="true" %>
<%# Import Namespace="System" %>
<%# Import Namespace="System.Drawing" %>
<%# Import Namespace="System.Web" %>
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
//string url = Request.QueryString["url"];
string url = #"C:\inetpub\wwwroot\testing\image.jpg";
string rotate_dir = Request.QueryString["dir"];
//create an image object from the image in that path
System.Drawing.Image img = System.Drawing.Image.FromFile(url);
//Rotate the image in memory
if (rotate_dir == "clockwise")
{
//Rotate clockwise
img.RotateFlip(RotateFlipType.Rotate90FlipNone);
} else if (rotate_dir == "anticlockwise")
{
//Rotate anti-clockwise
img.RotateFlip(RotateFlipType.Rotate90FlipXY);
}
//Delete the file so the new image can be saved
System.IO.File.Delete(url);
//save the image to the file
img.Save(url);
//release image file
img.Dispose();
}
</script>
What I use to access my database
'Create connection and load users database
set conn=Server.CreateObject("ADODB.Connection")
conn.Provider="Microsoft.ACE.OLEDB.12.0"
conn.Open Server.MapPath("/nightclub_photography/data/database/jamsnaps.mdb")
Hope you understand what I'm trying to do?
As you should know you can freely use Javascript (and thus ajax) in asp-classic.
this means you can easily do the following;
set conn = Server.CreateObject("ADODB.Connection")
set rs = Server.CreateObject("ADODB.Recordset")
conn.open Server.MapPath("foobar path") + ", Microsoft.ACE.OLEDB.12.0"
%><script type="text/javascript">
rotationArray = Array(id_Array.length);
for(int i = 0; i < id_Array.Length; i++
{
<% rs.open("SELECT rotation FROM images WHERE id="+ id_Array[i])%>
rotationArray[i] = <%= rs("rotation") %>;
<%rs.close() %>
}
//send rotationArray via ajax
but in general I would suggest you use Database tools for asp.NET instead.
then you just send your JS-IDArray to the aspx file and do the processing there.
for reference you can check here
You can use C#.Net and ASP together. Its not a very nice way to do it. My understanding is you have to create the C#project first then add any asp pages. This will allow you to call your C# pages from within the asp application.
I havent personally done one of these but I have seen it done for sure so I know its technically possible.

How to play media - saved on db as binary - on a website?

I have a table on SQL Server 2008, I saved on it videos and audios as binary.
I have to play these media (videos and audios) on my website.
Can I do that?
Is there a way that I could request the media as a link? so I can embed it...
Any help appreciated.
Sorry for my english.
They are probably other ways to do this but i'll just show mine below.
create an asp.net page (image.aspx for instance) that has no content on the page just the #page attributes... see below.
<%# Page Language="C#" AutoEventWireup="true" CodeFile="image.aspx.cs" Inherits="image" %>
You code behind file might look like below:
public void Page_Load(object s, System.EventArgs e)
{
int id = Request.QueryString["image_id"]; //assuming u are getting it from query string
byte[] bt = GetMediaData(id); //image data from database as byte array
Response.Buffer = true;
Response.ContentType = "audio/mp3"; //set mimetype of appropriate media type
Response.BinaryWrite(abt);
Response.Flush();
}
on the page that needs to use the resource:
<asp:Image runat="server" id="Image1" ImageUrl="image.aspx?image_id=xx" />
i'm sure this can be done using http handlers though.

problem in sending document when I click cancel

I have a link in aspx page and when i click on it,it shows a popup: open,save,cancel
but when i click cancel on that aspx page no other link works on that page.
code so far:
protected void method1()
{
byte[] byterendered = _Filename.OpenBinary();
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.AddHeader("Content-Disposition", "attachment;filename=abc.jpg");
Response.CacheControl = "Public";
Response.BinaryWrite(byterendered);
Response.End();
}
aspx code
<asp:Linkbutton id="link1" runat="server" onClick="method1" Text="LinkA"/>
<asp:Linkbutton id="link2" runat="server" onClick="method2" Text="LinkB" />
As the comments to your question have indicated, the reason is because your Response is being ended after the file dialog shows up. Once the response ends, any other actions on your page will not be registered. I ran into this myself while implementing a download function for my SharePoint app.
Basically, what you want to do is have your link buttons perform a window open script, instead of directly running the file transfer, like the following.
<asp:LinkButton id="link1" runat="server" onClick="window.open('TARGETURL'); return false;" Text="LinkA" />
Replace TARGETURL with an aspx page URL. Then, create a new ASPX page for the URL you specified. It will be pretty much empty, all you need are two lines.
<%# Assembly Name="YOURFOURPARTASSEMBLYSTRINGHERE" %>
<%# Page Language="C#" Inherits"YOURNAMESPACE.DOWNLOADCODE" %>
Replace YOURFOURPARTASSEMBLYSTRINGHERE with, of course, the four-part assembly string for your code. YOURNAMESPACE.DOWNLOADCODE will be replaced with the namespace and class that you will create for the page. The class will need to inherit the base page type, I personally used LayoutsPageBase since that's a perfect thing to use in a SharePoint app. All this class needs is an OnLoad method like the following.
// Don't actually name your class DOWNLOADCODE.
public class DOWNLOADCODE : LayoutsPageBase
{
protected override void OnLoad(EventArgs e)
{
byte[] byterendered = _Filename.OpenBinary(); //More on this afterwards
Response.Clear();
Response.ClearHeaders();
Response.ClearContent();
Response.ContentType = "image/jpeg";
Response.AddHeader("Content-Disposition", "attachment;filename=abc.jpg");
Response.CacheControl = "Public";
Response.BinaryWrite(byterendered);
Response.End();
}
}
You will have to retrieve _Filename in this new page, of course. The best way to do this is to take whatever parameters you use to determine _Filename in the first place, and pass it as part of the URL query string.
Using this, clicking the link button will open a new window, but since all this page does it have a file response, it will just open the file dialog and be done with it. Meanwhile, your original aspx page will not have ended its response, so it can continue whatever function you need it to.

ASP.NET which control could wrap JS block and extractable so I could render it back to header

As title, basically I have a user control placed inside a page and then the page is placed inside the master page. I want to extract a block of javascript and put it back to the page head. When I try to wrap the code inside any block control (e.g. a div runat server) and access divID.InnerText then ASP.NET bust off with
Cannot get inner content of startup_script because the contents are not literal.
I dont want to extract JS inside cs file, thats awfully ugly approach (all sort of escapes and people wont even notice you have JS written unless they drill your CS file), what can I do?
You could store the javascript in a separate file, and then add it to the page using Page.RegisterClientScriptBlock()
Add the javascript you want to a .js file and add the .js file to your project.
Alter the properties of the .js file so that it is an Embedded Resource.
Then use code like this somewhere in your UserControl (maybe the Page_Load) to pull the code from the file and drop it into the page:
string javaScript = "";
// the javascript is in a separate file which is an 'embedded resource' of the dll
using (StreamReader reader =
new StreamReader((typeof(ThisClass).Assembly.GetManifestResourceStream(typeof(ThisClass), "NameOfJavaScriptFile.js"))))
{
javaScript = String.Format("<script language='javascript' type='text/javascript' >\r\n{0}\r\n</script>", reader.ReadToEnd());
}
Page.RegisterClientScriptBlock("MyScriptBlock", javaScript);
Note that RegisterClientScriptBlock() will put the script near the top of the page, but apparently not in the page header.
(edited bit about header after comment)
<%# Page Language="C#"%>
<script runat=server>
protected override void OnLoad(EventArgs e)
{
string scriptText = someID.InnerHtml;
//if you really want it in the header...
//Page.Header.Controls.Add( new LiteralControl(String.Format( "<scr" + "ipt language=\"javascript\">{0}</scri" + "pt>\\n", scriptText )));
//doesnt add to header and requires form runat=server
Page.ClientScript.RegisterStartupScript(this.GetType(), "SomeScript", scriptText, true);
base.OnLoad(e);
}
</script>
<head runat=server></head>
<form runat=server>
<div id="someID" runat=server>alert('hi');</div>
</form>
Okay, I've probably done this in a horrible, horrible way, but I wanted to add a script to the head element in a recent project from a user control. This script didn't require any data from my server, but I only wanted it on specific pages, so I put the script in a .js-file, and added it to the head like this:
HtmlGenericControl script = new HtmlGenericControl("script"); // Creates a new script-element
script.Attributes.Add("type","text/javascript");
script.Attributes.Add("src","src/to/js-file.js");
Page.Master.FindControl("head").Controls.Add(script); // Finds the element with ID "head" on the pages master page.
Not entirely sure if the code works as I think it does as the code I wrote for the project is on another machine, but you get the idea, right?
Edit:
After googling your error message for a bit, I think this might be a solution to your problem:
using System.IO;
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
yourDivID.RenderControl(h);
String str = sw.GetStringBuilder().ToString();
If you combine the two examples, you should be able to get the result you want. I haven't tested this, but it works in my head.

Alternative Query String C# (asp.net)

Is there a quick and dirty way of using a query passed as follows:
domain.com/mypage.aspx/product/toycar/
I've done it before in PHP, but this needs to be done in page (in this instance).
--
I only have access to the aspx page and code behind, and have to work in asp.net 2 (i wish i was using 3.5)
quick and dirty:
public class ModuleRewriter : IHttpModule
{
public void Init(HttpApplication application)
{
application.BeginRequest += (new EventHandler(this.Application_BeginRequest));
}
private void Application_BeginRequest(Object source, EventArgs e)
{
// The url will look like: http://domain.com/mypage.aspx/product/toycar/
// The module will rewrite it to: http://domain.com/mypage.aspx?product=toycar
HttpApplication application = source as HttpApplication;
string[] urlInfo = application.Request.RawUrl.ToString().Split('/');
if (urlInfo.Length > 2)
{
string page = urlInfo[urlInfo.Length - 3];
string action = urlInfo[urlInfo.Length - 2];
string id = urlInfo[urlInfo.Length - 1];
if (string.IsNullOrEmpty(page))
{
page = "default.aspx";
}
application.Server.Transfer(string.Format(
"~/{0}?{1}={2}", page, action, id));
}
}
public void Dispose()
{
}
}
web.config:
<httpModules>
<add name="ModuleRewriter" type="ModuleRewriter, MyWebApplication"/>
</httpModules>
and a test page:
<%# Page Language="C#" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<%= Request["product"] %>
</div>
</form>
</body>
</html>
You might want to look into the ASP.NET System.Web.Routing namespace, which was added in .NET 3.5 SP1 I believe:
http://blogs.msdn.com/mikeormond/archive/2008/05/14/using-asp-net-routing-independent-of-mvc.aspx
http://msdn.microsoft.com/en-us/library/system.web.routing.aspx
You'd be able to get rid of the .aspx extension too.
This would involve making a custom HTTP Handler.
Check this
You've got a few options, but all of them require access to the web.config and a change to IIS to map all file extensions to the dotNet ISAPI dll:
Use MVC (like stackoverflow does,
notice the urls)
Use asp.net routing (new in 3.5)
Write your own http handler Massive guide from Microsoft here
Use the excellent urlrewriting.net which does just about everything perfectly including getting round some awkward authentication and image path problems.
Personally I used urlrewriting.net with good results.
Since you mention you don't have access to anything but the code behind and the page, the only thing I can think of is actually creating those dirs (if you have access to do that) and using a server.transfer page passing the value to your actual page in the folder above. Messy, but if you can't access the other stuff, your choices are limited.
In case you just want to read the path from within your .aspx:
Request.ServerVariables["PATH_INFO"]
To clarify:
he has only access to the aspx (+ codebehind) itself, so he must know how the query is, but it is not in the Request.QueryString because of the format. So the only way then is Request.ServerVariables["PATH_INFO"] (Request.RawUrl)

Resources