How to apply config transformations to an external config file - asp.net

I can't find an example of my question on the web and was wondering if anybody knew a solution. Basically, if on our web.config we point to another file, like so:
<configuration>
<configSections />
<appSettings file="AppSettings.config">
</configuration>
then how do we apply transformations to that external file?
Basically, I want to create an AppSettings.config, AppSettings.Debug.config, AppSettings.Release.config and have a transformation run over it... Is this even possible?
Thanks in advance,
Sergio

There are few workarounds:
Workaround 1
Write AppSettings.Debug.config, AppSettings.Release.config with full values (not with transform attributes)
In your web.config, using transformation, substitute with the appropriate file:
web.debug.config
<appSettings file="AppSettings.debug.config"
xdt:Transform="SetAttributes" xdt:Locator="Match(file)"/>
web.release.config
<appSettings file="AppSettings.release.config"
xdt:Transform="SetAttributes" xdt:Locator="Match(file)"/>
Its less than ideal, kinda defeats the purpose of transforms but may be appropriate based on one's situation than using something like SlowCheetah.
Workaround 2
Use TransformXml build task to transform your files during build as pointed here and here

There's a Visual Studio plugin project called Slow Cheetah that takes the idea of transformations and allows you to apply it to files other than web.config, I haven't used it but I think it'll do what you want to do. Scott Hanselman did a blog on it.

Workaround 1 in the accepted answer put me on the right track, but didn't work as is because the transformation isn't quite right. The correct transformation is just
<appSettings file="AppSettings.debug.config"
xdt:Transform="SetAttributes"/>
I had to remove xdt:Locator="Match(file)" so that the file attribute itself would change. Web Config Transformations explains that Match(key) will locate the element to change, but will only change the other elements of the node, not the locator/match key itself. There will be only one appSetting per config file, so we don't need to locate a particular instance.
(I don't have enough reputation to comment on the accepted answer, so I posted this as another answer.)

Related

Multiple, aggregate transforms of web.config

In short, is it possible to have this kind of nested transformation hierarchy for transorming web.config at build time?
web.config
|_
web.config.release
|_web.config.release.live
|_web.config.release.stage
So in other words, web.config.release applies xdt:transforms to web.config, and then the last two apply transformations to the output of that.
I'm trying to avoid the repetition that I'd otherwise have in all the transforms. The last two in my example here for instance would do little more than insert keys, connection strings or account passwords.
Have I missed something obvious - is this possible?
So it turns out this sort of works. It does what I want, although I have no idea how it knows which file to use in which circumstance, but given simply these files in VS2013;
web.debug and web.release transforms are applied as normal on build. Seondly, the Wen.IIS Localhost xxxx configs are applied to the output of that when published. The latter files only need to contain the few lines that differ from the previous transformation output.
Publishing is good for debug which is what I wanted it for, but for I don't publish live web sites that way. I'd have thought that perhaps there was some build event task in my csproj that I could edit but it seems either to be built into VS or defined elsewhere.
So I'm getting the multiple transform task that I wanted, however I haven't found a way to build nested transformations in general as outlined in the question.

python_stubs directory placed in wrong location (PyCharm 3.4)

my current Win7 environment has the user home set to a network drive. Because of that PyCharm startup is taking a long time. Therefore I changed idea.properties to these values:
idea.config.path=c:/config/.PyCharm30/config
idea.system.path=c:/config/.PyCharm30/system
All is working fine and startup is much faster now. But a background process is rebuilding the skeleton files (which takes a long time) and is placing them here:
<myNetworkDrive>:\.PyCharm30\system\python_stubs\-1234567890\
It seems that this skeleton process doesn't follow the settings in idea.properties. Or is there any other setting I have to make?
Thanks,
Best regards,
Michael
I copied and adapted this from here because it is unanswered, thanks to Marcel for that question:
http://forum.jetbrains.com/thread/PyCharm-1971
Not sure if this is the write way. I've changed file config/options/jdk.table.xml.
It worked for me.
I've changed line
<root type="simple" url="file://$USER_HOME$/.PyCharm30/system/python_stubs/1167955305" />
to
<root type="simple" url="file://$APPLICATION_HOME_DIR$/system/python_stubs/1167955305" />

How can one read a text file in a Struts 2 app [duplicate]

This question already has answers here:
Where to place and how to read configuration resource files in servlet based application?
(6 answers)
Closed 6 years ago.
Developing a Struts 2 app I run in a following problem. I need to read a text file that is deployed in web server with my app. How can I access it knowing its relative path. In other words how can I find absolute path if I know relative path inside the deployed directory.
When I had similar problem with servlets I used to use this.getContextPath() (or something similar) that returned an absolute path to the folder in the webserver.
EDIT:
Thank you guys for answer. For me worked this:
String path=GetPointsOfInterestAction.class.getResource("../../../resources/visitor_attractions.txt")
Could you please explain why I it worked because I'm making first steps in java.
If it is placed in the webapp's classpath, then just use:
InputStream input = servletContext.getResourceAsStream("file.txt");
If it is placed in the global classpath, then use:
InputStream input = Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt");
If it is placed in the webcontent, then just use:
InputStream input = new FileInputStream(servletContext.getRealPath("file.txt"));
The examples assumes that they're placed in the root. You can of course use relative path as opposed to the classpath root or webcontent root, e.g. path/to/file.txt. You can get the ServletContext in Struts by ServletActionContext#getServletContext().
Edit: You edited your question with following:
EDIT: Thank you guys for answer. For me worked this:
String path=GetPointsOfInterestAction.class.getResource("../../../resources/visitor_attractions.txt")
Could you please explain why
This is actually not the "right" way, but this is also doable. You only need to make sure that you know the relative path of the file as opposed to the actual path of the GetPointsOfInterestAction class. This class is of course placed in a different package, so you basically need to step a directory back (like you do in normal disk file systems: cd ../ and so on). Again, this is not the most elegant way. You need to use one of the first two aforementioned ways, with the resource name resources/visitor_attractions.txt.
Here
ServletActionContext.getServletContext()
You seem to know what to do from there.
You could use a Resource Bundle. I use them to look up properties files. I believe that the directory just needs to be on the Classpath and the ResourceBundle will find it.
If the file is on the classpath (which is not clear, but this would be a good idea), I'd suggest to use the utility classorg.apache.struts2.util.ClassLoaderUtils. From its java documentation:
This class is extremely useful for loading resources and classes in a fault tolerant manner that works across different applications servers.
Pay a special attention to the ClassLoaderUtils.getResourceAsStream(String resourceName, Class callingClass) static method which is a convenience method to load a resource as a stream. As documented, the algorithm used to find the resource is given in getRessource():
This method will try to load the
resource using the following methods
(in order):
From Thread.currentThread().getContextClassLoader()
From ClassLoaderUtil.class.getClassLoader()
From the callingClass.getClassLoader()

What is the best way to determine URL for local/staging/production?

For local testing the url is something like:
http://localhost:29234/default.aspx
For staging, the app is in a virtual directory:
http://stage/OurApp/default.aspx
For production, it's the root
http://www.ourcompany.com/default.aspx
However, sometimes we need to do a redirect to a particular directory. We don't always know exactly where we are at.
So, how would I do a redirect to say /subdir1/mypage.aspx?
MORE INFO
I neglected an important item. This url is sent back to the browser so that some javascript code can perform the redirect. (Odd, I know). So a regular ResolveUrl("~/pagename.aspx") won't give the full info...
UPDATE 2
I ended up with the following, which seems to work across the board... It looks a little ugly though.
StringBuilder buildUrl = new StringBuilder(#"http://");
buildUrl.Append(Request.Url.Host);
if (Request.Url.Port != 80) {
buildUrl.Append(":");
buildUrl.Append(Request.Url.Port.ToString());
}
buildUrl.Append(this.ResolveUrl("~/Pages/Customers.aspx"));
buildUrl.Append(String.Format("?AccountId={0}&tabName=Tab2&primaryCustomerId={1}", acctId, custId));
When paths start diverging between different environments, and you cannot bring any sanity to the situation, it's time to start puttin' paths in the web.config.
It's not a cure for inconsistent file paths, but it'll make your code consistent and you won't have to worry about having "let's figure out where i am" logic.
The tilde is a shortcut for HttpRuntime.AppDomainAppVirtualPath (more)
~/subdir1/mypage.aspx
If the subdir1 is a directory within your web application, you can use a relative link (subdir1/mypage.aspx instead of /subdir/mypage.aspx -- note the lack of the first forward slash). This way, it won't matter where your application is because the links will be relative to the current page.
A suggestion is you can use the BASE tag for the page which can be the root. by using this, all your relative paths will be resolved based on BASE path.
General Advice
I recommend storing the path in your settings. There are reasons why some of our projects need various paths and urls, and we can't always get away with using the tilde (~).
Our Strategy
In our projects here at Inntec, our web.config contains a database connection string and a variable saying what the environment is - Production, Staging, Development, etc.
Then, in the database, we've got a set of variables for each environment, and there's a nice class that strongly types the settings and pulls/caches the right setting for the current environment. So in our code we can say: Settings.AppUrl and everything just works.
We use Redgate's Sql Data Compare to sync the settings across all instances (so each environments always has the settings for all environments), and there are unit tests that make sure each environment has a complete batch of settings.
That's one way to do it... So far it has worked really well for us.

Can you rename the App_Code folder?

I realize this would violate convention, but I'm curious to know if you can do this through configuration.
Edit: I understand why I wouldn't want to do this. BUT, I do want to understand the internals of this time of project.
No you cannot rename this folder and have it actually contain executable code. The web project system is hard coded to look for code in this folder and will not consider any other folder for raw code.
Reflector tells me that System.Web.HttpRuntime contains...
internal const string CodeDirectoryName = "App_Code";
So the answer is no.
I dont think this is posible, but why do you need to change it?
Google "Convention over Configuration"

Resources