Where to store uploaded files? - c#

I have an Asp.net web service and I need to store user-uploaded files. At first I thought of storing them in the App_Data folder, however, I now see that when publishing from Visual Studio with the 'Remove additional files at destination' option, it will remove files from the App_Data folder despite checking also the 'Exclude files from the App_Data folder'.
(There seem to be workarounds for this, but if it's not through the 'Publish' designer, I'm afraid that at some point the files will be removed, either due to human error, or some future MS update that will break it.)
So, I need some folder that is not under the publish path, and yet accessible (to the web app, not to the public), and that will not be auto-deleted.
EDIT
This is being done on a web hosted environment, so privileges are limited.

You may choose any folder in any path (even in another drive) as long as your asp.net application has privilege to write to it. you may even create a virtual directory for this purpose.
Edit
As you are using a hosting environment, I don't know which options they have provided, as sometimes they restrict a lot, however in most cases when you are creating a new website in your hosting environment, you are asked to provide the path something like : \wwwroot you may want to change it to something like:
\somepath\wwwroot (of course you should create somepath first), and you will have access to somepath too.

Related

Should I create my folder for file uploads under wwwroot inside visual studio?

If I were to follow this example file uploads would be stored in the wwwroot file. It is my understanding this file is where you should store static files that will be served to the user. Sure, I want my users to be able to download but is there a filesystem, specific to asp.net core/IIS/Windows Server 2012, that would be best? I'm expecting around 10,000 files max after several years.
I'm planning on creating a folder for the uploaded documents, I'm just unsure of where to place it.
Note: The answer provided here was not sufficient
To the best of my understanding, unless you take special precautions, files under wwwroot can be downloaded freely by users, bots, etc. with no authentication. If the files are not sensitive in nature, then there is nothing wrong with using wwwroot.
If you want to provide security at the controller level (e.g., a user can only view their own files), then it's probably better to put them elsewhere in the file system. The path is kind of arbitrary, but the security settings on the folder must be set in such a way that the dotnet process can access it. You can give Everyone full access, or be more restrictive if you see fit. This is done directly on the OS of the server, assuming that you have access to it.
For 2 reasons I would not do that.
1. Keep control and overview. I would create a subfolder and give it the needed rights to create and write uploaded files there.
2. You are then free to change authorization if your requirements ever should change.

How to load a config file based on user selection from "unknown" location

I have searched and searched and can't find a solution to my specific problem. I am updating a console app that will now be used for more than one client. We have decided, over storing the info in a db at least for now, to store the clients info in config files. Each client will have their own configuration file. I need to know how to load a/any config file from an "unknown" location. All of the examples that I found want me to put in the path of the file. While using my computer, I will know the path, but once it gets pushed to other servers, the paths to the file will change.
Working under these conditions, how can I load a config file for any client without knowing the path to the file?
EDIT: The console app is only ran on one server, but it is used to go to different clients websites and crawl their site. This is why each client has their own config file. It contains the information needed to get and use their site. We have a task set up for the app to run each client on a timer.
Since everything was being read from the bin folder, I looked at the properties and changed from Do Not Copy to Copy Always for Copy to Output Directory. Now it WILL locate the config files in the bin folder. And the answer to this question put me in the direction to read my config files.
What about writing every piece of code with in mind that it is to be used in another file, say with an include statement. So, every file is used in another one until we reach a wrapper file, which only purpose is to define the location of the config file. The application would always be called through such a wrapper file. This wrapper file will do whatever necessary to determine the location of the config file and make it available to the included files. If it knows the user, it can look up in a table. The key point here is that, the wrapper files would not move when you move the code from one environment to another. I think that this is a useful feature, because we do not want edit the code each time that we move it from one environment to another. Another advantage of this approach is that it applies to all environments, even very limited environments. For example, let say you provide only a folder to a programmer as a sandbox to experiment with the code. This programmer does not have access to the /bin or the /etc directory. In contrast, the proposed approach will work fine in this case, because the programmer can set the config files wherever he wants in its local wrapper files. This issue is discussed here How to organize code so that we can move and update it without having to edit the location of the configuration file?

C# ClickOnce install folder - how windows generate the folder names

I would like to know how Windows generate folder, where will be ClickOnce application installed.
In Startmenu is "shortcut" to file, what is putted in some "startrek" folder like:
C:\Users\USERNAME\AppData\Local\Apps\2.0\GT??4KXX.PRJ\EGV???1G.??C\prin..tion_7???5a2?????74b6_0000.0002_1dae????89111c35
What does those folder names mean?
For example:
If i will have for example some settings.txt file where i want that user can change some parameters of the application. Is there way how to know, WHERE it will be installed and WHERE the file is? (Where user will find this settings.txt file).
I know that i can create the file for example in C:\ and after start the application i will modify the file in "strong" path. But i dont really like too much files, folders, whatever in C:\ and i prefer to have settings files in same folder like the application. But with ClickOnce installations is it really hard - impossible - to find that file.
It seems like when the "startrek" is something like hash of the project.
So i would like to know what does the folder means and if its some hash of the project or what is that.
To find the folder that contains your executable, you can use the Assembly.Location property.
For example:
string exeFolder = System.Reflection.Assembly.GetExecutingAssembly().Location;
However, if you want to store settings for your ClickOnce app, you shouldn't do it by writing a file to the .exe's folder.
Instead, you should use Microsoft's Application Settings support. Doing it any other way is going to be a lot of extra hassle, and Microsoft's support is very good. It does need half an hour to read through the documentation, but it's far and away the best thing to do, IMHO.
(I'm assuming that you only need the settings to be stored on the local PC for the same user to use later. If you want the settings to follow the user around (i.e. roaming settings), you can't use the Microsoft support.)
If you have more complex settings that you want to store in a file that you create directly, you should consider using the isolated storage that the answer from JRoughan mentions.
From inside the ClickOnce app you can find the default directory where files are stored using
ApplicationDeployment.CurrentDeployment.DataDirectory
Or you can use isolated storage and choose whether you want to save per application or per user.
I don't think it's possible to determine these folders from outside the app itself. If you need a known location you'll have to hard-code it.
Update
I also don't believe it's possible to infer what the install directory will be for an app. It would be unwise to use even if possible as updates to the app will not be in the same location.
If you have data that the user is modifying through your program, you will be happier if you don't leave it in the ClickOnce program directory. You can get completely messed up when there's an update. Check out this article about what to do with your data to keep it safe and be able to find it. It talks about putting it in LocalApplicationData, but if you want your user to be able to find it and edit it, just put it in MyDocuments/yourappname/settings or something like that.
I wouldn't use Isolated Storage; there are reported problems with that and ClickOnce.

How to get the directory of database?

I am using the Microsoft database that is inside C:\wpf1\WpfApplication1\WpfApplication1 folder. When I update the database it always updates the one inside C:\wpf1\WpfApplication1\WpfApplication1\bin\Debug which I don't want.
How do I get the folder C:\wpf1\WpfApplication1\WpfApplication1 without typing this full name?
There is an article here about sql server compact edition
I dont think anything has changed in the newer releases although it is a while since i have used it.
|DataDirectory| works as follows
Your connection string would normally look like this
“Data Source = |DataDirectory|\Mydb.sdf”
To set the DataDirectory property, call the AppDomain.SetData method.
If you do not set the DataDirectory property, the following default rules will be applied to access the database folder:
For applications that are put in a folder on the user's computer, the database folder uses the application folder. (this is the default rule that applies when debugging and hence why the database in \bin\debug is the one that is updated)
For applications that are running under ClickOnce, the database folder uses the specific data folder that is created.
In the past i have done the following
Handle the SettingsLoaded event in settings.vb
Private Sub MySettings_SettingsLoaded(sender As Object, e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded
If Not Debugger.IsAttached Then
My.Settings.SQLCEConnectionString = "somefolder\somefile.sdf"
End If
End Sub
The directory C:\wpf1\WpfApplication1\WpfApplication1 is your project directory - its the one that the source code is in, but its not normally a directory that your application would usually be aware of or work with (for example if your application is installed to another PC then this directory simply won't exist).
The usual approach when working with databases or dependent files is to either:
Put the file in some other common location (such as in a folder on the C: drive)
Just have the application work with the copy of the file in the output (bin\Debug\) directory, i.e. the directory that the application will be installed to - you can change the properties of the item in your solution to have the item copied to the output directory, either all the time or only when the item in the solution directory is newer:
If you really want to use C:\wpf1\WpfApplication1\WpfApplication1 directory then the way to do it is to assume that this directory will always be 2 higher than the current working directory:
Path.GetFullPath(Path.Combine(Environment.CurrentDirectory, "..\\.."));
This of course makes 2 horrible assumptions, first that the current directory is the directory that the .exe is contained in, and secondly that the directory you want is always 2 higher than this directory - I strongly recommend that you find another way as this sort of logic is highly unlikely to work on an end-users PC.

Best place to store configuration files and log files on Windows for my program?

I need to store log files and configuration files for my application. Where is the best place to store them?
Right now, I'm just using the current directory, which ends up putting them in the Program Files directory where my program lives.
The log files will probably be accessed by the user somewhat regularly, so %APPDATA% seems a little hard to get to.
Is a directory under %USERPROFILE%\My Documents the best? It needs to work for all versions of Windows, from 2000 forward.
If you're not using ConfigurationManager to manage your application and user settings, you should be. The configuration toolkit in the .NET Framework is remarkably well thought out, and the Visual Studio tools that interoperate with it are too.
The default behavior of ConfigurationManager puts both invariant (application) and modifiable (user) settings in the right places: the application settings go in the application folder, and the user settings go in System.Environment.SpecialFolder.LocalApplicationData. It works properly under all versions of Windows that support .NET.
As for log files, System.Environment.SpecialFolder.LocalApplicationData is generally the place that you want to put them, because it's guaranteed to be user-writeable.
There are certainly cases where you wouldn't - for instance, if you want to write files to a network share so that you easily can access them remotely. There's a pretty wide range of ways to implement that, but most of them start with creating an application setting that contains the path to the shared folder. All of them involve administration.
I have a couple of complaints about ConfigurationManager and the VS tools: there needs to be better high-level documentation than there is, and better documentation of the VS-generated Settings class. The mechanism by which the app.config file turns into the application configuration file in the target build directory is opaque (and the source of one of the most frequently asked questions of all: "what happened to my connection string?"). And if there's a way of creating settings that don't have default values, I haven't found it.
Note: You can get the path to the LocalApplicationData folder in .NET by using the following function:
string strPath=System.Environment.GetFolderPath(System.Environment.SpecialFolder.LocalApplicationData);
For application settings - use System.Environment.SpecialFolder.ApplicationData - this is where a roaming profile data is stored, so it allows your user to log and work from different machines in the domain.
For log files - System.Environment.SpecialFolder.LocalApplicationData
The accepted answer notes that for log files the following is a good spot.
System.Environment.SpecialFolder.LocalApplicationData This equates to a path of C:\Users\[User]\AppData\Roaming which you can see is user specific. Like the accepted answer mentions this is a guaranteed user-writeable location and can be useful for certain situations
However in a web application environment you may be running your application under a network account and you or a coworker may need to try and track down where exactly those logs are going per application. I personally like to use the non user specific location enumeration of
System.Environment.SpecialFolder.CommonApplicationData which equates to C:\ProgramData. Yes, you will need to specify access rights for any folders you create, but it's usually a one time deal and then all of your application logs can live in one happy location.
Additionally, while looking around the Internet, there is a project out there to programatically set write access to folders you create within CommonApplicationData, Allow write/modify access to CommonApplicationData.
To be honest %appdata% is still the best place to place your config files and log files, as it serves the purpose of a placeholder to store your application data. It should not be that hard to access, just write %appdata% in explorer and you will be directed straight to your %appdata% directory.
Do not store config files in the application folder, Microsoft has stated this is NOT the ideal location. Windows has been moving towards blocking writing to C:\Program Files\ and you'll find in Vista any application that tries to write here, will fire up a UAC warning.
Windows 7 will allow users to customize what UAC popups they use (expect some power users to block most of them) and your app will fail/freeze if the user never approves this write attempt.
If you use the proper userprofile and appdata variables, then Win 2000, XP, Vista, and Win7 will map the data to the proper write friendly folder, with no UAC popups.
You can use SHGetSpecialFolderPath:
int MAX_PATH = 255;
CString m_strMyPath;
SHGetSpecialFolderPath(NULL, m_strMyPath.GetBuffer(MAX_PATH), CSIDL_COMMON_APPDATA, TRUE);
This will specify the 'special folder path' which you can safely write logs to for windows:
For XP: C:\Documents and Settings\All Users\Application Data
For Vista: C:\ProgramData
Check the MSDN page here: http://msdn.microsoft.com/en-us/library/bb762204(VS.85).aspx
The best answer depends on the nature of the logs and configurations. If they are program-wide, and don't need to survive uninstallation of the application, then I think they're fine where they are. If the logs and configurations are user specific, or need to survive uninstallation, then they belong somewhere under %USERPROFILE% - %APPDATA% being the 'proper' base directory for this type of thing.
I use the Isolation Storage for configuration. You can also use the Temp folder to store temporary information like log.

Categories

Resources