The differences of running on a server - c#

I have a program that fetches a file from a server and downloads it. It is itself located on the server, so to run it you open your browser and type in a URL with parameters.
Now, it runs perfectly fine when the program is located on my machine. However when accessed via your browser it seems to hang. I have tried
MessageBox.Show(username, "Error", MessageBoxButtons.OK, MessageBoxIcon.Exclamation, MessageBoxDefaultButton.Button1, MessageBoxOptions.ServiceNotification);
string[] lines = {"First line", "Second line", "Third line"};
System.IO.File.WriteAllLines(#"C:\Users\Public\TestFolder\WriteLines.txt", lines);
and both of those cause errors when done on the server (but it's fine when on my own machine).
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\Public\TestFolder\WriteLines2.txt"))
file.WriteLine("asfsd");
this seems to hang on the writeline, as the file is created but no content is ever put into the file. Any idea why this is happening or suggestions of things I can put so I know where the problem is?

If I had to guess. Id say you didnt have permissions. Try wrapping everything in an Impersonate statement or give the worker process access to the directory.
using (new Impersonator(username, domain,password)) {
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\Users\Public\TestFolder\WriteLines2.txt"))
file.WriteLine("asfsd");
}
}
Also, make sure the directory exists before writing.

It sounds like you're mixing WinForms development with ASP.NET development, and they are two very different animals.
If you are having an issue writing to a file, it's more than likely caused by a permissions issue. IIS default app pool typically runs as NETWORK SERVICE user, which most likely doesn't have permissions in your target directory.

You're trying to write to a local file and IIS on the server obviously doesn't have permissions to do that (what a surprise :-) ). Save files in your webapp folder instead, not in C:\

Related

Application can find 'Downloads' folder when debugging but not on IIS

I have an application that allows the user to upload a file (saving it to in a folder located in the wwwroot of the ASPNETCORE application). From here they can make edits to it and then they can choose to export the file as a csv/ xml/ xlsx which downloads the file to the user's 'downloads' folder.
While debugging in Visual Studio this all works fine however when I publish and deploy the application to IIS I am getting the exception
Error saving file C:\windows\system32\config\systemprofile\Downloads(FILE NAME)
Could not find part of the path C:\windows\system32\config\systemprofile\Downloads(FILE NAME)
This is the current way I am getting the downloads folder:
FileInfo file = new FileInfo(Path.Combine(Environment.ExpandEnvironmentVariables(#"%USERPROFILE%\Downloads"), data.Filename + "." + data.FileType));
However I have also tried the solution that Hans Passant has answered to a similar question here. Both solutions worjk fine while debugging locally however as soon as I publish them, this one produces the exception:
Value cannot be null. Parameter name: path1
Which I presume is thrown at this point here when I try and save the file to the user's download folder.
using (var package = new ExcelPackage(file))
{
var workSheet = package.Workbook.Worksheets.Add("ExportSheet");
workSheet.Cells.LoadFromCollection(exports, true);
package.Save();
}
I don't really know how I would be able to reproduce these exceptions seeing as locally using Visual Studio it all works fine.
Has anyone else came across this issue while trying to download a file?
UPDATE: When the application is running on IIS, it seems to be using that as the user profile instead of the actually user, so when it tries to navigate to the Downloads folder, it cannot find it. How can I force it to use the user's profile?
LoadUserProfile is already set to True.
Web applications have no knowledge of the end-user's computer's filesystem!
So using Environment.GetFolderPath or Environment.ExpandEnvironmentVariables in server side code will only reveal the server-side user (i.e. the Windows Service Identity)'s profile directories which is completely separate and distinct from your web-application's actual browser-based users OS user profile.
As a simple thought-experiment: consider a user running a weird alien web-browser on an even more alien operating system (say, iBrowse for the Amiga!) - the concept of a Windows-shell "Downloads" directory just doesn't exist, and yet here they are, browsing your website. What do you expect your code would do in this situation?
To "download" a file to a user, your server-side web-application should serve the raw bytes of the generated file (e.g. using HttpResponse.TransmitFile) with the Content-Disposition: header to provide a hint to the user's browser that they should save the file rather than try to open it in the browser.

Can't see path to another server in ASP.NET MVC

I have an internal ASP.NET MVC site that needs to read an Excel file. The file is on a different server from the one that ASP.NET MVC is running on and in order to prevent access problems I'm trying to copy it to the ASP.NET MVC server.
It works OK on my dev machine but when it is deployed to the server it can't see the path.
This is the chopped down code from the model (C#):
string fPath = HttpContext.Current.Server.MapPath(#"/virtualdir");
string fName = fPath + "test.xlsm";
if (System.IO.File.Exists(fName))
{
// Copy the file and do what's necessary
}
else
{
if (!Directory.Exists(fPath))
throw new Exception($"Directory not found: {fPath} ");
else
throw new Exception($"File not found: {fName } ");
}
The error I'm getting is
Directory not found:
followed by the path.
The path in the error is correct - I've copied and pasted it into explorer and it resolves OK.
I've tried using the full UNC path, a mapped network drive and a virtual directory (as in the code above). Where required these were given network admin rights (to test only!) but still nothing has worked.
The internal website is using pass through authentication but I've used specific credentials with full admin rights for the virtual directory, and the virtual dir in IIS expands OK to the required folder.
I've also tried giving the application pool (which runs in Integrated mode) full network admin rights.
I'm kind of hoping I've just overlooked something simple and this isn't a 'security feature'.
I found this question copy files between servers asp.net mvc but the answer was to use FTP and I don't want to go down that route if I can avoid it.
Any assistance will be much appreciated.
First, To be on the safe side that your directory is building correctly, I would use the Path.Combine.
string fName = Path.Combine(fPath, "test.xlsm")
Second, I would check the following post and try some things there as it seems to be a similar issue.
Directory.Exists not working for a network path
If you are still not able to see the directory, there is a good chance the user does not have access to that network path. Likely what happened is the app pool running your application has access to the directory on the server. The production box likely doesn't have that same access. You would have to get with the network engineer to get that resolved.
Alternatively, you could write a Powershell script to run as a user who has access to both the production and the development server to copy the file over to the production server if that is your ultimate goal and your server administrators could schedule it for you if that is allowed in your environment.

Can not delete file off of a server when running on server

part of a console application I have is built to delete an unwanted order file out of a directory on a server we use. This part of the code works fine when I run it off of my local machine, but when we run it on the server it self (it will be a scheduled task), it no longer deletes the file.
try
{
System.IO.File.Delete(#"\\ServerName\ProductionFileShare\Orderfiles\FileDir\" + fileName);
}
catch (System.IO.IOException e)
{
Console.WriteLine(e.Message);
return;
}
The filename is just the storeorder.txt.
As I said, this works just fine on my local computer, but does not delete the file when we run this program from the server itself. Any ideas?
UPDATE: The exception message is: The process cannot access the file '\ServerName\ProductionFileShare\Orderfiles\FileDir\storeorder_07062014_16-25-0.txt' because it is being used by another process.
This is strange to me, since it works on my computer. I will add some garbage collection and see what happens.
UPDATE #2: Apparently that fixed it! That was an unexpected solution. Thanks to everyone for taking the time to comment, I really appreciate it.
I've had this problem before, where I simply moved to the admin share (\\server\c$\path\file.txt), or changed the path to a local path, and all was good.
It should be mentioned that there are both file permissions, and permissions to access the share itself, the later is likely where the problem lies.
If changing the path helps (and you do not have easy access to fix the share), then you could make it a configuration setting, and use a different configuration at each location.

Copying files to a mapped drive while user is not logged in (scheduled task)

I have a job that needs to connect to two fileshares and copy some files for a data feed.
The source server is on our domain's network, and that works fine. The remote server, however, chokes on me and throws a "Could not find part of the path" error. I should add the destination server lives in a different domain than my source server.
The source and destination paths are read out of my app.config file.
I thought persistently mapping a drive would work, but since this is a scheduled task, that doesn't seem to work. I thought about using NET USE, but that doesn't seem to like taking a username and password.
The really weird thing - if I double click on the job while I'm logged into the machine, it'll run successfully.
Sample code:
DirectoryInfo di = new DirectoryInfo(srcPath);
try
{
FileInfo[] files = di.GetFiles();
foreach (FileInfo fi in files)
{
if(!(fi.Name.Contains("_desc")))
{
Console.WriteLine(fi.Name + System.Environment.NewLine);
File.Copy(fi.FullName, destPath + fi.Name, true);
fi.Delete();
}
}
}
Apparently this isn't as simple as copying the files over. Any suggestions on mapping a drive with credentials in C# 4.0?
EDIT
I'm trying to use a batch file called from the console application that maps the drive while the program is running. I'll know for sure whether that works in the morning.
I'd suggest looking into a proper file transfer protocol, like FTP.
Assuming that's out of the question, try using a UNC path like \\servername\path\file.txt. You will still need credentials, but assuming that the account running the application has those permissions you should be fine. Given that you mention a web.config file, I am guessing that would be an ASP.NET application, and therefore I mean the account that runs the Application Pool in IIS. See http://learn.iis.net/page.aspx/624/application-pool-identities/
What I finally wound up doing was mapping the drive in a batch file called by my program. I just launch a NET USE command and pause for a few seconds for the mapping to complete.
It looks like while the user is logged out, there's no context around mapped drives.

Writing to a file I get unauthorized access error.How can I do it?

Despite numerous post on the web I cannot find an answer to my problem.
I am writing an application that writes csv files to folders.Users should be able to pick a directory.
I am developing in windows 7 using vs2010 running my app in Admin Mode.Regardless of all this I still get the "Unauthorized access exception" when I do
var path=#"c:\" or c:\MyFolder
StringBuilder sb=new StringBuilder();
sb.AppendLine("Test");
var myFile=sb.ToString();
using (var writer=new StreamWriter(path))
{
writer.Write(myFile);
}
Am I missing something?
I have feeling that in window7 you can only write to designated folders.Is this what's happening?
any suggestions?
EDITED
I have created few folders under "C:\MyFolder\"
I am not using any credentials eg windows impersonation etc..
It does write if it writes to the bin\debug\ of my class library. but not to any designated folder.
Is your code snippet the real code causing the problem?
On the face of it, you are trying to stream the text "Test" into a directory on the file system, not trying to write a file. (path is just assigned to #"C:\"). I'm not surprised that you get an UnauthorizedAccessException.
Assign the full path of the file you want to write into your path variable, and I imagine you'll succeed.
Try running your app with "Run as Administrator". The comments above will probably also steer you in the right direction. You should definitely pick a directory that your windows users has access to edit.

Categories