Umbraco - Get Directory of Config Files - asp.net

I'm working with Umbraco 4.7.1 and I've created some extensions that hook into Document.AfterPublish and Document.AfterUnPublish. I need to find the directory of the config files from here, but need to be independent of server installation (i.e. a literal won't work). Is there any way of finding this at that point in time?

I think what you are looking for is the umbraco.IO.SystemDirectories class, specifically the Config property.
This will return "~/config" by default, but can be overridden by adding a umbracoConfigDirectory key to the appSettings section of the web.config file and specifying a different path there.

Related

Confused on what is the correct procedure on storing passwords in Web.config for Azure deployment

I've had a very frustrating experience on putting an MVC 5 app on Azure. I have been reading the following page: http://www.asp.net/identity/overview/features-api/best-practices-for-deploying-passwords-and-other-sensitive-data-to-aspnet-and-azure
But what I haven't managed to put in my head is the following:
Security Warning: Do not add your secrets .config file to your project or check it into source control. By default, Visual Studio sets the Build Action to Content, which means the file is deployed. For more information see Why don't all of the files in my project folder get deployed? Although you can use any extension for the secrets .config file, it's best to keep it .config, as config files are not served by IIS. Notice also that the AppSettingsSecrets.config file is two directory levels up from the web.config file, so it's completely out of the solution directory. By moving the file out of the solution directory, "git add *" won't add it to your repository.
And:
Security Warning: Unlike the AppSettingsSecrets.config file, the external connection strings file must be in the same directory as the root web.config file, so you'll have to take precautions to ensure you don't check it into your source repository.
The problem is the following: When I upload the Web.config file with the external files without being included I get hit by "The System cannot find the file specified", so for it to go away I must include the .config files defeating the purpose of Microsoft's post.
I really really really do not understand. I have added the connectionStrings and appSetting's keys in Azure's portal. What is the correct and secured way of putting my passwords and secrets online? What am I missing? Is it because I'm running in Debug mode?
According to this:
How can I secure passwords stored inside web.config?
There is nothing to worry about accessing the Web.config file...
But that just defies Microsoft's post.
Thanks.
I find the following technique to be the easiest way to do this.
Instead of putting the deployment values of these settings into the web.config, I keep the test values in there instead. I then put the deployment values into the Application Settings section of the Azure Website via the Azure Portal:
When the website runs, these settings will take precedence over what is in the web.config. This helps me avoid externalized files, allows me to keep sane development configuration that the team can share, and makes deployment very easy.
The best way is to set your secrets in the Connection Strings section of the portal. Any values set there will override values you specify in your web.config file.
This way they are only exposed to people who have admin access over the site itself. Having full access to the source won't even be enough to get the secret values.
More details here

ASP.NET bundling - default virtual paths?

As far as I can tell (because frankly documentation on System.Web.Optimization is very sparse), the way bundling works in ASP.NET is that you register a set of files (Javascript or CSS, corresponding with ScriptBundle and StyleBundle), and associate them with a virtual path; for example, ~/bundles/jqueryui for all the jQuery UI scripts. Later, ASP.NET can minify these files when you're running in non-debug mode, and the minified version will be made available at the virtual path you specified for the bundle.
The default bundle setup registers some script bundles with ~/bundles/... as the virtual path, and some CSS with ~/Content/css as the virtual path. My question is, isn't this inconsistent? Wouldn't it make more sense to have something like ~/bundles/js/... and ~/bundles/css/...? In fact, the ~/Content directory actually exists as a real directory, so there's even the chance of a name collision. I'd have thought you'd want your virtual bundle paths to be directories that don't exist by default, and are not meant to be created on the actual filesystem. Is there some reason why ~/Content/css is used for the CSS bundle virtual paths that I'm not understanding?
Great question, and the short story is that in general it doesn't matter at all. However, some script files and CSS depend on their physical location on disk because they use relative paths to reference other content. For example, of you look at the default jQuery UI bundle in new ASP.NET 4.5 project you see it has a rather long path. That's because jQuery's CSS has relative references to some image files. To get those to resolve correctly the paths matter or else things like ".." will not go up to the right parent directory.

Modifying Root Web.config in code

I would like to store some meta-information about a given site instance that can (a) be managed by that site instance and (b) persist clobbering of Web.config file.
The site will run in multiple environments (dev,testing,staging and production) and each environment can have different values for this metadata.
Note: All environments are running IIS 7.0+
The Root Web.config seems very appealing, as it is certainly outside of the website. Therefore, both files and databases can be changed while maintaining the metadata. I have seen how to modify the appSettings of the Web.config stored in the website, but is it possible to similarly modify the appSettings in the Root Web.config (Specifically within the proper directive)?
If you have other suggestions of approaching this problem, I would be very happy to hear them. Thank you!
would not use web.config for runtime modifications, that will cause the application to recycle, perhaps some other form of configuration file like app.config
if my assumption is incorrect and the web.config will not be edited after the application is started, then you can use WebConfigurationManager to access the file sections
Yes you can modufy the app settings within your web.config Just use the WebConfigurationManager class in the System.Web.Configuration namespace to create a Configuration object. This object could then be used to read and write changes to the web.config file.
You could then create your own "keys" or attributes that could be read as needed.
Depending upon what your attributes represent or if they need to be picked up by multiple environmnets from that server I would also look into making the modifications within the machine.config file as then those settings would apply to the enter machine and thereby picked up by multiple environments( if you are hosting multiple webapps from the server). This could save you time in modifying multiple web.config files and narrorw the storage or the metadata to one location vs. multiple config files in certain situations.

How might i setup my ASP.NET project to find my files?

edit I do not want to redirect pages, specific files etc. I would like to change the path where images, videos and other media are stored from the root source directory to the directory of my choosing. In this case c:/dev/prjfiles/prjname/public (c:/dev/prjfiles/prjname/ is my working directory) and i except when my html does img src="/pic.png" it will find the image in c:/dev/prjfiles/prjname/publi/pic.png. I need a working solution, i tried looking at how to set virtual directories and etc. I cant figure it out. Thus the bounty. I am generating the html, i am not writing asp:image runat="server" etc i am pulling data from a DB and outputing the html. The part that is still a WIP is the code that handles POST request. The html already exist but i cant have hundreds of files in site.com/here pollution my source directory (c:/dev/trunk/thisprj/thisprj/where my .aspx files are and i do not wish 500 .png/gif/jpg here)
I dont know how asp.net environments are usually set up. I am assuming i have a root path that is not available from the web, a bin/ where i may put my asp.net dll and a public where i stick in any files i want.
I would like to have my project files seperated from everything else. My JS, css and image files are in prjfiles/prjname/public with my sqlite db in prjfiles/prjname/ and extra binaries in prjfiles/prjname/bin.
The problem comes when i run my app and try to load an image. Such as /cssimg/error.png. My project does not find resource in my /public folder and i have no idea how to make it find them. How can i set my project up so it does?
NOTE: I set the working directory path so its at prjfiles/prjname/. In code i write ./bin/extrabin.exe and db.sqlite3 which access the files properly.
You might want to watch the getting started videos for ASP.NET
http://www.asp.net/get-started/
EDIT: More info added
As #Murph suggests, your assumptions are incorrect.
IIS takes care of blocking HTTP access to any important files and folders like your *.aspx.cs, and *.cs in the App_Code, any DLLs, anything under the App_Data directory and the web.config.
Content files, such as *.html, *.css, *.js, .gif, .jpg, .png are all served in the normal manner.
In this way, there is no need for a "public" folder.
I dont know how asp.net environments are usually set up. I am assuming i have a root path that is not available from the web, a bin/ where i may put my asp.net dll and a public where i stick in any files i want.
This is wrong assumption!
You have a root folder, which IS available in public. You set IIS or ASP.NEt Development Server to this folder.
(optional, but always needed) You have a web.config file in this root folder for configuration
You have a bin folder for your assemblies (each page or user control "include" compiles to a class)
(optional) You have App_Data as default folder for file-based DBs and/or other data files (say XML storage, ..)
(optional) You have an App_theme folder for styling and images. Read about ASP.NET themes.
(optional) You can add App_Code folder if you want to add classes to be compiled by the server.
You can create folders for scripts, etc...
Normally for complex logic, etc.. you create in a separate project outside the root and reference the result assembly in the bin folder.
Seriously, you cannot do ASP.NET work without an IDE or a manual. Visual Web Developer 2008 Express IDE is free and http://asp.net has tons of resources for getting started.
I don't know if I got the question right, but maybe you could try the <BASE> HTML tag.
HTML <base> Tag
"Specify a default URL and a default target for all links on a page"
There's a nice and simple example at W3Schools, check it out.
The negative side is that you need to put a <BASE> tag in each page you want.
It sounds like you should be able to create a virtual directory to do what you're asking -- but it's a very non-standard setup.
Keep in mind that IIS will prevent users from downloading DLLs and other project-level files, so you usually don't need to partition them off in a separate layer.
For example, just have a cssimg folder at the top level of your project, and skip the whole public folder thing.
I see where you're coming from. ASP.NET projects are set up a little differently from how you're treating them, but you can make them work like you want.
The root of an ASP.NET project IS publicly accessible. When you created your WebSite within Visual Studio, it created a default.aspx page right on the root. Are you hosting in IIS? If so, it's set up to serve up default.aspx by default. But I digress.
Here's how to make it work like you want (mostly):
Create a WebSite, then right-click the site and add a folder named "prjfiles". Right-click that folder and make another named "public". Create another subfolder of that one called "cssimg".
Now, if you want to use the image you mentioned, you'd reference it like this: "~/prjfiles/public/cssimg/error.png" (pathing starting with the root) or "./cssimg/error.png" if you're coming from a page in the public folder (relative pathing).
Really, though, you're doing too much work. Here's how to make it work with less effort:
Create your WebSite, right-click the project and add a folder called "cssimg".
Treat the root as you would the "public" folder- put your pages right there on the root or in subfolders, as needed. You can reference that same image file like this now: "./cssimg/error.png" (relative) or "~/cssimg/error.png" (start from root)
There's also another way to tell the engine where to look for resources, but it's for your css files. Inside the "head" tag, you can add a "style" element (with type="text/css") and inside that you can add something like this: #import '<%= ResolveUrl("~/prjfiles/public/cssimg/styles.css") %>';
Good luck!
If I correctly understood your problem, you're trying to find files which aren't physically stored on a filesystem folder, or stay on a different folder. You can deal with this problems by implementing a UrlRewrite mechanism.
I suggest you to read URL Rewriting in ASP.NET and, after, to take a look into this implementation: A Complete URL Rewriting Solution for ASP.NET 2.0.
If I understand all this correctly (please comment with any correction) right now all your files are together in the root directory and you use <img src="/img.png" /> and it works.
If this is the case, make another directory in the directory the images are in, say call that directory images and put the image files there. now use <img src="/images/img.png" />.
Done.

ASP.NET: external custom config file in a virtual directory - how to?

I know that there at least two approaches to leverage the web.config file:
using the configSource attribute which was introduced in .NET 2.0 - here is a good blog entry about it.
The file attribute of the appSettings tag which lets you point to an external file with a relative path. Described in the MSDN documentation on the appSettings element.
Now, my problem is that both approaches work well only for physical paths. But I need to address a config file which is in a virtual directory.
Which other method could I use to put my config resources in a virtual directory?
Note: I want to do it this way, because I have multiple instances of my web application on the same server (and that on many servers). To keep deployment easy and clean, I want to keep one directory for all the files (aspx, ascx, images, css, js etc.) and point the web apps in IIS for different customers (=domains, https etc.) to this single directory. In every IIS web I would have a virtual directory called "custom" which points to a different folder for each web.
Update: I'd like to point out that this virtual directory "custom" is not suited to contain an inherited web.config - that web.config would be valid only for the custom folder which doesn't contain aspx/ascx files.
I have the same scenario and after reading you post I realised that asp.net won't let you do this for various security reasons.
Therefore I turned to the OS to find an equivalent to the Linux soft link function which in turn led me to the Junction utility from sysinternals. This can create a directory that is actually any other directory on that volume and asp.net can't tell the difference and so happy loads the config sections that are not actually in a subdirectory of you website. Works for me :)
Virtual Directories can be set as applications, and you can just place another web.config there.
It will inherit any changes from the parent config, and you can add custom settings in it.
I was looking to do the same thing but it did not work, so I decided to do the opposite, as you know the web.config can be inherited, so I pointed IIS to a folder containing the client config (connection string, file path etc) files and the website files i put them on a virtual directory with the rest of the webconfig (where it load dll and other application files needed)
So basically i can use the website files to multple clients and the clients with their own Database connection string and other specific client settings.

Resources