I'm using a RTF file as a template for an ASP.NET web application. My VB.NET code reads the file using a StreamReader, replaces some strings, and creates a new Word document with data from the database. My code closes and disposes of the StreamReader. However, when I attempt to upload a revised RTF file to the web server I get an error, "Cannot open the file for writing". So obviously the file remains open long after the ASP.NET page has run.
How can I force the StreamReader to close? Even editing the web.config file to force the web application to restart isn't enough to kill the lock on this file.
consider using the "using" idiom, also available in VB.net
using(StreamReader reader = new StreamReader(...)) {
}
the stream will get closed, even if exception is thrown
Consider closing all IDisposable implementations like this
It seems odd if it's hanging on even after a close/dispose. Are you using a FileStream along with the StreamReader? Generally, I use a FileStream to control access to the file and feed that to the StreamReader, a la:
FileStream fsIn = new FileStream("path",FileMode.Open, FileAccess.Read, FileShare.None);
StreamReader srIn = new StreamReader(fsIn, System.Text.Encoding.Default);
//...do stuff....
srIn.close();
srIn.Dispose();
fsIn.close();
fsIn.Dispose();
Better yet, if you're limiting the use of your StreamReader to one method, stick the Close/Dispose in a Finally.
Make sure the stream is closed in finally.
FileStream fsIn = null;
StreamReader srIn = null;
try
{
fsIn = new FileStream("path",FileMode.Open, FileAccess.Read, FileShare.None);
srIn = new StreamReader(fsIn, System.Text.Encoding.Default);
//...do stuff....
}
catch (Exception ex)
{
}
finally
{
srIn.close();
srIn.Dispose();
fsIn.close();
fsIn.Dispose();
}
Related
I subscribe to a mass email service which, when an error occurs at their end, posts to a page on my website as an endpoint to notify me that an email has bounced.
They describe it as follows:
The event data is sent in the POST request body using a JSON object.
What I need to know is how can I capture the info posted to me?
Currently I'm pointing them to a generic handler, a .ashx page, this can be changed to whatever as long as it's in .NET.
In 10 years working with first classic ASP and now .NET I've never done this before and I must admit I don't even know where to start.
This is the code I used to achieve a similar thing - not sure where I got it originally.
C#
var strJSON = String.Empty;
context.Request.InputStream.Position = 0;
using (var inputStream = new StreamReader(context.Request.InputStream))
{
strJSON = inputStream.ReadToEnd();
}
JavaScriptSerializer javaScriptSerializer = new JavaScriptSerializer();
object serJsonDetails = javaScriptSerializer.Deserialize(strJSON, typeof(object));
// go and process the serJsonDetails object
or VB
Dim strJSON = [String].Empty
context.Request.InputStream.Position = 0
Using inputStream = New StreamReader(context.Request.InputStream)
strJSON = inputStream.ReadToEnd()
End Using
Dim javaScriptSerializer As New JavaScriptSerializer()
Dim serJsonDetails As Object = javaScriptSerializer.Deserialize(strJSON, GetType(Object))
' go and process the serJsonDetails object
You could just read the Request stream (Request.GetRequestStream) and use Json.NET to deserialize to an object.
You could use MVC4 and the built in object mapping.
There's many options. Perhaps you should read up on them more so that you have an idea of their capabilities and drawbacks.
Probably Request.Form (here) will help you get the JSON, if you know the content of the post, and then you need something like json.net library to get the object, or you can simply search the string using regex or keywords
Or if you can direct the post to a web service(asmx) instead of a web page, those services will parse the json for you
If you need to read raw post data twice or many times, i advice you to use this code.
string postBodyJson = null;
MemoryStream ms = new MemoryStream();
Request.InputStream.Position = 0;
Request.InputStream.Seek(0, SeekOrigin.Begin);
Request.InputStream.CopyTo(ms);
ms.Position = 0;
ms.Seek(0, SeekOrigin.Begin);
using (var reader = new StreamReader(ms))
{
postBodyJson = reader.ReadToEnd();
}
I am using iTextSharp for creating pdf reports (files) and storing those on the web server where my application resides. I am able to create the file, go into the storage folder and open the file without a problem. Notice: The user is not to get the file automatically
downloaded on creation.
I want to give the user the option to download "old" reports from the server with a button.
This is working fine in IE (10) but not in Chrome and Firefox. I always get the error message:
There was an error opening this document. The file is damaged and could not be repaired.
I have this image button and on click I send the user to a Generic Handler (since my page contains Update Panels) according to this post (only using it partially for now).
This is the code that actually downloads the file:
public void ProcessRequest(HttpContext context)
{
var _fileName = context.Request.QueryString["fileName"];
using (var _output = new MemoryStream())
{
//var _fileSeverPath = context.Server.MapPath(_fileName);
context.Response.Clear();
context.Response.ContentType = "application/pdf";// "application/pdf";
//context.Response.AppendHeader("Content-Length", _fileName.Length.ToString());
context.Response.AppendHeader("Content-Disposition", string.Format("attachment; filename=" + Path.GetFileName(_fileName)));
context.Response.WriteFile(_fileName);
context.Response.Flush();
context.Response.Close();
context.Response.End();
}
}
As I said, this works fine in IE but not in Chrome and Firefox.
When I open the file in Notepad it seams that I only get about 1/3 of the file when downloaded in Chrome and Firefox.
Any suggestions would be greatly appreciated. Been trying to resolve this for a few days now..
From HttpResponse.WriteFile Method (String)
When this method is used with large files, calling the method might
throw an exception. The size of the file that can be used with this
method depends on the hardware configuration of the Web server. For
more information, see article 812406, "PRB: Response.WriteFile Cannot
Download a Large File" on the Microsoft Knowledge Base Web site.
Try this instead:
public void ProcessRequest(HttpContext context)
{
var _fileName = context.Request.QueryString["fileName"];
context.Response.Clear();
context.Response.Buffer = true;
context.Response.ContentType = "application/pdf";
context.Response.AppendHeader(
"Content-Disposition",
string.Format("attachment; filename=" + Path.GetFileName(_fileName)));
using (var fs = new FileStream(_fileName, FileMode.Open, FileAccess.Read))
{
using (var sr = new StreamReader(fs, true))
{
int length = (int)fs.Length;
byte[] buffer;
using (BinaryReader br = new BinaryReader(fs, sr.CurrentEncoding))
{
buffer = br.ReadBytes(length);
context.Response.BinaryWrite(buffer);
}
}
}
context.Response.Flush();
context.Response.Close();
context.Response.End();
}
Ok, FINALLY.. I found the solution and it makes me feel like a fool at the same time..
Removed context.Response.Close(); ...then everything worked perfectly :)
Hi i have the following code to read the xml file and change the value of particular node ,but i want to do the same using xmltextreader or xmlreader, i am trying to avoid the statement doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml")); , which has a direct reference to my physical file.
XmlDocument doc = new XmlDocument();
string xmlFile = System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml");
doc.Load(xmlFile);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));
Well something's going to have to have a reference to the file. However, you could easily change your code to simply accept a Stream (which would have to be readable, writable and seekable):
private static void ChangeDocument(Stream stream)
{
XmlDocument doc = new XmlDocument();
doc.Load(stream);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
stream.Position = 0;
doc.Save(stream);
stream.SetLength(stream.Position); // Truncate the file if it was longer
}
It's somewhat ugly, admittedly...
Of course you could always pass in the filename itself - your MapPath call would still be in a higher level method, which may be all you're trying to achieve:
private static void ChangeDocument(string filename)
{
XmlDocument doc = new XmlDocument();
doc.Load(filename);
XmlNodeList xmlnode = doc.GetElementsByTagName("value");
xmlnode[0].ChildNodes[0].Value = 23;
doc.Save(filename);
}
One final aside - if you're using .NET 3.5 or higher, I'd strongly recommend using LINQ to XML as a rather nicer XML API.
You can not write or update XML data using XmlTextReader or XmlReader ansectors, use XmlTextWriter or XmlWriter ancestors, ot XmlSerializer.Serialize(..) method as alternative.
You can not avoid the statement and alike,
doc.Save(System.Web.HttpContext.Current.Server.MapPath("Data/Example.xml"));
which has a direct reference to your physical file, because you have to write the changed nodes back to the origin file again, otherwize you have to switch your system from using file-based approach (ASP.NET web site using file-based data storage) to database-driven approach (ASP.NET web site using the database server).
As alternative, use your own XML data in your SQL server, then load and update it using EF of ORM.
I need to have a page on my website that when opened will read another URL address and capture the response from it (it's actually XML data responding) and then save that data on that same webservr to a file called DATA.XML
It needs to overwrite any file that is already there.
I only have ASP.NET available to me as a progrmming language.
Can someone show me how to do this in a ASP page.
so something like?
Get the response from the other URL in to strResult.
WebResponse objResponse;
WebRequest objRequest = HttpWebRequest.Create(strURL);
objResponse = objRequest.GetResponse();
using (StreamReader sr = new StreamReader(objResponse.GetResponseStream()))
{
strResult = sr.ReadToEnd();
sr.Close();
}
return strResult;
Use System.IO to save the strResult to a file (you can look that up as its pretty common code)
I am using the following code to export a data set to an Excel sheet.
[WebMethod]
public static void ExporttoExcel()
{
DataSet ds;
productfactory pf=new productfactory();
ds = pf.getproducts();
HttpResponse response = HttpContext.Current.Response;
// first let's clean up the response.object
response.Clear();
response.Charset = "";
response.ContentEncoding = System.Text.Encoding.Default;
// set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"products.xls\"");
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
// instantiate a datagrid
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
string filepath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + "\\products.xls";
response.Write(sw.ToString());
// response.End();
}
}
}
The problem is that it's not raising file download and hence no export is taking place. The same code works fine in a normal method. But with the web method it's not working.
I suggest to make an HttpHandler ending in ashx, and place inside him your code that create the excel file.
then call it from your javascript code like that.
document.location.href = "ExporttoExcel.ashx";
The problem is that WebMethods are not designed to allow you to interact with the Response object (evident in that it wasn't available and you had to use HttpContext.Current.Response to get to it). WebMethods are designed to be blackbox to the user. They will perform and action and/or return a value.
Perhaps you can give us a better idea of what you are trying to accomplish and we can suggest an alternate solution.
u can use to create a dynamic iframe with URL set to the Web Handler to generate the Excel this will raise the file download with out posting the current page.