Find a root directory of the web application - c#

I'm trying to find a root folder on the server. Nothing works, or works wrong
#{
string [] list = Directory.GetFiles(Directory.GetCurrentDirectory());
foreach(var item in list)
{
<p>#item</p>
}
}
Shows exactly what I don't need
#{
string [] list = Directory.GetFiles("~/");
foreach(var item in list)
{
<p>#item</p>
}
}
Doesn't work
How to solve this?

You can use the following:
Server.MapPath("~");
The ~ is always the root in an ASP.NET application. If you insert it in a Razor view it will be translated to the appropriate path for "external access", e.g. ~/Content/site.css will be converted to /Content/site.css if the site is hosted in the root directory or to e.g. /Page1/Content/site.css if it is hosted at a virtual directory called Page1. Therefor to get the absolute path you need to "map it".
If you do not have access to Server you can also use HostingEnvironment.ApplicationPhysicalPath.

Try
Server.MapPath("~");
or:
HostingEnvironment.ApplicationPhysicalPath

Refer http://msdn.microsoft.com/en-us/library/ms178116.aspx.
For your ease i have modified your code:
string [] list = Directory.GetFiles(Server.MapPath("~"));
StringBuilder sb=new StringBuilder();
foreach (var item in list)
{
sb.Append(item + "\n");
}
Response.Write(sb);
Even though I am giving you answer, I will suggest try to have path which is configurable in web.config or in the database because fixing paths are like hard coding the login ID :). Hope you got me.
Thanks

Related

TFS - Get latest code in a folder

I am using the TFS API to get latest code files, directories, .csproj files, etc. under a TFS-bound folder.
For the same, I use something like the following:
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new
Uri(ConfigurationManager.AppSettings["TFSUrl"]));
tfs.EnsureAuthenticated();
var vsStore = tfs.GetService<VersionControlServer>();
string workingFolder = #"C:\TFS\SolutionFolder";
Workspace wsp = vsStore.TryGetWorkspace(workingFolder);
if (wsp != null)
{
ItemSet items = vsStore.GetItems(workingFolder, VersionSpec.Latest, RecursionType.Full);
string relativePath = workingFolder + #"/";
foreach (Item item in items.Items)
{
string relativePath1 = item.ServerItem.Replace("$/TFS/SolutionFolder", relativePath);
if (item.ItemType == ItemType.Folder)
{
Directory.CreateDirectory(relativePath1);
}
else
{
item.DownloadFile(relativePath1);
}
}
}
Now, I get the items to download and then download happens. However, I want it to be like how VS handles it - if (and only if) there is a change in a file/folder, then only download the same. With this code, I always get 'n' number of files/folders in that folder and then I overwrite the same. Wrong approach, I know. I can, however, modify this code to check for the folder's or file's last change time and then choose to either overwrite it or ignore it. That's an option, albeit a bad one at that.
Now, what I would ideally like is to get ONLY the list of files/folders that actually need to be changed i.e. the incremental change. After that, I can choose to overwrite/ignore each item in that list. So, in the present case, if a new file/folder is created (or one of the existing ones got changed inside $/TFS/SolutionFolder i.e. in the sever), then only I want to pull that item in the list of files/folders to change(and decide what I want to do with it inside C:\TFS\SolutionFolder).
Also, is using one of the overloads of VersionControlServer.QueryHistory() an option? I had something like this:
(latestVersionIdOf $/TFS/SolutionFolder) - (existingVersionIdOf C:\TFS\SolutionFolder) = (Versions that I'd go out and get back from the server, for that folder)
in mind.
Any pointers will be very helpful. Thanks!
Just use Workspace.Get() or overload method (wsp.Get()), it just update updated files.
I don't think we can achieve that. If the files are downloaded to a folder without in source control, there are no versions compared within the folder, even if the folder is in source control, the behavior is just download also no version compare actions. So, it will download all the files ever time and then overwrite the same ones.
In VS, the files are all in TFS source control system, so when we Get Latest Version the changed/added files will be retrieved from TFS. If you want to get the same behavior as VS handles, you can use the tf get command. See Get Command
You can reference this article to use the tf get command :
get-latest-version-of-specific-files-with-tfs-power-tools
Update :-
var tfs = TfsTeamProjectCollectionFactory.GetTeamProjectCollection(new Uri(ConfigurationManager.AppSettings["TFSUrl"]));
tfs.EnsureAuthenticated();
var vsStore = tfs.GetService<VersionControlServer>();
string workingFolder = ConfigurationManager.AppSettings["LocalPathToFolder"]; // C:\TFS\SolutionFolder
string tfsPathToFolder = ConfigurationManager.AppSettings["TFSPathToFolder"]; // $/TFS/SolutionFolder
Workspace wsp = vsStore.GetWorkspace(workingFolder);
if (wsp != null)
{
ItemSpec[] specs = { new ItemSpec(tfsPathToFolder, RecursionType.Full) };
ExtendedItem[][] extendedItems = wsp.GetExtendedItems(specs, DeletedState.NonDeleted, ItemType.Any);
ExtendedItem[] extendedItem = extendedItems[0];
var itemsToDownload = extendedItem.Where(itemToDownload => itemToDownload.IsLatest == false);
foreach (var itemToDownload in itemsToDownload)
{
try
{
switch (itemToDownload.ItemType)
{
case ItemType.File:
if (itemToDownload.LocalItem != null)
{
vsStore.DownloadFile(itemToDownload.SourceServerItem, itemToDownload.LocalItem);
}
else
{
string localItemPath = itemToDownload.SourceServerItem.Replace(tfsPathToFolder,
workingFolder);
vsStore.DownloadFile(itemToDownload.SourceServerItem, localItemPath);
}
break;
case ItemType.Folder:
string folderName = itemToDownload.SourceServerItem.Replace(tfsPathToFolder, workingFolder);
if ((!string.IsNullOrEmpty(folderName)) && (!Directory.Exists(folderName)))
{
Directory.CreateDirectory(folderName);
}
break;
}
}
catch (Exception e)
{
File.AppendAllText(#"C:\TempLocation\GetLatestExceptions.txt", e.Message);
}
}
}
This code works well, except:
a. Whenever it downloads the latest copy of, let's say a file, it 'checks it out' in TFS :(
b. For some items, it throws errors like 'Item $/TFS/SolutionFolder/FolderX/abc.cs was not found in source control at version T.' - I have to find out what the exact cause of this issue is, though.
Any ideas on how to get around these two issues or any other problems you see with this code? Thanks!

Web.GetFileByServerRelativeUrl throws "Value does not fall within expected range"

I have a SP Online site where I store Documents, I have no issues adding/retrieving documents but in the delete flow I get an error during retrieval of a File object.
public static void DeleteDocument()
{
using (ClientContext ctx = ClientContextFactory.Create("https://my-sponline-site.sharepoint.com/sites/documentsite"))
{
Web web = ctx.Web;
ctx.Load(web);
ctx.ExecuteQuery();
string relativeUrl = "/Documents/images.jpg";
File file = web.GetFileByServerRelativeUrl(relativeUrl);
ctx.Load(file);
file.DeleteObject();
ctx.ExecuteQuery();
}
}
Full Url of the file is "https://my-sponline-site.sharepoint.com/sites/documentsite/Documents/images.jpg" (No more accessible 2016-12-07)
When I execute this, I get a ServerException :
Value does not fall within the expected range.
The Context is working fine as I'm able to add/retrieve items from the library and the context user is administrator.
I tried adding the web url to the relativeUrl so it would be "/documentsite/Documents/images.jpg" but I get the same error.
I can't seem to figure this out, any suggestions?
Thanks
string relativeUrl = "/sites/documentsite/Documents/images.jpg";

TreeView Where Root And All Nodes Thereafter Are Derived From First Sub-Folder - How To Specify Correct Path?

I am working on a simple, portable, single-form, application where the *.exe and a folder entitled UserGeneratedContent reside in the same directory. On my form I have a treeview that I want to populate with nodes corresponding to all sub-folders (if any exist) of UserGeneratedContent. The code I've pasted in below works almost the way I want it to, but it populates the treeview with UserGeneratedContent as the root node and in turn treats the sub-folders it finds as child nodes, etc.
string folder = #"UserGeneratedContent";
FolderHierachy.Nodes.Add(GetDirectoryNodes(folder));
private static TreeNode GetDirectoryNodes(string path)
{
var node = new TreeNode(Path.GetFileName(path));
var subDirs = Directory.GetDirectories(path).Select(d => GetDirectoryNodes(d)).ToArray();
node.Nodes.AddRange(subDirs);
return node;
}
At this stage I have tried just about every combination of #"UserGeneratedContent" I can think of - adding back-slashes etc, in an attempt to access the sub-folders but I'm having no luck. I know its probably something simple, but I'm stuck - what is the correct syntax to ensure that the method above looks into UserGeneratedContent to get the sub-folders?
Furthermore, I want the treeview control to allow the user to create, rename, and delete folders in any hierachy of their choice so I'm wondering what would be considered best practices in this regard?
Edit \ Update # 1 - 12.2.2012:
After a lot more trial and error I have given up on the code above - no matter what I tried I couldn't get it to work for some reason. Luckily the code below is working perfectly for me :-)
DirectoryInfo dirInfo = new DirectoryInfo(#"UserGeneratedContent");
DirectoryInfo[] subDirs = dirInfo.GetDirectories();
string pathToSubFolders = Path.Combine(#"UserGeneratedContent", subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
private void PopulateTreeView(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach(var directory in directoryInfo.GetDirectories())
{
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
}
return directory;
}
I need to add some error handling code to it to allow for there being no sub-folders under #"UserGeneratedContent" - as it is subDirs[0].ToString() throws an IndexOutOfRangeException if no sub-folders exist and I'm not exactly sure how to go about it so I'd be grateful for some pointers.
Edit \ Update # 2 - 12.2.2012:
For my error checking I've used a try-catch block as below:
try
{
string pathToSubFolders = Path.Combine(dirInfo.ToString(), subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
}
catch (IndexOutOfRangeException)
{
//Do Something Here
}
The above code works, but can anyone tell me if I have gone about this the right way?
Thanks for reading.
if you haven't found an other solution yet, a simple way would be:
if(subDirs.Lenght != 0) // or > 0
{
string pathToSubFolders = Path.Combine(dirInfo.ToString(), subDirs[0].ToString());
PopulateTreeView(treeView1, pathToSubFolders);
}
else
{
//Do Something Here
}

Recursive delete of files and directories in C#

How to delete a given directory recursively in C# ? A directory containing files.
Should the System.IO.Directory.Delete with the second parameter true do the trick?
EDIT:
So, I actually did answer my own question, although the answers here were a little more clarifying. The reason for me asking this in the first place was that the code that has exactly that invocation of Delete (2nd param set to true) was not doing what it was supposed to be doing. As it turned out the cause of that was that there was a file somewhere down in the the directory hierarchy with RO attribute set, and the Polish version of Windows XP was throwing a really strange message for that.
The only solution that worked for me if the subdirectories also contains files is by using a recursive function:
public static void RecursiveDelete(DirectoryInfo baseDir)
{
if (!baseDir.Exists)
return;
foreach (var dir in baseDir.EnumerateDirectories())
{
RecursiveDelete(dir);
}
baseDir.Delete(true);
}
It appears that Directory.Delete(dir, true) only delete files of the current directory, and subdirectories if they are empty.
Hope it helps someone.
btw, example: RecursiveDelete( new DirectoryInfo(#"C:\my_dir") );
Yup, that's the point of that parameter. Did you try it and have any problems? (I've just double-checked, and it works fine for me.)
If you get UnauthorizedAccessException .
You can use modified of RecursiveDelete from Jone Polvora. Thank you for Idea. I will use it.
public static void RecursiveDelete(DirectoryInfo baseDir)
{
if (!baseDir.Exists)
return;
foreach (var dir in baseDir.EnumerateDirectories())
{
RecursiveDelete(dir);
}
var files = baseDir.GetFiles();
foreach (var file in files)
{
file.IsReadOnly = false;
file.Delete();
}
baseDir.Delete();
}
Recursive works for both files and folders (oddly, I thought it didn't work for files; my bad...):
// create some nested folders...
Directory.CreateDirectory(#"c:\foo");
Directory.CreateDirectory(#"c:\foo\bar");
// ...with files...
File.WriteAllText(#"c:\foo\blap.txt", "blup");
File.WriteAllText(#"c:\foo\bar\blip.txt", "blop");
// ...and delete them
Directory.Delete(#"c:\foo", true); // fine
Modified solution from #StayOnTarget, so that root dir is not getting removed:
public static void RecursiveDelete(DirectoryInfo baseDir, bool isRootDir)
{
if (!baseDir.Exists)
return;
foreach (var dir in baseDir.EnumerateDirectories()) RecursiveDelete(dir, false);
foreach (var file in baseDir.GetFiles())
{
file.IsReadOnly = false;
file.Delete();
}
if (!isRootDir) baseDir.Delete();
}
Why do not use?
Directory.Delete(directoryPath, true);
https://msdn.microsoft.com/en-us/library/fxeahc5f(v=vs.110).aspx

Using "~" in a path resolves as C:\

I'm trying to implement a server control that frobs a couple of files inside the web directory of an ASP.NET site. I'm using VS Web Dev Express 2008 as my IDE. When I call HttpContext.Current.Request.ApplicationPath to get a path to the web root so I can find those files, it returns C:. What the heck?
Absolute paths work just fine, but I'd like to be able to feed the server control a relative directory and just let it do it's thing. What have I done wrong?
public String Target
{
get { return _target; }
set
{
if (value.StartsWith("~"))
{
// WTF? Gives me C:\? Why?
_target = HttpContext.Current.Request.ApplicationPath +
value.Substring(1);
}
else
{
_target = value;
}
}
}
private String _target;
protected override void Render(HtmlTextWriter writer)
{
HtmlControl wrapper = new HtmlGenericControl("div");
int fileCount = 0;
try
{
DirectoryInfo dir = new DirectoryInfo(_target);
foreach (FileInfo f in dir.GetFiles())
{
fileCount++;
a = new HtmlAnchor();
a.Attributes.Add("href", f.FullName);
a.InnerHtml = f.Name;
wrapper.Controls.Add(a);
}
}
catch (IOException e)
{
throw e;
}
Controls.Add(wrapper);
base.Render(writer);
}
This might be because it's using the development web server, which can just serve files from any directory on your hard drive. It doesn't have any specific root. Can you run your project under IIS (assuming your version of windows supports it), and see if you get the same results?
To get rid of the problem completely you could just hard code the path you want to look at in your web.config and go around any problems with what Request.ApplicationPath is returning.
[EDIT]
Just found out you can use
HTTPContext.Current.Request.ServerVariables("APPL_PHYSICAL_PATH")
to return the path of your application, on the hard disk. I'm pretty sure that's what you are looking for. If that's not right, check out all the other ServerVariables to see if you can get what you are looking for.
How about this:
Server.MapPath(ResolveUrl("~/filename"))
There's also information on a page TLAnews.com titled, Understanding Paths in ASP.NET.
The ADME Developer's Kit may be what you need if you are trying to get the directory at design time.

Categories

Resources