What i am trying to do is, i am getting file name/path using asp.net uploader control and then saving its path it grid view. e.g
String path = String.Empty;
path = FileUploader.FileName;
and then saving this path in grid view column.
savefiletoGrid(path);
After uploading all required files i am saving these file on server. like this
while( // condition )
{
string tempfilename = ""; // file name/path from gridview
string path2 = Server.MapPath("Dir\\" + tempfilename);
FileUploader.SaveAs(path2);
}
But, problem is that file is being saved on server with correct name but with size 0 byte.
Please let me know how to solve this issue ?
Actually i want something like client upload in asp.net, i 'll upload more than one file and show them in gridview ( or in something else ) so that user can see files to be selected and can delete from listed files.
File 'll be saved to server only when user click some other button say 'Update'. could you please help me , how to accomplish this ?
You have to catch the event generated in GridView in its RowCommand event also set a CommandName property for upload button.
Following is the detailed code through which you can accomplish this:
<asp:GridView ID="GridView1" runat="server" OnRowCommand="GridView1_RowCommand">
<Columns>
<asp:TemplateField>
<ItemTemplate>
<asp:FileUpload ID="FileUpload1" runat="server" />
<asp:Button ID="Button1" runat="server" Text="Upload" CommandName="Upload"/>
</ItemTemplate>
</asp:TemplateField>
</Columns>
</asp:GridView>
And in you code behind:
protected void GridView1_RowCommand(object sender, GridViewCommandEventArgs e)
{
if (e.CommandName == "Upload")
{
FileUpload FileUp = (FileUpload)e.Item.FindControl("FileUpload1");
string UploadedFileName = FileUp.FileName;
string Path = Server.MapPath("Documents");
FileUpload.SaveAs(Path + "\\" + UploadedFileName);
}
}
Hope it helps.
To accomplish this functionality, you'll have to let the user upload the files. You must save them temporarily to display them.
Then, upon the user clicking an 'Update' button, you will transfer the temporary files to your permanent storage.
Do you keep the FileUploaders in a GridView?
Problem has been solved by creating a DataTable with one column for control (with column data Type FileUpload) for example :
private DataTable CreateDtDocs(string name, string path, FileUpload FileUploader)
{
DataTable dt1 = new DataTable();
dt1.Columns.Add("SR_NO");
dt1.Columns.Add("Name");
dt1.Columns.Add("Path");
Type col_type = fubrowse.GetType();
DataColumn dt_col = new DataColumn("Control", col_type);
dt1.Columns.Add(dt_col);
DataRow dr = dt1.NewRow();
dr["SR_NO"] = "1";
dr["NAME"] = name;
dr["Path"] = path;
dr["Control"] = FileUploader;
dt1.Rows.Add(dr);
return dt1;
}
And then Populate table like below :
private DataTable AddDtDocs(string name, string path, FileUpload FileUploader)
{
DataTable dt1 = (DataTable)Session["AttachFilesdt"];
int count = dt1.Rows.Count;
DataRow dr = dt1.NewRow();
dr["SR_NO"] = count + 1;
dr["NAME"] = name;
dr["Path"] = path;
dr["Control"] = FileUploader;
dt1.Rows.Add(dr);
return dt1;
}
And then i am adding path name and control in Dictionary and passing them to a different function to save them on server.
Dictionary<string, FileUpload> DocsPathAndControl = new Dictionary<string, FileUpload>();
if (Session["AttachFilesdt"] != null)
{
tempdt = (DataTable)Session["AttachFilesdt"];
for (int i = 0; i < tempdt.Rows.Count; i++)
{
DocsPathAndControl.Add(tempdt.Rows[i]["Path"].ToString(), (FileUpload)tempdt.Rows[i]["Control"]);
}
Session["AttachFilesdt"] = null;
}
Function to save Files
private void AddDocuments(int jurisdictionID, Dictionary<string,FileUpload> docPathsAndControl)
{
foreach (var item in docPathsAndControl)
{
string tempfilename = jurisdictionID + "_" + item.Key.ToString();
string path = Server.MapPath("Dir\\" + tempfilename);
FileUpload FileUploaderControl = (FileUpload)item.Value;
FileUploaderControl.PostedFile.SaveAs(path);
}
}
Hope, it 'll help.
Related
So I finally was able to create a XML and change it as I want but now I needed to add the contents of a DataGridView to it. I thought that's quite easy as I saw the options to place it into a DataSet and use XmlWrite, but that was a mistake of me. Note that I'm still trying to learn C# so probably I make a silly mistake here. It is still not working maybe someone is willing to point me out what I am doing wrong?
I actually have two issues with this:
It ForEach loop doesn't get the existing column names
It doesn't add the table and its contents to the XML file
private void CreateClientFile()
{
string filename;
filename = Company + "_" + SiteName + ".xml";
XmlDocument doc = new XmlDocument();
XmlElement root = doc.CreateElement("CompanyProfile");
doc.AppendChild(root);
//Save document on Harddisk
doc.Save(#"C:\Users\NLRAGIL\Documents\10 - VibroManager\" + filename);
//Need to save first and than load again????
//Load document into program
doc.Load(#"C:\Users\NLRAGIL\Documents\10 - VibroManager\" + filename);
XmlNode main = doc.SelectSingleNode("CompanyProfile");
//Create Company name element
XmlElement companyname = doc.CreateElement("CompanyName");
companyname.InnerText = CompanyName;
main.AppendChild(companyname);
//Create sitename element
XmlElement sitename = doc.CreateElement("Sitename");
sitename.InnerText = SiteName;
main.AppendChild(sitename);
//Create IMO element
XmlElement imo = doc.CreateElement("IMO");
imo.InnerText = IMO;
main.AppendChild(imo);
DataTable dt = new DataTable();
for (int i = 0; i < dataGridView1.Columns.Count; i++)
{
dt.Columns.Add("column" + i.ToString());
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < dataGridView1.Columns.Count; j++)
{
dr["column" + j.ToString()] = row.Cells[j].Value ;
}
dt.Rows.Add(dr);
}
//Create DataSet and add the datatable
DataSet ds = new DataSet();
ds.Tables.Add(dt);
//Give the file name for where to write to.
ds.WriteXml(#"C:\Users\NLRAGIL\Documents\10 - VibroManager\" + filename);
//Show example for debugging
doc.Save(#"C:\Users\NLRAGIL\Documents\10 - VibroManager\" + filename);
System.Console.WriteLine(doc.InnerXml);
}
EXTRA CLARIFICATION:
The form I have looks as below:
The Textbox in the groupbox "Client Information" I'm able to save in a XML file. By altering the value of the numeric control I can express how much machine the particular client has. And the DataGridView gets more or less rows. But the information from the DataGridView I'm unable to append to the created XML file.
So the information from "Machine Name", "Serial No" etc I can't add to the XML file.
This is what I wanted to do, so later on in the program I can add certain measurements of each machine to it and store also in the same file.
But whatever I do my XML file looks like this:
I hope I explained it better now sorry for the confusion
Your question is Add the contents of a DataGridView to an existing XML file and you say your first issue is that your ForNext loop is not giving you the column names and your second issue is that the code fails to serialize the record to an XML file on disk. These two goals can be simplified by using Data Binding. This decouples your data from the view, making it easier to process. I would like to give you some insight if you wanted to try it out using the CompanyProfile in your code.
First, a CompanyProfile class declares the intended public properties:
public class CompanyProfile
{
public string CompanyName { get; set; }
public string SiteName { get; set; }
public string IMO { get; set; } = "Some Value";
}
Next, in your MainForm class a BindingList<CompanyProfile> is declared and attached to the DataGridView like this:
BindingList<CompanyProfile> DataSource = new BindingList<CompanyProfile>();
protected override void OnHandleCreated(EventArgs e)
{
base.OnHandleCreated(e);
if(!DesignMode)
{
// Attach the data source to the view. Now changes to source records refresh in the view.
dataGridView1.DataSource = this.DataSource;
// Adding one or more records will generate the columns.
DataSource.Add(new CompanyProfile { CompanyName = "Linear Technology", SiteName = "Colorado Design Center"});
DataSource.Add(new CompanyProfile { CompanyName = "Analog Devices", SiteName = "1-1-2"});
// Use string indexer to get a column
dataGridView1.Columns[nameof(CompanyProfile.CompanyName)].AutoSizeMode = dataGridViewAutoSizeColumnMode.Fill;
dataGridView1.Columns[nameof(CompanyProfile.SiteName)].AutoSizeMode = DataGridViewAutoSizeColumnMode.Fill;
DataGridView1.AllowUserToAddRows = false;
}
}
The resulting DataGridView now looks like this:
This method makes a single file from a CompanyProfile record using XmlSerializer (but this is just one approach - and you could also serialize the entire list at one time if you choose).
private void CreateClientFile(CompanyProfile companyProfile, string fileName)
{
System.Xml.Serialization.XmlSerializer x = new System.Xml.Serialization.XmlSerializer(typeof(CompanyProfile));
using (var writer = new StreamWriter(fileName))
{
x.Serialize(writer, companyProfile);
}
// Open the file to view the result
Process.Start("notepad.exe", fileName);
}
Now, iterate a ForNext loop on the DataSource not the DataGridView. You no longer need to worry about columns because you have the bound properties instead.
private void btnSerialize_Click(object sender, EventArgs e)
{
var appData = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"datagridview_to_xml");
Directory.CreateDirectory(appData);
// Iterate the datasource list, not the DataGridView.
foreach (CompanyProfile companyProfile in DataSource)
{
CreateClientFile(
companyProfile,
fileName: Path.Combine(appData,
$"{companyProfile.CompanyName}_{companyProfile.SiteName}.xml")
);
}
}
Clicking the [Serialize] button reveals the two files.
I have too many files on ftp server which I want to display in data gridview without saving or downloading and sort by date. These files are .qrt but I can open them in excel or notepad.
I did that but from sql db but never worked with ftp.
These files have names with dates.
I'm using asp.net web forms in C#.
How can I do this?
This as noted is quite easy. But, you don't mention if you have a bunch of folders that you want to display, or just files from one FTP folder?
As noted, if you have a bunch of folders, then VERY easy to use a tree view to display this hierarchy type setup. However, for one folder? Sure, a GridView is a great choice.
You can say use this:
our markup is thus this:
<asp:GridView ID="GridView1" runat="server"
CssClass="table" Width="20%"></asp:GridView>
Ok, and our code is this:
using System.Net;
using System.IO;
So, for page load, we have this:
const string UserId = "User Name here";
const string Password = "Password here";
const string fRoot = "ftp://ftp.mycoolwebsite.com/test";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
LoadGrid();
}
void LoadGrid()
{
DataTable MyFiles = new DataTable();
MyFiles.Columns.Add("File", typeof(string));
List<string> fList = GetFtpFiles();
foreach (string sFile in fList)
{
DataRow OneRow = MyFiles.NewRow();
OneRow["File"] = sFile;
MyFiles.Rows.Add(OneRow);
}
GridView1.DataSource = MyFiles;
GridView1.DataBind();
}
List<string> GetFtpFiles()
{
FtpWebRequest ftpR = (FtpWebRequest)WebRequest.Create(fRoot);
ftpR.Credentials = new NetworkCredential(UserId, Password);
ftpR.Method = WebRequestMethods.Ftp.ListDirectory;
FtpWebResponse response = ftpR.GetResponse() as FtpWebResponse;
StreamReader sread = new StreamReader(response.GetResponseStream());
List<string> myDir = new List<string>();
string oneLine = sread.ReadLine();
while (!string.IsNullOrEmpty(oneLine))
{
myDir.Add(oneLine);
oneLine = sread.ReadLine();
}
sread.Close();
return myDir;
}
And out output is now this:
Now, if we want the file size? that's a problem, since in theory ONCE we have the file list, we could cook up code to "request" each file size - that's a pain, but WORSE is a lot of requests. The other way, is we can change this:
ftpR.Method = WebRequestMethods.Ftp.ListDirectory;
to:
ftpR.Method = WebRequestMethods.Ftp.ListDirectoryDetails;
The above will return file information VERY much like an old style DOS file listing.
When we run above with above, we now get this:
So, if we want to sort say by file name, we have to parse out the file name, and date. This is not too hard. As noted, the other way is to "request" the file size an date for each file - but that is extra code, but WORSE is a LOT of hits to the ftp server.
And the style of the file listings are not consistent from web servers (might be windows, or linux), but we COULD parse out the above into columns - and then we can sort by date, or file name.
Parsing? Gee, this works:
void LoadGrid()
{
DataTable MyFiles = new DataTable();
MyFiles.Columns.Add("Date", typeof(DateTime));
MyFiles.Columns.Add("Size", typeof(int));
MyFiles.Columns.Add("File", typeof(string));
List<string> fList = GetFtpFiles();
foreach (string s in fList)
{
DataRow OneRow = MyFiles.NewRow();
string sRow = s;
while (sRow.Contains(" "))
sRow = sRow.Replace(" ", " ");
sRow = sRow.Replace(" ", ",");
string[] scols = sRow.Split(',');
OneRow["Size"] = scols[4];
OneRow["File"] = scols[8];
OneRow["Date"] = scols[7] + "-" + scols[6] + "-" + scols[5];
MyFiles.Rows.Add(OneRow);
}
GridView1.DataSource = MyFiles;
GridView1.DataBind();
}
And now we get this:
We need to formt that ate in the grid - but at least now, with a table, you can sort that table by date, or filename before you bind it, say like this:
MyFiles.DefaultView.Sort = "File";
GridView1.DataSource = MyFiles;
GridView1.DataBind();
And you can/could sort by date also - since we defined date column as datetime.
I have a datatable containing file paths which I am passing via viewstate (referencing, via a linkbutton, an index in this table), wanting to then use the path from the table to construct a HTTP filetransfer. (So 3 cols; name, path and index)
I am unable to successfully retrieve the datatable once saved in viewstate;
ViewState["varFiles"] = filedata;
(When page is originally constructed, then after postback:)
if (!IsPostBack) { SetupSession(); newpopfiles(); }
else { { if (ViewState["varFiles"] != null) { DataTable filedata = new DataTable(); filedata = (DataTable)Session["varFiles"]; } } }
From what I understand this should pull back filedata as a table in exactly the same form as before postback. Is this correct?
When subsequently referencing the table I get a null reference exception. Any ideas?
Many thanks,
Dan
It sounds like you're almost there, just need to be a bit more consistent with using the same storage mechanism :)
The bit to save the DataTable into your session, probably in OnInit() or PageLoad():
DataTable myDataTable = //... fill it in somehow
Session["varFiles"] = myDataTable;
The bit to read the DataTable after postback:
if (!IsPostBack)
{
SetupSession();
newpopfiles();
}
else
{
DataTable filedata = Session["varFiles"] as DataTable;
if (filedata != null)
{
//... do something
}
}
I'm having some evils trying to get my GridView control to behave. I have the below code, which successfully displays all the files in the directory. However I require two changes, both of which I am struggling with:
a) Currently the URL you get when clicking on the URL field is
http://localhost/LBSExplorer/SharedUser.csv (ie my home directory with the filename).
What I require is that the 'Display Text' be the filename only, and the URL be my desired text followed by the filename eg:
http://mystuff/page.aspx?FileID=SharedUser.csv
b) I want only to see the files that start with a certain prefix eg "Pay". I can do that with something like:
string[] filelist = Directory.GetFiles((#"C:\MF\Data\","Pay*.*");
but this doesn't like to bind to my Gridview!
I'd appreciate your help!
Mark
const string DocumentFolderPhysicalPath = (#"C:\MF\Data\");
const string DocumentFolderUrl = (#"C:\MF\Data\"); //"http://localhost/virtualfoldernameyouexposed/"; ; // now it is hardcoded but you could retreive it automatically
HyperLinkField hyperLinkField = new HyperLinkField();
hyperLinkField.DataTextField = "Name";
hyperLinkField.DataNavigateUrlFields = new string[] { "Name" };
//Would like this to work!
//HyperLinkField hyperLinkField2 = new HyperLinkField();
//hyperLinkField2.DataTextField = "Destination";
//hyperLinkField2.DataNavigateUrlFields = new string[] { (#"C:\MF\Data\") + "Name" };
GridView1.DataSource = GetDocuments(DocumentFolderPhysicalPath);
GridView1.Columns.Add(hyperLinkField);
GridView1.DataBind();
private System.IO.FileInfo[] GetDocuments(string physicalPath)
{
System.IO.DirectoryInfo directory =
new System.IO.DirectoryInfo(physicalPath);
if (directory.Exists)
{
return directory.GetFiles();
}
else
{
throw new System.IO.DirectoryNotFoundException(physicalPath);
}
}
What you are looking for is the DataNavigateUrlFormatString property.
hyperLinkField.DataNavigateUrlFormatString = "http://mystuff/page.aspx?FileID={0}";
The {0} here is replaced with your DataNavigateUrlFields value.
I want to load the data into session so that when the next button is clicked in crystal report viewer then in should load the data from the datatable instead retrieving the data again from the database. Here goes my code...
ReportDocument rpt = new ReportDocument();
DataTable resultSet = new DataTable();
string reportpath = null;
protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
if (Request.QueryString.Get("id") == "5")
{
string publication = Request.QueryString.Get("pub");
DateTime date = DateTime.Parse(Request.QueryString.Get("date"));
int pages = int.Parse(Request.QueryString.Get("pages"));
int sort = int.Parse(Request.QueryString.Get("sort"));
if (sort == 0)
{
reportpath = Server.MapPath("IssuesReport.rpt");
rpt.Load(reportpath);
DataTable resultSet1 = RetrievalProcedures.IssuesReport(date, publication, pages);
Session["Record"] = resultSet1;
}
DataTable report = (DataTable)Session["Record"];
rpt.SetDataSource(report);
CrystalReportViewer1.ReportSource = rpt;
I am trying this code but when i clicked the next button it gives me the error that invalid report source..i guess the session is null thats why its giving me this error.
Any sugesstions how can I solve this...
I think you'd want to use the Cache object with a unique key for each user instead of Session here.
Pseudo code:
var data = Cache["Record_999"] as DataTable;
if (data == null) {
// get from db
// insert into cache
}
SetDataSource(data);
The problem lies not in with using Session, it lies with the logic used to determine when to retrieve data. Session is the correct approach to use here as Cache is shared across requests - that is, User A would see the report User B just configured if User B was the first user to execute code that used Cache instead of Session.
if (!Page.IsPostBack)
{
if (Request.QueryString.Get("id") == "5")
{
string publication = Request.QueryString.Get("pub");
DateTime date = DateTime.Parse(Request.QueryString.Get("date"));
int pages = int.Parse(Request.QueryString.Get("pages"));
int sort = int.Parse(Request.QueryString.Get("sort"));
// fixed the statement below to key off of session
if (Session["Record"] == null)
{
reportpath = Server.MapPath("IssuesReport.rpt");
rpt.Load(reportpath);
Session["Record"] = RetrievalProcedures.IssuesReport(date, publication, pages);
}
rpt.SetDataSource((DataTable)Session["Record"]);
CrystalReportViewer1.ReportSource = rpt;
// ....
}
}
`Could it be that sort is not 0? If sort is not 0 and the user is accessing the page for the first time(Session["Record"] has not been set before) he might get the error.
might want to try:
if(sort==0 || Session["Record"] == null)
{
// do your magic
}