Reverting ASP.NET response header
've programmatically created a listview, for displaying images. When you click on the download the ItemCommand is fired, and the browser sends the user the image as a binary response, using the following:
SPFile ImageIfile = spfolder.Files[ServerName];
byte[] bs = ImageIfile.OpenBinary();
string res = Page.Response.ContentType;
Page.Response.ContentType = "image/jpeg";
Page.Response.AppendHeader("Content-Disposition", "attachment; filename=" + Path.GetFileName(fileName))
Page.Response.BinaryWrite(bs);
Page.Response.End();
This works, exactly once. Then neither the download link, nor the DataPage paging controls work until you refresh (Indeed any postbacks).
开发者_如何学CEDIT: It's a SharePoint 2007 WebPart, this is the declaration of the ListView in the CreateChildControls method:
lv.ItemPlaceholderID = "itemPlaceholder";
lv.GroupPlaceholderID = "groupPlaceholder";
lv.ID = "MediaSearch";
lv.LayoutTemplate = new LayoutTemplate();
lv.GroupTemplate = new GroupTemplate();
lv.GroupItemCount = 4;
lv.ItemTemplate = new ItemTemplate();
lv.EmptyDataTemplate = this.Page.LoadTemplate("/usercontrols/MediaResults_Empty.ascx");
And this is the ItemTemplate and DataBinding
public class ItemTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
//Top bit
Panel ItemPanel = new Panel();
ItemPanel.ID = "itemPlaceholder";
ItemPanel.Attributes["class"] = "mlitem";
var thumbdiv = new HtmlGenericControl("div");
thumbdiv.Attributes["class"] = "thumb-image";
HyperLink aspLink = new HyperLink();
aspLink.ID = "hlPicPreview";
aspLink.Attributes["class"]="picture-preview";
Image aspImg = new Image();
aspImg.ID = "thumb";
aspLink.Controls.Add(aspImg);
thumbdiv.Controls.Add(aspLink);
ItemPanel.Controls.Add(thumbdiv);
//Bottom bit
var bDiv = new HtmlGenericControl("div");
bDiv.Attributes["class"] = "details";
var UnOrderedList = new HtmlGenericControl("ul");
var li1 = new HtmlGenericControl("li");
Literal lit = new Literal();
lit.ID = "liSize";
lit.Text = "Size";
li1.Controls.Add(lit);
var li2 = new HtmlGenericControl("li");
LinkButton down = new LinkButton();
down.ID = "lbDownload";
down.CommandArgument = "Pugs";
down.CommandName = "Download";
down.Text = "Download";
li2.Controls.Add(down);
UnOrderedList.Controls.Add(li1);
UnOrderedList.Controls.Add(li2);
bDiv.Controls.Add(UnOrderedList);
ItemPanel.Controls.Add(bDiv);
ItemPanel.DataBinding += new EventHandler(ItemPanel_DataBinding);
container.Controls.Add(ItemPanel);
}
void ItemPanel_DataBinding(object sender, EventArgs e)
{
Panel ThePanel = (Panel)sender;
//Get bindables
Image thumb = ThePanel.FindControl("thumb") as Image;
LinkButton lbdown = ThePanel.FindControl("lbDownload") as LinkButton;
ListViewDataItem lvdi = (ListViewDataItem)ThePanel.NamingContainer;
//Bind that stuff.
lbdown.CommandArgument = ((DataRowView)lvdi.DataItem)["URL"].ToString();
thumb.ImageUrl = "~/" + ((DataRowView)lvdi.DataItem)["ThumbsNailsImg"].ToString();
}
I more than a little stumped here. AJAX is enabled on the site, but not being used in this control.
What you're running into is SharePoint trying to be clever. When a Web site it slow (and this can happen even when running SharePoint) users tend to push buttons/links multiple times, which isn't going to make things faster and may cause trouble as events are fired twice. So SharePoint is by default disabling multiple postbacks.
The fix for this can be found in almost any article about using AJAX with SharePoint. Look for the EnsurePanelFix function which you should implement and call in the code showing the listview.
The problem was nothing to do with the listview or even SharePoint(for once). I was using the itemCommand method, which is a postback, so when the postback is being processed my code suddenly hijacks the HTTP response then changes the output to a image type and adds an attachment header. This means that the asp.net can no longer process the stream as it would usually. solution: I made the download link a standard anchor tag, pointing to a httpHandler that solves that issue.
精彩评论