I have a utility to rename a file in a specified directory using a certain condition. Running the code using a console application works well and the file is renamed appropriately. However, when I attempt the same in a web application the file is not getting renamed. I am using VS2017 Development Server for the web application debugging.
What am I missing?
Using the console application code as below the file successfully gets renamed :
Rename method:
public static string AddSuffix(string filename, string suffix)
{
string fDir = Path.GetDirectoryName(filename);
string fName = Path.GetFileNameWithoutExtension(filename);
string fExt = Path.GetExtension(filename);
string renamedFilePath = Path.Combine(fDir, String.Concat(fName, suffix, fExt));
return renamedFilePath;
}
Usage in main program:
static void Main(string[] args)
{
string batchperiod = "_70_";
string realPath = #"C:\Users\myuser\source\repos\Solution\Project\BatchIn";
IEnumerable<string> fileList = Directory.EnumerateFiles(realPath);
var CurrentBatchName = (from file in fileList
let fileName = Path.GetFileName(file)
where fileName.Contains(batchperiod)
select fileName).FirstOrDefault();
string absolutePath = (#"C:\Users\myuser\source\repos\Solution\Project\BatchIn\" + CurrentBatchName);
string newPath = Helpers.AddSuffix(absolutePath, String.Format("({0})", Helpers.parameters.IsProcessed));
System.IO.FileInfo fi = new System.IO.FileInfo(absolutePath);
if (fi.Exists)
{
fi.MoveTo(newPath);
}
}
With this code the file is successfully renamed from
GL_Export_70_201907081058.xml
to
GL_Export_70_201907081058(P).xml
The only difference using web application is that the absolutePath is stored in a Session variable .. its derived from a preceding operation/ActionResult :
var absolutePath = (#"C:\Users\myuser\source\repos\Solution\Project\BatchIn\" + CurrentBatchName);
files.FileName = CurrentBatchName;
Session["AbsoluteBatchPath"] = absolutePath;
and later invoked in another ActionResult as :
var sourceFile = Convert.ToString(Session["AbsoluteBatchPath"]);
string newPath = AddSuffix(sourceFile, String.Format("({0})", parameters.IsProcessed));
System.IO.FileInfo fi = new System.IO.FileInfo(sourceFile);
if (fi.Exists)
{
// Move file with a new name. Hence renamed.
fi.MoveTo(newPath);
}
What am I missing?
I do suspect there are some permissions I may need to configure when attempting the rename using the Visual Studio Development Server.
Your code see perfect there is no missing ,debug and check whether in MVC your code entered fi.exist if condition..
Please confirmed the same
Related
I have to create a directory and then a text file inside this directory with name come from parameter. E.g. _year is a parameter and I tried as:
var _root = "C:\\Users\\~\\DirichletProcessClustering\\Results";
var _clusterFilename = _year.ToString() + "cluster.txt";
var _path = Path.Combine(_root, _year.ToString(), _clusterFilename);
if(!Directory.Exists(_path))
{
Directory.CreateDirectory(_path);
}
// output topk file
TextWriter _twClus = File.CreateText(_path);
foreach (// loop )
{
_twClus.WriteLine("Cluster");
//... rest of the implementation...
}
This code is creating a folder named 2005 at specified path and then inside this folder, there is another folder named 2005cluster.txt while I want to create a text file named 2005cluster.txt inside folder 2005.
Where I am getting wrong in creating correct folder and file names?
An UnauthorizedAccessException generated at undermentioned line of
code i.e. access is denied. Why is this happening?
TextWriter _twClus = File.CreateText(_path);
Try this so that your path has a slash before the file name:
var _root = "C:\\Users\\~\\DirichletProcessClustering\\Results\\";
As you are defining fileName separately, You could try this:
var _root = "C:\\Users\\~\\DirichletProcessClustering\\Results";
var _clusterFilename = _year.ToString() + "cluster.txt";
var _path = Path.Combine(_root, _year.ToString());
if(!Directory.Exists(_path))
{
Directory.CreateDirectory(_path);
}
// output topk file
TextWriter _twClus = File.CreateText(Path.Combine(_path, _clusterFilename));
foreach (// loop )
{
_twClus.WriteLine("Cluster");
//... rest of the implementation...
}
Remove the file name from your path as:
var _path = Path.Combine(_root, _year.ToString());
For defining the filename you have to modify this line of code as:
TextWriter _twClus = File.CreateText(Path.Combine(_path, _clusterFilename));
My program saves user's input to a txt file on it's current location
TextWriter ts = new StreamWriter("url.txt");
ts.WriteLine(textBox2.Text.ToString());
ts.Close();
It reads that when application starts
if (File.Exists("url.txt")) {
TextReader tr = new StreamReader("url.txt");
readUrl = tr.ReadLine().ToString();
textBox2.Text = readUrl;
tr.Close();
}
I add this program to Windows startup with these code
using (RegistryKey key = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true)) {
key.SetValue("House Party Protocol", "\"" + Application.ExecutablePath + "\"");
}
I published it with ClickOnce and installed it to my computer. It starts at windows startup bu doesn't read txt file. When I open it manually it works. I think ClickOnce installation path and windows startup path are different. How should I change my startup code to avoid this
You could try to use a specific directory. For example, you could save the url.txt file to LocalApplicationData (the directory for application-specific data that is used by the current, non-roaming user).
static void Main(string[] args)
{
string inputText = string.Empty;
//string directory = Environment.CurrentDirectory;
string directory = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
string path = Path.Combine(directory, "url.txt");
if (File.Exists(path))
{
TextReader tr = new StreamReader(path);
string readUrl = tr.ReadLine().ToString();
inputText = readUrl;
tr.Close();
}
string text = "abc";
TextWriter ts = new StreamWriter(path);
ts.WriteLine(text);
ts.Close();
}
If you really want to use the directory where the application is running then you could try to use Environment.CurrentDirectory (commented-out in the sample code above). This might give you the same error you had before (when using relative path) but it might help you troubleshoot the issue by showing what directory it's trying to use.
Here's a list of other special folders:
Environment.SpecialFolder
I have this code in my Web API app to write to a CSV file:
private void SaveToCSV(InventoryItem invItem, string dbContext)
{
string csvHeader = "id,pack_size,description,vendor_id,department,subdepartment,unit_cost,unit_list,open_qty,UPC_code,UPC_pack_size,vendor_item,crv_id";
int dbContextAsInt = 0;
int.TryParse(dbContext, out dbContextAsInt);
string csvFilename = string.Format("Platypus{0}.csv", dbContextAsInt);
string csv = string.Format("{0},{1},{2},{3},{4},{5},{6},{7},{8},{9},{10},{11},{12}", invItem.ID,
invItem.pksize, invItem.Description, invItem.vendor_id, invItem.dept, invItem.subdept, invItem.UnitCost,
invItem.UnitList, invItem.OpenQty, invItem.UPC, invItem.upc_pack_size, invItem.vendor_item, invItem.crv_id);
string existingContents;
using (StreamReader sr = new StreamReader(csvFilename))
{
existingContents = sr.ReadToEnd();
}
using (StreamWriter writetext = File.AppendText(csvFilename))
{
if (!existingContents.Contains(csvHeader))
{
writetext.WriteLine(csvHeader);
}
writetext.WriteLine(csv);
}
}
On the dev machine, the csv file is saved to "C:\Program Files (x86)\IIS Express" by default. In preparation for when it is deployed to its final resting/working place, what do I need to do to get the file to save, e.g., to the server's "Platypi" folder - anything special? Do I have to specifically set certain folder persimmons to allow writing to "Platypi."
Is it simply a matter of changing this line:
string csvFilename = string.Format("Platypus{0}.csv", dbContextAsInt);
...to this:
string csvFilename = string.Format(#"\Platypi\Platypus{0}.csv", dbContextAsInt);
?
In the case of the IIS folder the application has rights to write in there. I suggest to write files to the App_Data folder.
When you want to save files outside the IIS application folder you have to give the service account of the IIS application pool (I think it by default is NETWORKSERVICE) the appropriate rights on that folder.
As requested by B. Clay Shannon my implementation:
string fullSavePath = HttpContext.Current.Server.MapPath(string.Format("~/App_Data/Platypus{0}.csv", dbContextAsInt));
Thanks to Patrick Hofman; this is the exact code I am using, and it is saved to the project's App_Data folder:
public static string appDataFolder = HttpContext.Current.Server.MapPath("~/App_Data/");
. . .
string csvFilename = string.Format("Platypus{0}.csv", dbContextAsInt);
string fullSavePath = string.Format("{0}{1}", appDataFolder, csvFilename);
I have this file: C:\Documents and Settings\extryasam\My Documents\Visual Studio 2010\Projects\FCR\WebApplication4\config\roles.txt and I want to import it into my C# application. If I insert the full path it's ok, but I want to do something similar to what we do with websites, and that is "\config\roles.txt"
However with the below code, this is not working.
This is my code:
public string authenticate()
{
WindowsIdentity curIdentity = WindowsIdentity.GetCurrent();
WindowsPrincipal myPrincipal = new WindowsPrincipal(curIdentity);
//String role = "NT\\Internet Users";
//string filePath = Server.MapPath("config/roles.txt");
//string filePath = (#"~/WebApplication4/config/roles.txt");
//string filePath = Path.GetDirectoryName(#"\config\roles.txt");
string filePath = Path.GetPathRoot(#"/config/roles.txt");
string line;
string role = "";
if (File.Exists(filePath))
{
StreamReader file = null;
try
{
file = new StreamReader(filePath);
while ((line = file.ReadLine()) != null)
{
role = line;
}
}
finally
{
if (file != null)
{
file.Close();
}
}
}
if (!myPrincipal.IsInRole(#role))
{
return "401.aspx";
}
else
{
return "#";
}
}
In ASP.NET, you can use ~/config/roles.txt - in combination with Server.MapPath(), you can get the full path.
[...] ASP.NET includes the Web application root operator (~), which
you can use when specifying a path in server controls. ASP.NET
resolves the ~ operator to the root of the current application. You
can use the ~ operator in conjunction with folders to specify a path
that is based on the current root.
(see http://msdn.microsoft.com/en-us/library/ms178116.aspx)
So you could try the following:
string filePath = System.Web.HttpContext.Current.Server.MapPath("~/config/roles.txt");
You can use Server.MapPath to map the specified relative or virtual path to the corresponding physical directory on the server.
Since you are working locally you can use absolute path to that file and it's will works.
But what about situation when web application that contains roles.txt file will be deployed on some web server and user will try to access this file from another machine?
You can use the approach below to access file hosted on a web server from a Windows application:
using (var stream = new WebClient().OpenRead("your_web_application_root_url/configs/roles.txt"))
using (var reader = new StreamReader(stream))
{
Console.WriteLine(reader.ReadToEnd());
}
Be warned that share security settings over network is not quite good idea.
You should select your file and press F4, and choose copy to output directory. Then you will be able to work with it
You could try embedding the file as a resource in your project. Something like this: How to embed a text file in a .NET assembly?
I have some xml files, which are used in my application. They are stored in the same folder with application , in subfolder DATA: "C:\MyProject\DATA\".
To get the DATA folder path i use this code :
static public string GetDataFolderPath()
{
string s = System.IO.Directory.GetCurrentDirectory().Replace(#"\bin\Debug", "");
int i = s.LastIndexOf(#"\");
s = s.Substring(0, i);
i = s.LastIndexOf(#"\");
s= s.Substring(0, i);
return s + #"\Data\";
}
So when i want to deploy my application, i create a setup project, and add the DATA folder to Application folder. But after i install the program f.e. "C:\Project"(DATA folder- "C:\Project\DATA" i got the error: "folder C:\DATA is not found".
What i need to change to make things working after deployment. Why it looks for the DATA folder on 1 level higher?
Try this, it might work better:
public static string GetDataFolderPath()
{
#if DEBUG
// This will be executed in Debug build
string path = Directory.GetCurrentDirectory().Replace(#"\bin\Debug", "");
#else
// This will be executed in Release build
string path = Directory.GetCurrentDirectory();
#endif
return Path.Combine(path, "Data");
}
Or just this if you want one for both Debug and Release builds:
public static string GetDataFolderPath()
{
string path = Directory.GetCurrentDirectory().Replace(#"\bin\Debug", "");
return Path.Combine(path, "Data");
}
You have to add using System.IO; for this to work.
Maybe current directory (during launching your program) is not the same one that assemblies lie?
try:
//get the full location of the assembly
string fullPath = System.Reflection.Assembly.GetAssembly(typeof(<your class name>)).Location;
//get the folder that's in
string theDirectory = Path.GetDirectoryName( fullPath );
or
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path = Uri.UnescapeDataString(uri.Path);
return Path.GetDirectoryName(path);