Getting the link for a virtual directory - c#

I have written a server in C# for a JS client.
The Solution consists restApi BL and DAL.
The BL creates links for images stored on a virtual directory, on the server.
The JS and the server code, are stored in the same directory.
When I build the string of the link I use this line of code:
string keyImageName = Settings.Default.ServerUrl +
Settings.Default.KeyImagesFolder + relatedFinding.KeyImagePath;`
where KeyImageFolder is a virtual directory.
It works fine, but my problem is that the website has multiple Amazon instances, one for each geographical zone , so every time I deploy, I need to change the ip in the settings.it's annoying.
Is there a way to get the virtual directory's url, specifically for each machine?
if the JS is installed on the same machine as the server, does it really need a full path?
Many thanks

First, you'll need to get the physical path for the file or directory that you want to generate a url for. This can be done within a Page object using Request.ApplicationPath.
Next, this path can be converted to a url path using the Server.MapPath function. This will take into account if there are more than one websites tied to the same path in IIS.
var physicalPath = Path.Combine(Request.ApplicationPath, Settings.Default.KeyImagesFolder, relatedFinding.KeyImagePath);
var resourceUrl = Server.MapPath(physicalPath);

Related

Visual Studio 2022 C# ASP.NET Webforms with service reference text files not found on server (HTTP Error 404.0)

I am currently trying to create a web service application using Visual Studio 2022 ASP.NET Webforms application with a service reference. The goal is to take in information and store it as a text file on the local machine within the project folder so it is accessible by the web service on my local server.
I have successfully created the text files and can access them on my local machine, but when I navigate to the text file on my local server tree I get an HTTP Error 404.0 which is shown below. I need any user who accesses my server to be able to access the saved text files. I have tried to change security privileges on the folder and in my web.config file, but have not had any luck. I would appreciate any suggestions someone may have.
Here is my code for where I save the information as a text file.
// Randomly generate string for text file name
var chars = "abcdefghijklmnopqrstuvwxyz0123456789";
var textFile = new char[4];
var random = new Random();
for (int i = 0; i < textFile.Length; i++)
{
textFile[i] = chars[random.Next(chars.Length)];
}
eventFile = "\\";
eventFile += new String(textFile);
eventFile += ".txt";
folderPath = Server.MapPath("~/Events");
File.WriteAllText(folderPath + eventFile, fullEventDetails);
Both my URL and local file path are the following:
URL https://localhost:44399/sx1l.txt
Path Name \\Mac\Home\Desktop\Homework3\Homework3\sx1l.txt
Ok, so you have to keep in mind how file mapping works with IIS.
Your code behind:
that is plane jane .net code. For the most part, any code, any file operations using full qualified windows path names. It like writing desktop software. For the most part, that means code behind can grab/use/look at any file on your computer.
However, in practice when you use a full blown web server running ISS (which you not really doing during development with VS and IIS express)? Often, for reasons of security, then ONLY files in the wwwroot folder is given permissions to the web server.
However, you working on your development computer - you are in a effect a super user, and you (and more important) your code thus as a result can read/write and grab and use ANY file on your computer.
So, keep above VERY clear in your mind:
Code behind = plane jane windows file operations.
Then we have requests from the web side of things (from a web page, or a URL you type into the web browser.
In that case, files are ONLY EVER mapped to the root of your project, and then sub folders.
So, you could up-load a file, and then with code behind save the file to ANY location on your computer.
However, web based file (urls) are ONLY ever mapped though the web site.
So, in effect, you have to consider your VS web project the root folder. And if you published to a real web server, that would be the case.
So, if you have the project folder, you can add a sub folder to that project.
Say, we add a folder called UpLoadFiles. (and make sure you use VS to add that folder). So we right click on the project and choose add->
So, you right click on the base project and add, like this:
So, that will simple create a sub folder in your project, you see it like this:
So, the folder MUST be in the root, or at the very least start in the root or base folder your project is.
So, for above, then with UpLoadFiles, then any WEB based path name (url) will be this:
https://localhost:44399/UpLoadFiles/sx1l.txt
(assuming we put the file in folder UpLoadFiles).
But, if you want to write code to touch/use/read/save and work with that file?
You need to translate the above url into that plane jane windows path name. (for ANY code behind).
So, if I want to in code read that file name?
Then I would use Server.MapPath() to translate this url.
say somthing like this:
string strFileName = "sx1l.txt";
string strFolderName = "UpLoadFiles"
string strInternaleFileName = server.MapPath(#"~/" + strFolderNme + #"/" + sx1l.txt";
// ok, so now we have the plane jane windows file name. It will resolve to something like say this:
C:\Users\AlbertKallal\source\repos\MyCalendar\UpLoadFiles\sx1l.txt
I mean I don't really care, but that web server code could be running on some server and that path name could be even more ugly then above - but me the developer don't care.
but, from a web browser and web server point of view (URL), then above would look like this:
https://localhost:44392/UpLoadFiles/sx1l.txt
And in markup, I could drop in say a hyper link such as:
UpLoadFiles/sx1l.txt
So, keep CRYSTAL clear in your mind with working with path names.
Web based URL, or markup = relative path name, ONLY root or sub folders allowed
code behind: ALWAYS will use a plane jane full windows standard file and path.
But, what about the case where you have big huge network attached storage computer - say will a boatload of PDF safety documents, or a catalog of part pictures?
Well, then you can adopt and use what we call a "virtual" folder. They are pain to setup in IIS express, but REALLY easy to setup if you using IIS to setup and run the final server where you going to publish the site to.
Suffice to say, a virtual folder allows you to map a EXTERNAL folder into the root path name of your side.
So, you might have say a big server with a large number of PDF docuemnts,
say on
\\corporate-server1\PDF\Documents
so, in IIS, you can add the above path name, say as a folder called PDF.
Say like this:
So, WHEN you do the above, then the folder will appear like any plane jane folder in the root of the project, but the file paths can and will be on a complete different location OUTSIDE of the wwwroot folder for the web site.
So, now that we have the above all clear?
\\Mac\Home\Desktop\Homework3\Homework3\sx1l.txt
But, your code has this:
folderPath = Server.MapPath("~/Events");
File.WriteAllText(folderPath + eventFile, fullEventDetails);
(you missing the trailing "/" in above, you need this:
File.WriteAllText(folderPath + #"/" + eventFile, fullEventDetails);
So, that means the url for the text file will then be:
https://localhost:44399/Events/sx1l.txt
And if you using Visual Studio to add files to that folder (add->existing items), then MAKE SURE you Build->rebuild all (else the file will not be included in the debug run + launching of IIS express.
So, given that you saving into a folder called Events (as sub folder of wwwroot, or your base folder for hte web site, then the above is the url you should use, but your code always was missing that "/" between folder and file name.

c# absolute path shared drive

I am trying to get the path of my WCF service folder hosted on my web server using C# code. I am using below logic to get the path:
string codeBase = Assembly.GetExecutingAssembly().CodeBase;
UriBuilder uri = new UriBuilder(codeBase);
string path1 = Uri.UnescapeDataString(uri.Path);
string path2 = Path.GetDirectoryName(path1);
path2 = path2.Substring(0, path2.LastIndexOf("\\"));
When I run this code on my local machine, it gives me correct path starting from the drive letter like "D:\appdir\servicehost\". However, when I run it on my web server, it does not work as expected because the IIS virtual directory on my web server is pointing to a shared location pointing to some other machine. In this case, the initial IP address part is omitted and it directly starts from the shared drive name, like
"\SharedFolder\servicehost\"
Instead, I am expecting the code to return the whole path. When the service is hosted on a local drive, it should give me "D:....." and when it is hosted on a shared drive then it should give me the path including the IP address like "\\10.44.22.11\SharedFolder\servicehost"
This is causing a file load logic to fail on my web server having the same code as my local machine because it does not find the file located at a wrong location which excludes the IP address.
Hence, I decided to use the "URI" string which contains the whole path of the dll file starting from "file://..". So I can cut the "file:" part and the dll name part of the string and get the whole path. But this does not seem to be the right way and I am sure there will be the more sophisticated way to get it worked in both cases.
Is there any common way of coding this, which I can use in both these scenarios to get the full path?
I created a new IIS App Pool as per the image:
Important thing for me was to set the NetworkService as the identity account otherwise I wasn't getting access to the network.
Then I created a share on another server to hold my TestWcfService and pointed the IIS Application at it:
In addition, the ACLs on the file system are set to EVERYONE, FULL CONTROL for ease of testing.
The service has this line:
String result = String.Format("HostingEnvironment.MapPath: {0}", HostingEnvironment.MapPath("~\\MyFile.txt"));
Resulting in this output in my testing client:
HostingEnvironment.MapPath: \\Company\Shares\1 - JayV\TestWcfService\MyFile.txt
To access the file internally within the Wcf Service, you use the return value of HostingEnvironment.MapPath as above.
To access the file remotely, from a client talking to your web service use: http://localhost/Remote/myfile.txt
My Virtual Application has no other virtual sub-directories, the Wcf Service is run from this Virtual Application and not from the root web site

ASP MVC Rotativa (wkhtmltopdf) to Virtual Directory

I don't want to raise this as an issue / bug on the git page as I imagine I am simply using the package wrong.
I have an ASP MVC site running on IIS10. Actual folder structure is:
x:/
library/ <-- Physical
Web Sites/
Site A/
Files/ <-- Virtual
Site B/
Site C/
And using IIS10, I've made a virtual folder called Files under Site A, of which the physical path is X:/library/ (the reason for this is to share resources between sites and to take the content outside of the web-site path).
Users are able to upload / download files to / from the virtual directory fine. I can load images from there without issue also.
However, I cannot seem to get Rotativa to write to the virtual directory from within my application. Obviously command line does not see the virtual directory anyway, but creating a file from cmd to the physical directory works fine.
From within the app though:
X:/Web Sites/Files/Test.pdf results in Unable to write to destination
X:/library/Test.pdf results in Access to the path is denied (despite already giving NETWORK SERVICE full control of the library folder and sub-folders)
The code I am using is:
var pdf_output= new ActionAsPdf("Summary", new { id = id }) {
FileName = String.Format("Summary_{0}.pdf",id.ToString()),
CustomSwitches = "--print-media-type"
};
byte[] pdf_data= pdf_output.BuildPdf(ControllerContext);
System.IO.File.WriteAllBytes(String.Format("xxx",id.ToString()), pdf_data);
with a variety of directory path combinations in place of "xxx".
Has anyone had any experience with this before that might show me where I am going wrong? Any help would be greatly appreciated.
Never mind, solved it. I needed to grant the respective Application Pool permission to the physical library directory by adding the user IIS AppPool\Site A.

How to find a file in server based on name in c#

I have an xml named Mapping.xml stored in my local system. i am accessing in code ,in my local system like XDocument xd = new XDocument(#"D:\MVCPopup\Mapping.xml"); .But i don't think this will work if i deploy it in iis server due to the folder structure change.Do we have a generic mechanism which will find the file Mapping.xml. Will Server.Mappath will work here?
Server.MapPath returns the phisical address from a virtual one. So if you configure a virtual folder on the iis that maps to the folder you save your XML in, then yes, Server.MapPath will help.

Providing links to files outside of IIS

I have an upload function in my system that stores the files on the d drive e.g D:\KBFiles. Now i need to offer these files as links through internet explorer. Obviously i cant just offer a path e.g D:\KBFiles\test.pdf. Whats the best way to handle this scenario
Write "proxy" file with such code and call it DownloadFile.aspx:
string fileName = Request.QueryString["file"];
string filePath = Path.Combime("D:\\KBFile", fileName);
Response.WriteFile(filePath);
Then have such link:
test.pdf
This allows you to check the user permissions if you're using Login system and also you can check the requested file against some white list to prevent hacking attempts.
You need to create a Virtual Folder for that windows folder inside your WebApplication. As soon as IIS has mapped the virtual folder, it would be possible to use direct links, which would have your WebApplication as a root.

Categories