Link to home
Start Free TrialLog in
Avatar of rickhill11
rickhill11

asked on

VisualStudio is adding characters to filename rendering it unusable

I'm working in Visual Studio using razor.  I have a file, "AllCodes.txt."  I want to open that file, and probably read its contents into an array.  My problem is that no matter what I do whether attempting to open the file using a string literal, or a string variable, the filename is altered by something in the code providing a leading slash.

            string FilePath = @"c:\AllCodes.txt";
            string[] lines = System.IO.File.ReadAllLines(FilePath);
           
For instance, the above tries to open /c:/AllCodes.txt"

What am I doing wrong?

Thanks in advance!
Avatar of it_saige
it_saige
Flag of United States of America image

Could you expand on what you mean by "rendering it useless".  Are you getting an error?  If so what error are you getting?

-saige-
Avatar of rickhill11
rickhill11

ASKER



It complains that the filename isn't valid.

I get an unhandled exception error in the browser, and the following debug output

      Unhandled exception rendering component: Could not find a part of the path "/c:/AllCodes.txt".
System.IO.DirectoryNotFoundException: Could not find a part of the path "/c:/AllCodes.txt".

I've tried all sorts of naming conventions, moving directories, adding to Resources, ... that IMHO should work, but no matter what I do, I get a leading "/", and the above message.

Thanks
You are getting this error because of the way webpages and web server engines work.  Web server engines use what is known as relative paths to serve and/or locate files which are to be processed.  The extra character is there because the web server is trying to locate the file relative to your project or wwwroot location.

Try putting the file in the wwwroot directory or a separate directory in the project.  Then set the file properties so that the Copy to Output Directory option is set to either Copy always or Copy if newer and that the Build Action is set to Content.  This will place the file in the same folder as the compiled libraries (usually the bin folder); e.g. -
With the above, my ReadAllLines method looks like this:User generated image
And does open the file:User generated image
-saige-
Thanks for the help, but no joy.  Maybe I don't understand what you meant.

I already had a copy of the file in the Resources Dir, changed the property to copy if newer

Then tried to open within the program with
   @"AllCodes.txt"
   @".\Resources\AllCodes.txt"
    @".\AllCodes.txt". etc.  All fail.

Still  getting the same error.

I just tried what I believe to be essentially what you suggested:
            string FilePath = @"Resources\AllCodes.txt";
            string[] lines = System.IO.File.ReadAllLines(FilePath);

Debug output

Could not find a part of the path "/Resources/AllCodes.txt"
Also tried, just for giggles:

 string[] lines = System.IO.File.ReadAllLines(@"Resources\AllCodes.txt");

Same failure!
My guess is that your project is set up for .NET Core instead of one of the Windows-only .NET frameworks. If that's the case and you don't truly need it to be cross-platform, then just switch the project targeting to use the normal .NET framework.
After you build the solution, did you check the bin folder to see if the resources folder was there and that it contained your file?

-saige-
As I've mentioned, I'm a old C, C++ programmer with somewhat a somewhat stale skillset even in those languages.  

My intent is that anyone, without logging in, my simply use their favorite browser navigate to the site, enter some data, and get/print the output.
it_saige:

Hate to sound obtuse, but I don't see a bin folder.  I do have AllCodes.txt in a Resource directory, but I'm pretty certain that I manually put it there myself.
That's fine. Do you know how to check the target framework in the project properties and change it?
gr8gonzo,

Sorry, not a clue!


So in Visual Studio, you have the Solution Explorer box where you can see the tree containing your solution, which contains your project, and your project contains your files and folders. If you right-click on the project and go to properties, you should see a screen open up with various tabs (the layout looks a little different depending on which version of Visual Studio you're using).

The first/main tab should contain fields that dictate the name of your project and also should contain a drop-down indicating the target framework.

That target framework basically means "what's the minimum framework version required for someone to run this application that I'm building?"

The different frameworks are sort of like the runtime libraries in VC++ projects. Your final executable was smaller because it was just making use of some common functions that were stored in that runtime library. The idea is that Microsoft gets everyone to install the  .NET framework on their machines as a normal part of Windows and keep it updated. Then, when you build a fancy new .NET application and distribute it, the executable is ridiculously small because it's just making use of the hundreds of megabytes of libraries (the .NET framework) that are already installed on everyone's machines.

Now, MS came out with .NET Core as a way to write some code that could run on other platforms. However, Windows is really the only major platform that uses backslashes and drive letters for its paths. UNIX and Linux and all of its variants, including the underlying system for Macs, uses filesystems that use forward slashes, like:
/partition/path/to/file.txt, where the initial slash indicates the root of everything in the filesystem, so it is basically an absolute path vs. a relative path.

While I don't personally write .NET Core apps, my understanding is that it tries to utilize forward slashes in its paths because they are the more common syntax and semi-compatible with Windows. In some of the Linux subsystems that can be installed on Windows, like bash for Windows, the absolute pathing looks like: /x/path/to/file.txt 
...for X:\path\to\file.txt

So if you are writing this for your own server that will always be Windows, then in that target framework drop-down, change it to .NET Framework 4.7 or later (whichever version of the framework is installed on your server).

Visual Studio should give you a prompt warning about the possibility of something breaking (more common when going -to- .NET Core because it has less functionality than the full .NET Framework), which you can accept. Then it'll reload your project but this time your code will be building against the full framework that is meant specifically for Windows and uses the paths you're used to.
gr8gonzo,

Found the Taget Framework .Server is .NET Core 3.1, output type Console Application
                                               .Client is .NET Standard 2.1 output type Console Application 

Is this what you mean.  If sop, what should I change it/them to, and what are the implications when I try to deploy to the web?
Yes, change the server target framework to .NET Framework.

Microsoft has some documentation about the differences here:
https://docs.microsoft.com/en-us/archive/msdn-magazine/2017/september/net-standard-demystifying-net-core-and-net-standard
gr8gonzo,

Thanks for the information.  I'm a long-time unix guy, so I totally get the absolute path vs relative path thing.  My problem is "why is Studio adding junk to a pathname?"  AND if I target Windows, what happens when I deploy to GoDaddy or another web site.
You can't simply change from a .NET Core/Standard to .NET Framework.  You would either have to modify the project file via a text editor or create a new Project targeting .NET Framework.

-saige-
gr8gonzo,

Changed the target framework on the Server to .NET 5.0 from .NetCore 3.1

Rebuilt solution,

still got    Unhandled exception rendering component: Could not find a part of the path "/Resources/AllCodes.txt".
As far as implications go, if this is only for your own purposes, then the main difference is that your code will not worry about trying to be cross-platform-compatible and you'll gain access to a lot more functionality.

Using .NET Core or .NET Standard is only useful if you're building something that you plan on distributing to others so they can run the same services on their servers.
Saige,

where would I make that text edit?

Rick
GoDaddy (and others) has/have MS Web Servers, you just have to ensure that you request that type.  However, more and more you find the people are using virtualization services where Docker is more prevalent via some sort of DevOps automation pipeline where you can trigger builds and deployments seamlessly; e.g. Azure DevOps.

-saige-
Maybe I am dating myself here.  I just have trouble seeing why opening a simple text file, and reading in a few hundred lines of data should be so complicated.
It's not, even with .NET Core it's as simple as shown above.  My solution/project is a .NET Core solution.  Without seeing your configuration we are just grasping at straws.  If you have TeamViewer I'd be willing to setup a quick session to see if we can get to the bottom of the problem and possible provide any additional answers to questions you might have.  If this is viable, send me a private message with your team viewer session information.

-saige-
So I wouldn't go straight to .NET 5.0 if you're planning on deploying to other hosts. The .NET 5.0 framework is pretty new and there's always a chance that a 3rd party host may not have it yet. I would stick with 4.7 or 4.8.

Next, the error you have now is indicating the code is probably set to a relative path starting at the root of the current drive. I would suggest trying out the full path (starting with drive letter), just to test to make sure switching the framework allowed that scenario to occur.

If the full path works on the full .NET framework, then the next thing would be to use some of the standard methods to determine the current path / web root and then build the final path from there.

And for what it's worth, yes .NET Core can do this and it's just a matter of the right syntax but if you don't need the portability of .NET Core, there's no reason to handicap yourself and put other future potential hurdles in your path.
Also, be careful with TeamViewer. If you use it, make sure you have two-factor authentication on. It's a popular target for malicious hackers (I discovered this the hard way several years ago).
Assuming the web server is Windows IIS, did you put the text file in
c:\Inetpub\wwwroot\Resource\AllCodes.txt

These links might help:
https://docs.microsoft.com/en-us/aspnet/web-pages/overview/data/working-with-files
http://www.beansoftware.com/ASP.NET-Tutorials/using-server.mappath.aspx
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Nice work figuring that out!

Ahhh.  Important detail. :)
Many thinks to everyone for your help, especially IT_Saige who went way above and beyond.  For now, the problem seems to have been solved, so now I am on to finding other problems :-).