I am tryin to implement UPSP label generating but i am getting this error.
**API Authorization failure. DelivConfirmCertifyV3.0Request is not a valid API name for this protocol.**
if i test on browser, it's working fine
http://production.shippingapis.com/ShippingAPI.dll?API=Verify&XML=%3CAddressValidateRequest%20USERID=%22Testuserid%22%3E%3CAddress%20ID=%221%22%3E%3CAddress1%3E%3C/Address1%3E%3CAddress2%3E10051+Orr+%26amp%3b+Day+Rd%3C/Address2%3E%3CCity%3Esanta+fe+springs%3C/City%3E%3CState%3Eca%3C/State%3E%3CZip5%3E90670%3C/Zip5%3E%3CZip4%3E%3C/Zip4%3E%3C/Address%3E%3C/AddressValidateRequest%3E
Anyone know about this problem...
Code Is below:
public Package GetDeliveryConfirmationLabel(Package package)
{
string labeldate = package.ShipDate.ToShortDateString();
if (package.ShipDate.ToShortDateString() == DateTime.Now.ToShortDateString())
labeldate = "";
string url = "?API=DelivConfirmCertifyV3.0Request&XML=<DelivConfirmCertifyV3.0Request.0Request USERID=\"{0}\"><Option>{1}</Option><ImageParameters></ImageParameters><FromName>{2}</FromName><FromFirm>{3}</FromFirm><FromAddress1>{4}</FromAddress1><FromAddress2>{5}</FromAddress2><FromCity>{6}</FromCity><FromState>{7}</FromState><FromZip5>{8}</FromZip5><FromZip4>{9}</FromZip4><ToName>{10}</ToName><ToFirm>{11}</ToFirm><ToAddress1>{12}</ToAddress1><ToAddress2>{13}</ToAddress2><ToCity>{14}</ToCity><ToState>{15}</ToState><ToZip5>{16}</ToZip5><ToZip4>{17}</ToZip4><WeightInOunces>{18}</WeightInOunces><ServiceType>{19}</ServiceType><POZipCode>{20}</POZipCode><ImageType>{21}</ImageType><LabelDate>{22}</LabelDate><CustomerRefNo>{23}</CustomerRefNo><AddressServiceRequested>{24}</AddressServiceRequested><SenderName>{25}</SenderName><SenderEMail>{26}</SenderEMail><RecipientName>{27}</RecipientName><RecipientEMail>{28}</RecipientEMail></DelivConfirmCertifyV3.0Request.0Request>";
url = GetURL() + url;
//url = String.Format(url,this._userid, (int)package.LabelType, package.FromAddress.Contact, package.FromAddress.FirmName, package.FromAddress.Address1, package.FromAddress.Address2, package.FromAddress.City, package.FromAddress.State, package.FromAddress.Zip, package.FromAddress.ZipPlus4, package.ToAddress.Contact, package.ToAddress.FirmName, package.ToAddress.Address1, package.ToAddress.Address2, package.ToAddress.City, package.ToAddress.State, package.ToAddress.Zip, package.ToAddress.ZipPlus4, package.WeightInOunces.ToString(), package.ServiceType.ToString().Replace("_", " "), package.OriginZipcode, package.LabelImageType.ToString(), labeldate, package.ReferenceNumber, package.AddressServiceRequested.ToString(), package.FromAddress.Contact, package.FromAddress.ContactEmail, package.ToAddress.Contact, package.ToAddress.ContactEmail);
url = String.Format(url, this._userid, (int)package.LabelType, package.FromAddress.Contact, package.FromAddress.FirmName, package.FromAddress.Address1, package.FromAddress.Address2, package.FromAddress.City, package.FromAddress.State, package.FromAddress.Zip, package.FromAddress.ZipPlus4, package.ToAddress.Contact, package.ToAddress.FirmName, package.ToAddress.Address1, package.ToAddress.Address2, package.ToAddress.City, package.ToAddress.State, package.ToAddress.Zip, package.ToAddress.ZipPlus4, package.WeightInOunces.ToString(), package.ServiceType.ToString().Replace("_", " "), package.OriginZipcode, package.LabelImageType.ToString(), labeldate, package.ReferenceNumber, package.AddressServiceRequested.ToString(), "", "", "", "");
string xml = web.DownloadString(url);
if (xml.Contains("<Error>"))
{
int idx1 = xml.IndexOf("<Description>") + 13;
int idx2 = xml.IndexOf("</Description>");
int l = xml.Length;
string errDesc = xml.Substring(idx1, idx2 - idx1);
throw new USPSManagerException(errDesc);
}
int i1 = xml.IndexOf("<DeliveryConfirmationLabel>") + 27;
int i2 = xml.IndexOf("</DeliveryConfirmationLabel>");
package.ShippingLabel = StringToUTF8ByteArray(xml.Substring(i1, i2 - i1));
return package;
}
I get the error on
int i1 = xml.IndexOf("<DeliveryConfirmationLabel>") + 27;
The solution to your problem is the same on this stackoverflow question- How to remove 'SAMPLE DO NOT MAIL' from USPS shipping API image
And you can find the steps to get this done from my answer on that question or by directly following this link- https://stackoverflow.com/a/27936025/3748701
USPS returns the Label in Base64 string you'd be required to convert that into an image. In my application i was required to provide the image as downloadable file, so I have returned the file result from the controller-action. Below is the action which gets the Base64 string label from DB, converts it into image and provides as downloadable file-
public ActionResult GetReturnShippingLabel(int orderId, bool showFull)
{
string shippingLabel = new OrderRepository().GetOrderReturnShippingLabel(orderId);
if (!string.IsNullOrEmpty(shippingLabel))
{
byte[] bytes = Convert.FromBase64String(shippingLabel);
Image image = null;
MemoryStream ms = new MemoryStream(bytes, 0, bytes.Length);
ms.Write(bytes, 0, bytes.Length);
image = Image.FromStream(ms, true);
image.RotateFlip(RotateFlipType.Rotate90FlipNone);
if (!showFull)
image = image.GetThumbnailImage(326, 570, null, IntPtr.Zero);
ImageConverter converter = new ImageConverter();
byte[] imgArray = (byte[])converter.ConvertTo(image, typeof(byte[]));
return File(imgArray.ToArray(), "image/gif");
}
else
{
return null;
}
}
Related
var PDF = new ActionAsPdf("TestReport", null)
{
FileName = "TestFile.pdf",
PageOrientation = Rotativa.Options.Orientation.Landscape,
PageMargins = { Left = 1, Right = 1 }
};
byte[] PDFData = PDF.BuildPdf(ControllerContext);
Is it possible to check for a string (eg. "Daily Task") in the 'PDFData' ?
Please guide me. Thanks!
Try to convert byte array into string:
var str = System.Text.Encoding.Default.GetString(PDFData);
var isContains = str.Contains("Daily Task");
An example:
string dailyTask = " Daily Task ";
byte[] PDFData = Encoding.ASCII.GetBytes(dailyTask);
var str = System.Text.Encoding.Default.GetString(PDFData);
var isContains = str.Contains("Daily Task");
Console.WriteLine(isContains);
I have a flex program (AS3/Flash) that allows the user to create PNG images of portions of the stage and send them via email. This works swimmingly.
I want to take the same image and send it to the clipboard, but that does not work. So the next best thing is to allow them to send it to their browser, where they can save it to a file.
Here is the code that I am using to do that;
bmpPanelData.draw(uiPrintObject)
var baPanel:ByteArray = PNGEnc.encode(bmpPanelData);
// Clipboard.generalClipboard.clear();
// var bolClipboard:Boolean = Clipboard.generalClipboard.setData(ClipboardFormats.BITMAP_FORMAT, baPanel, true);
// trace('bolClipboard=' + bolClipboard);
var strFileName:String = strPrintObject;
var strFileExt:String = "png"
var variables:URLVariables = new URLVariables();
variables.mimeType = "application/octet-stream";
variables.fileExt = strFileExt;
baPanel.position = 0;
var strPanel:String = getBytes(baPanel);
// var strPanel:String = baPanel.readMultiByte(baPanel.bytesAvailable,"latin1");
variables.fileContents = escape(strPanel);
trace('strPanel.length=' + strPanel.length + ' baPanel.length=' + baPanel.length);
variables.disposition = "Attachment";
variables.fileName = strFileName;
var u:URLRequest = new URLRequest( RootDomain + "SendBinaryFile2.aspx");
u.data = variables;
u.method = "POST";
navigateToURL(u,"_blank");
}
catch (err:Error)
{
Alert.show("This Panel cannot be copied to the clipboard. \nSorry for the inconvenience \nError: " + err.errorID,"E-mail not premitted",Alert.OK)
}
(I left the clipboard stuff commented out in case someone knows how to do that. It is my understanding that you cannot send binary data to the clipboard from Flash, but it works in AIR.)
Since I could not find an AS3 method to convert a binary ByteArray to a string I wrote my own called getBytes. If you know of a method in AS3, please let me know.
private function getBytes(baArray:ByteArray):String
{
var strOut:String = "";
baArray.position = 0;
var intBASize:int = baArray.bytesAvailable;
for (var i:int = 0;i < intBASize;i++)
{
strOut += String.fromCharCode(baArray.readByte());
}
return strOut;
}
On the ASPX side I have a file called SendBinaryFile2.aspx that looks like this;
<%# Page Language="C#" validateRequest="false"%>
<script Runat="Server">
void Page_Load(Object sender, EventArgs e)
{
string fileExt = Request.Form["fileExt"];
string mimeType = Request.Form["mimeType"];
string disposition = Request.Form["disposition"];
string fileName = Request.Form["fileName"];
byte [] fileContents = Encoding.ASCII.GetBytes(HttpUtility.UrlDecode(Request.Form["fileContents"]));
Response.Buffer = true;
Response.Clear();
Response.AddHeader("Content-Length", fileContents.Length.ToString());
Response.ContentType = mimeType;
Response.AddHeader("Content-Disposition", disposition + "; filename=" + fileName + "." + fileExt);
Response.BinaryWrite(fileContents);
Response.Flush();
Response.Close();
Response.End();
}
</script>
The results is a file that looks a whole lot like a .PNG file, but is corrupt when it is opened. I have visually compared the file sent via email, and the one sent via this program using VIM, and they look similar, have roughly the same number of characters, begin/end with similar characters.
Help on any of the items defined above is greatly appreciated.
Try this for your getBytes function...
private function getBytes (baArray:ByteArray) : String
{
var strOut:String = ""; var strRead:String = "";
baArray.position = 0;
var intBASize:uint = baArray.length;
for (var i:int = 0; i < intBASize; i++)
{
strRead = baArray.readUnsignedByte().toString(16);
if(strRead.length < 2) { strRead = "0" + strRead; } //# do padding
strOut += strRead ;
}
return strOut.toUpperCase();
}
This should give you padded bytes. Consider x0FF3 becomes just xFF3 without the padding, later the other side could be assuming the bytes are really xFF30 leading to corrupt images.
I'd suggest you use Base64 encoding to transport your binary data. You already must have needed to use it for encoding your email attachment, anyways.
Actionscript:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/utils/Base64Encoder.html
c#:
byte[] textAsBytes = System.Convert.FromBase64String(encodedText);
Also, if your SWF is running as standalone AIR (You wrote "Flex program"...), you can directly save files anywhere and give the user a "Save as..." prompt to do so.
Source to save from AIR:
var bmpd:BitmapData = new BitmapData(myWidth, myHeight, true, 0);
bmpd.draw(mySource);
var imgByteArray:ByteArray = new PNGEncoder().encode(bmpd);
var fl:File = File.desktopDirectory.resolvePath("myImage.png");
var fs:FileStream = new FileStream();
fs.open(fl, FileMode.WRITE);
fs.writeBytes(imgByteArray);
fs.close();
I'm currently working on a project that include file transferring. The way I originally planned it was to read it in python via
f = open(filename)
f.read()
and write it in C# using the File object interface, and the same from C#, I'm reading it through
File.ReadAllText(file)
and saving it in python.
It is transferred via sockets.
For some reason, it keeps corrupting the files. Even though the sending is perfectly fine(I checked it a thousand times), the files is read and written properly, so I'm looking for information about how to read a file through text(only text) and not having it corrupted. Any help is welcome, thanks.
Networking(Python):
def send(msg, sock):
msg = msg.__repr__()
size_of_package = sys.getsizeof(msg)
package = str(size_of_package)+":"+ msg
sock.send(package)
def recv(sock):
try:
header = sock.recv(2)
while ":" not in header:
header += sock.recv(2)
size_of_package, separator, message_fragment = header.partition(":")
message = ""
while len(message) < int(size_of_package) - len(message_fragment):
recvsize = int(size_of_package) - len(message_fragment) - len(message)
if recvsize > 2048:
recvsize = 2048
message+=sock.recv(recvsize)
full_message = message_fragment + message
return full_message
except OverflowError:
return "OverflowError."
except:
print "Unexpected error:", sys.exc_info()[0]
raise
Networking C#:
private void Send(string st)
{
int size = Encoding.ASCII.GetByteCount(st);
string pack = size + ":" + st;
buffer = Encoding.ASCII.GetBytes(pack);
connection.Send(buffer);
MessageBox.Show(buffer.Length.ToString());
}
private string Recv()
{
try
{
buffer = new byte[2];
connection.Receive(buffer, 2, SocketFlags.Partial);
string header = Encoding.ASCII.GetString(buffer, 0, 2);
while (!header.Contains(":"))
{
connection.Receive(buffer, 2, SocketFlags.Partial);
header += Encoding.ASCII.GetString(buffer, 0, 2);
}
int size = int.Parse(header.Split(':')[0]);
string mes0 = header.Split(':')[1];
buffer = new byte[size];
connection.Receive(buffer, size, SocketFlags.Partial);
string fullmes = mes0 + Encoding.ASCII.GetString(buffer);
return fullmes;
}
catch(Exception e)
{
MessageBox.Show(e.ToString());
}
return "";
}
File saving (Python)
class fileSaver:
def __init__(self , fileInf):
self.fileInf = fileInf
self.file = open(BASE_PATH+fileInf.getPath(), "wb")
self.file.write(fileInf.getContent())
self.file.close()
where fileInf is an object that contains all the info, including content, etc.
File loading(C#):
StreamReader sr = new StreamReader(file);
networking.Upload(file.Substring(file.LastIndexOf('/')+1), basepath, sr.ReadToEnd());
sr.Close();
I have a web app written in C# that I need to be able to render an SSRS report on an aspx page without using the Report Viewer control.
As HTML inside a div tag would be perfect. I have the app attached to my SSRS instance via ReportingService2010 reference.
I've found some examples online but are for ReportingServices2005 and couldn't port them over.
How can I do this?
I pulled this out of a project I put together about a year ago.
A few key points:
you need to pass credentials to the report server.
you need to create an images path so that any images in your report are rendered and displayed in the html Report/GraphFiles/ "this should be relative to your app url"
and if your report has any parameters you will need to add them.
you will definitely need to tweek the code to get it going.
it uses the ReportExecutionService reference, you will have to play around with it but the nuts and bolts should all be here.
i'd really love to spend time cleaning it up a bit but i dont have the time sorry, i hope it helps
class RenderReport
{
public struct ReportServerCreds
{
public string UserName { get; set; }
public string Password { get; set; }
public string Domain { get; set; }
}
public ReportServerCreds GetReportCreds()
{
ReportServerCreds rsc = new ReportServerCreds();
rsc.UserName = ConfigurationManager.AppSettings["reportserveruser"].ToString();
rsc.Password = ConfigurationManager.AppSettings["reportserverpassword"].ToString();
rsc.Domain = ConfigurationManager.AppSettings["reportserverdomain"].ToString();
return rsc;
}
public enum SSRSExportType
{
HTML,PDF
}
public string RenderReport(string reportpath,SSRSExportType ExportType)
{
using (ReportExecutionService.ReportExecutionServiceSoapClient res = new ReportExecutionService.ReportExecutionServiceSoapClient("ReportExecutionServiceSoap"))
{
ReportExecutionService.ExecutionHeader ExecutionHeader = new ReportExecutionService.ExecutionHeader();
ReportExecutionService.TrustedUserHeader TrusteduserHeader = new ReportExecutionService.TrustedUserHeader();
res.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
ReportServerCreds rsc = GetReportCreds();
res.ClientCredentials.Windows.ClientCredential.Domain = rsc.Domain;
res.ClientCredentials.Windows.ClientCredential.UserName = rsc.UserName;
res.ClientCredentials.Windows.ClientCredential.Password = rsc.Password;
res.Open();
ReportExecutionService.ExecutionInfo ei = new ReportExecutionService.ExecutionInfo();
string format =null;
string deviceinfo =null;
string mimetype = null;
if (ExportType.ToString().ToLower() == "html")
{
format = "HTML4.0";
deviceinfo = #"<DeviceInfo><StreamRoot>/</StreamRoot><HTMLFragment>True</HTMLFragment></DeviceInfo>";
}
else if (ExportType.ToString().ToLower() == "pdf")
{
format = "PDF";
mimetype = "";
}
byte[] results = null;
string extension = null;
string Encoding = null;
ReportExecutionService.Warning[] warnings;
string[] streamids = null;
string historyid = null;
ReportExecutionService.ExecutionHeader Eheader;
ReportExecutionService.ServerInfoHeader serverinfoheader;
ReportExecutionService.ExecutionInfo executioninfo;
// Get available parameters from specified report.
ParameterValue[] paramvalues = null;
DataSourceCredentials[] dscreds = null;
ReportParameter[] rparams = null;
using (ReportService.ReportingService2005SoapClient lrs = new ReportService.ReportingService2005SoapClient("ReportingService2005Soap"))
{
lrs.ClientCredentials.Windows.AllowedImpersonationLevel = System.Security.Principal.TokenImpersonationLevel.Impersonation;
lrs.ClientCredentials.Windows.ClientCredential.Domain = rsc.Domain;
lrs.ClientCredentials.Windows.ClientCredential.UserName = rsc.UserName;
lrs.ClientCredentials.Windows.ClientCredential.Password = rsc.Password;
lrs.GetReportParameters(reportpath,historyid,false,paramvalues,dscreds,out rparams);
}
// Set report parameters here
//List<ReportExecutionService.ParameterValue> parametervalues = new List<ReportExecutionService.ParameterValue>();
//string enumber = Session["ENumber"] as string;
//parametervalues.Add(new ReportExecutionService.ParameterValue() { Name = "ENumber", Value = enumber });
//if (date != null)
//{
// DateTime dt = DateTime.Today;
//parametervalues.Add(new ReportExecutionService.ParameterValue() { Name = "AttendanceDate", Value = dt.ToString("MM/dd/yyyy")});
//}
//if (ContainsParameter(rparams, "DEEWRID"))
//{
//parametervalues.Add(new ReportExecutionService.ParameterValue() { Name = "DEEWRID", Value = deewrid });
//}
//if (ContainsParameter(rparams, "BaseHostURL"))
//{
// parametervalues.Add(new ReportExecutionService.ParameterValue() { Name = "BaseHostURL", Value = string.Concat("http://", Request.Url.Authority) });
//}
//parametervalues.Add(new ReportExecutionService.ParameterValue() {Name="AttendanceDate",Value=null });
//parametervalues.Add(new ReportExecutionService.ParameterValue() { Name = "ENumber", Value = "E1013" });
try
{
Eheader = res.LoadReport(TrusteduserHeader, reportpath, historyid, out serverinfoheader, out executioninfo);
serverinfoheader = res.SetExecutionParameters(Eheader, TrusteduserHeader, parametervalues.ToArray(), null, out executioninfo);
res.Render(Eheader, TrusteduserHeader, format, deviceinfo, out results, out extension, out mimetype, out Encoding, out warnings, out streamids);
string exportfilename = string.Concat(enumber, reportpath);
if (ExportType.ToString().ToLower() == "html")
{
//write html
string html = string.Empty;
html = System.Text.Encoding.Default.GetString(results);
html = GetReportImages(res, Eheader, TrusteduserHeader, format, streamids, html);
return html;
}
else if (ExportType.ToString().ToLower() == "pdf")
{
//write to pdf
Response.Buffer = true;
Response.Clear();
Response.ContentType = mimetype;
//Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.pdf", exportfilename));
Response.BinaryWrite(results);
Response.Flush();
Response.End();
}
}
catch (Exception e)
{
Response.Write(e.Message);
}
}
}
string GetReportImages(ReportExecutionService.ReportExecutionServiceSoapClient res,
ReportExecutionService.ExecutionHeader EHeader,
ReportExecutionService.TrustedUserHeader tuh,
string reportFormat, string[] streamIDs, string html)
{
if (reportFormat.Equals("HTML4.0") && streamIDs.Length > 0)
{
string devInfo;
string mimeType;
string Encoding;
int startIndex;
int endIndex;
string fileExtension = ".jpg";
string SessionId;
Byte[] image;
foreach (string streamId in streamIDs)
{
SessionId = Guid.NewGuid().ToString().Replace("}", "").Replace("{", "").Replace("-", "");
//startIndex = html.IndexOf(streamId);
//endIndex = startIndex + streamId.Length;
string reportreplacementname = string.Concat(streamId, "_", SessionId, fileExtension);
html = html.Replace(streamId, string.Concat(#"Report\GraphFiles\", reportreplacementname));
//html = html.Insert(endIndex, fileExtension);
//html = html.Insert(startIndex, #"Report/GraphFiles/" + SessionId + "_");
devInfo = "";
//Image = res.RenderStream(reportFormat, streamId, devInfo, out encoding, out mimeType);
res.RenderStream(EHeader,tuh, reportFormat, streamId, devInfo, out image , out Encoding, out mimeType);
System.IO.FileStream stream = System.IO.File.OpenWrite(HttpContext.Current.Request.PhysicalApplicationPath + "Report\\GraphFiles\\" + reportreplacementname);
stream.Write(image, 0, image.Length);
stream.Close();
mimeType = "text/html";
}
}
return html;
}
bool ContainsParameter(ReportParameter[] parameters, string paramname)
{
if(parameters.Where(i=>i.Name.Contains(paramname)).Count() != 0)
{
return true;
}
return false;
}
}
To Execute:
first parameter is the location of the report on the server.
the second is a SSRSExportType enum
RenderReport("ReportPathOnServer",SSRSExportType.HTML);
If you are just trying to show the HTML render of a report and you want it to look like a native object to the application without any parameters or toolbar, then you could call the URL for the report directly and include "&rc:Toolbar=false" in the URL. This will hide the toolbar for the Report Viewer control. This method is described under the URL Access Parameter Reference msdn article. Not exactly what you asked for, but it may achieve the purpose.
Here's a sample call that omits the HTML and Body sections if you are embedding the results in an existing HTML document:
http://ServerName/ReportServer?%2fSome+Folder%2fSome+Report+Name&rs:Command=Render&rc:Toolbar=false&rc:HTMLFragment=true
Definitely an old question but if you're using ASP.NET MVC you could try this open source solution. It uses an HTML helper and renders an .aspx page in an iframe. The repo has a server-side, local render, and anonymous example.
Here is my code :
HTML : <img src="thumbCreate.ashx?Id=223" alt="asd" />
HTTP Handler : `
public void ProcessRequest (HttpContext context)
{
CreateThumbNail(context);
}
private void CreateThumbNail(HttpContext context)
{
string resourceId = context.Request.QueryString["Id"];
context.Response.Write("No resource found for Id = " + resourceId);
Bitmap original = new Bitmap("C:/Devp/My work/ASHXSampleApp/Images/Desert.jpg");
int oWidth = original.Width;
int oHeight = original.Height;
int preferredWidth = 80;
int preferredHeight = 100;
int thumbWidthFactor = oWidth / preferredWidth;
int thumbHeightFactor = oHeight / preferredHeight;
int maxFactor = Math.Max(thumbWidthFactor, thumbHeightFactor);
int thumbNailWidth = oWidth / maxFactor;
int thumbNailHeight = oHeight / maxFactor;
Bitmap thumbNailImage = (Bitmap)original.GetThumbnailImage(thumbNailWidth, thumbNailHeight, ThumbNailCallback, IntPtr.Zero);
context.Response.ContentType = "image/Jpeg";
thumbNailImage.Save(context.Response.OutputStream, System.Drawing.Imaging.ImageFormat.Jpeg);
}`
But this code does not display image. When I manually try to run the handler in firefox, it gives me an error : - "The image “http://localhost:57157/ASHXSampleApp/thumbCreate.ashx?Id=223” cannot be displayed because it contains errors." Any idea?
The problem comes from this part of your code.
string resourceId = context.Request.QueryString["Id"];
context.Response.Write("No resource found for Id = " + resourceId);
You are always adding a string to the response stream and then you write the image data afterwards which will result in a corrupted string. Remove that (or make it conditional so it is added when an error occurs or something) and it should work.
Does context.Response.WriteFile() work?