ASP.NET - Unity - Read configuration section from external configuration file - configuration

I want to integrate Unity in my app and I want it to use an external config file
The Unity initialization code is
var fileMap = new ExeConfigurationFileMap { ExeConfigFilename = "unity.config" };
System.Configuration.Configuration configuration =
ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
// *** problem starts here ***
var unitySection = (UnityConfigurationSection)configuration.GetSection("unity");
var container = new UnityContainer().LoadConfiguration(unitySection);
Also I have external config file for unity, named "unity.config" with the following content
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<alias alias="IEmailConfigurator" type="Server.Common.Interfaces.IEmailConfigurator, Server.Common" />
<alias alias="EmailConfigurator" type="Server.Common.EmailConfigurator, Server.Common" />
<namespace name="Server.Common.Interfaces" />
<namespace name="Server.Common" />
<container>
<register type="IEmailConfigurator" mapTo="EmailConfigurator" />
</container>
</unity>
The problem is, in the line where I want to load unitySection, GetSection() returns null.
What could be the problem?
EDIT
I added
<configuration>
<configSections>
<section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Microsoft.Practices.Unity.Configuration"/>
</configSections>
However, now when I trace through code, in line
System.Configuration.Configuration configuration = //...
The configuration variable in initialized that FilePath property is C:\Program Files (x86)\IIS Express\unity.config, and not my own unity.config file
Any idea how to reference the config file from web folder?
Thank you.

http://msdn.microsoft.com/en-us/library/ff660935%28v=pandp.20%29.aspx
Your external config file must also start from <configuration> tag, not <unity> tag

Did you try to add the <configuration> and <configSections> element to your config file?

I don't know if you solved this yet. In Visual Studio, you have to ensure the following file properties for "Unity.config":
Build Action -> "Content"
Copy to Output Directory -> "Copy if newer" or "Copy Always"
I suggest "Copy Always" to ensure the current Unity configuration is always present after a build.

To access the web folder, use the HttpServerUtility.MapPath method.
var mappedConfig = Server.MapPath("~/unity.config");
Server is a property of the Page, or use HttpContext.Current.Server.

Related

How to configure Tomcat to use a context path like /webapps/myapp

After reading that I shouldn't set the context in server.xml, I tried creating META-INF/context.xml. The Resource definitions are read ok but the path attribute is ignored.
<Context path="/webapps/uebersetzung" docBase="UebersetzungWeb">
<Resource ....
</Context>
The war file is UebersetzungWeb and I want to set the context path to webapps/uebersetzung. (I am migrating a WebSphere app and the context path is hard-coded in many places)
So far, the only way I found to do this is to rename the war to webapps#uebersetzung before deployment.
Is this the correct way?

SQLCMD include all scripts in folder

In my Post Deployment Script, I would like to include all script files in a folder using a wildcard like this:
:r .\$(ReleaseName)\*.sql
Is there a way to do this? I can't find any..
I got it working:
<MyFilesPath Include="$(ProjectDir)MyPath\*.sql"/>
<MyFiles Include="#(MyFilesPath->':r %22..\Scripts\%(filename)%(extension)%22%0D%0A', '')"/>
Then I include #MyFiles in my PostScript-file.
I took a different approach that was easier for me to understand.
I simply added code to the Pre-build event in the database project properties page that copies the script files into a single file. I call a bat file and pass in the project path as a parameter because it's much nicer to edit the file than trying to edit in that little textbox in the properties page.
$(ProjectDir)PreBuildEvent.bat "$(ProjectDir)"
I set the contents of the bat to this:
copy %ProjectDir%DbUpdateScripts\*-Pre.sql %ProjectDir%DbUpdateScripts\AllPreScripts.sql
copy %ProjectDir%DbUpdateScripts\*-Post.sql %ProjectDir%DbUpdateScripts\AllPostScripts.sql
Then just include those files in your actual pre and post deploy scripts.
:r .\DbUpdateScripts\AllPreScripts.sql
:r .\DbUpdateScripts\AllPostScripts.sql
And finally, add AllPreScripts.sql and AllPostScripts.sql to your .gitignore file if you have one to prevent them from getting added to source control.
Building upon #SAS answer, here is what I did to get this working using MSBuild. Basically, the idea is that we add a pre-build target that auto-generates a post-deployment script referencing all the scripts in the source folder.
In the .sqlproj add the following at the end of the file:
<Target Name="BeforeBuild">
<PropertyGroup>
<MyAutogeneratedScriptPath>$(ProjectDir)Scripts\Post-deployment\MyScript.autogenerated.sql</MyAutogeneratedScriptPath>
</PropertyGroup>
<ItemGroup>
<MyScriptsLocation Include="$(ProjectDir)Scripts\Post-deployment\RunAll_1\*.sql" />
<MyScriptsLocation Include="$(ProjectDir)Scripts\Post-deployment\RunAll_2\*.sql" />
</ItemGroup>
<WriteLinesToFile File="$(MyAutogeneratedScriptPath)" Lines="-- This is an auto-generated file, any changes made will be overwritten" Overwrite="true" />
<WriteLinesToFile File="$(MyAutogeneratedScriptPath)" Lines="#(MyScriptsLocation->':r %22%(FullPath)%22', '%0D%0A')" Overwrite="false" />
</Target>
And then in your main post-deployment script file, include the MyScript.autogenerated.sql file.
Also, you might also want to add *.autogenerated.sql to your .gitignore file.

What manifest visual studio is using to generate msdeploy package

I want to package a folder with msdeploy.exe to a zip destination at the end of CI process.
I run the following command line
msdeploy.exe -verb:sync -source:contentpath="C:\SampleWebApp" -dest:package="c:\SampleWebApp.zip" -declareParamFile="parameters.xml"
I also like the *.deploy.cmd and *.SetParameters.xml which msbuild generates when it spits out a deployment package. I renamed the one set of *.deploy.cmd and *.SetParameters.xml file and changed the content accordingly. to be able to run in deployment environment.
When I run *.deploy.cmd file it generates the folder "C:\SampleWebApp" rather than creating the iis app based on parameters provided in .SetParameter.xml.
After some investigation, I've found that the .cmd deploys to -dest:auto which is good. but apparently my package manifest inside the package indicates that this package is contentPath whereas packages generated by msbuild has more complex manifest in archive.xml inside package using iisApp provider.
Having looked at following post
http://blogs.msdn.com/b/webdev/archive/2013/01/09/real-scenario-folder-deployment-scenarios-with-msdeploy.aspx
I believe if I use -source:manifest="Package.xml" with right Package.xml the end result should be similar to VS package output
The I thought maybe the *.SourceManifest.xml is the manifest for the package. I used and it builds the package but when I want to deploy that to the using .deploy.cmd it complains about setAclUser
Error: A value for the 'setAclUser' setting must be specified when the
'setAcl' provider is used with a physical path.
Does anybody know that is the manifest msbuild uses?
To directly answer your question: the manifest is generated dynamically based on MsDeploySourceManifest MSBuild items.
You can make it use contentPath rather than iisApp by declaring DeployAsIisApp=false in your publish profile (or command line /p:DeployAsIisApp=false). This will also disable the setAcl providers.
If you want to keep iisApp, you can disable the ACL providers...
... being added to the package by declaring IncludeSetAclProviderOnDestination=false in your publish profile
... being deployed by passing /I:False to deploy.cmd
Following is the manifest template
<?xml version="1.0" encoding="utf-8"?>
<sitemanifest>
<iisApp path="[PATH1]"/>
</sitemanifest>
and Parameter.xml template
<parameters>
<parameter name="IIS Web Application Name" defaultValue="WEBSITENAME" tags="IisApp">
<parameterEntry kind="ProviderPath" scope="IisApp" match="^[PATH1ESCAPED]$" />
</parameter>
<!-- appSetting section-->
</parameters>
note: [PATH1] should be replaced with your folder path like C:\MY.FOLDER\WWW
and [PATH1ESCAPED] should be same path but escaped with postfix and prefix ^ $ like
^C:\MY.FOLDER\WWW$
Then you can call
"C:\Program Files\IIS\Microsoft Web Deploy V3\msdeploy.exe" -verb:sync -source:manifest="Manifest.xml" -dest:package=%1 -declareParamFile="parameters.xml"
and %1 being folder path like C:\MY.FOLDER\WWW

How to pass relative path in appsetting

i have following code and when i pass absolute path my project works but i need relative path configuration.ini is a file which is in my current project so when i give absolute path, like this ,the code never runs
<app Settings
<add key="Configuration Path" value="d:DocsWcfService\Configuration.INI"/>
</app Settings
i need something like this ,is there any way?
<app Settings
<add key="Configuration Path" value="~\Configuration.INI"/>
</app Settings
Server.MapPath
var physicalPath = Server.MapPath("~\Configuration.ini");
I had the same problem for config file before. I was able to use full path and it was working fine. When I try to use relative path , it wasn't able to find my config file. I hope my solution helps you or at least give you an idea.
Try to click file located in the solution expllorer and expand the properties tab to change 'copy to output directory' as 'Copy Always' . As I know VS copy to file to \bin\Debug folder every time when we run the project, so the relative path of that file will always be the same during development as well as after deployment.
After that below code will be enough
<app Settings
<add key="Configuration Path" value="Configuration.INI"/>
</app Settings

What's a consistent way of obtain AppSettings that accounts for applicationHost.config?

So, appSettings can be set in app.config, web.config, machine,config... But, when you work under IIS 7 you can also have appSettings being applied under applicationHost.config with a specific carve out for your site. So, what's a consistent way for me to know what AppSettings I should be using???
System.Configuration.ConfigurationManager is fine if this is a client profile.
System.Web.Configuration.WebConfigurationManager if this is a web-app ... well, maybe.
Microsoft.Web.Administration if I expect values in applicationHosting.config - ouch ... and even then they don't roll-up hierarchically so it seems that you're left holding that process.
Does anyone have a consistent approach to processing AppSettings that accounts for applicationHost.config?
You can't actually specify <appSettings> in your applicationHost.config file. This is because applicationHost.config defines settings specific to IIS only. You can review the applicationHost.config schema to confirm this:
%systemroot%\System32\inetsrv\config\schema\IIS_schema.xml
If you try to edit applicationHost.config and add an <appSetting> section to a site or under a <location path="..."> section you will get an error (IIS may not start and IIS MMC console will display a configuration error).
If you configure a global application setting in IIS manager this actually gets configured in the master web.config file that matches the default .NET Framework version setting in IIS.
<appSettings/> is specific to the .NET Framework and can only be configured in:
%SYSTEMROOT%\Microsoft.NET\Framework\[framework version]\CONFIG\machine.config
%SYSTEMROOT%\Microsoft.NET\Framework\[framework version]\CONFIG\web.config
%SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\CONFIG\machine.config
%SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\CONFIG\web.config
and of course your application's app.config or web.config files.
My advice would be to keep these settings local to your application unless there is the rare occasion where you need some value to be available globally.
Update:
Now that I understand your problem - you have multiple IIS sites which all point to the same physical folder - there is a way to approach this.
You could have a configuration table in your database that has a primary key of whatever the HTTP_HOST value is. This maps to a prefix, for example:
Host SitePrefix
==== ======
domain1.com D001
domain2.com D002
In your web.config:
In your application's Application_Start event in Global.asax.cs initialise an application wide value:
void Application_Start(object sender, EventArgs e)
{
// Code that runs on application startup
string httpHost = HttpContext.Current.Request.ServerVariables["HTTP_HOST"];
Application["SitePrefix"] = GetSiteKeyFromDb(httpHost);
}
This value will be available across the whole application but unique to the site.
When you need to read a setting that is specific to the site:
string siteSetting = ConfigurationManager.AppSettings[
HttpContext.Current.Application["SitePrefix"] + "_Setting1"
];
But if you're hitting the database in Application_Start then it may actually be expedient to store all these site specific settings in the database then read and cache them in Application instead of using <appSettings />.
I used the information provided by Anti-Santa's answer to accomplish this but I didn't want to parse the URL and have another database to look up information. The same codebase is used on-premise and I wouldn't have those pieces in that scenario.
Just add the appSettings to the .NET Framework web.config with a location node.
In %SYSTEMROOT%\Microsoft.NET\Framework64\[framework version]\Config\web.config, add the following where Site1 and Site2 are my two applications pointing to the same physical directory:
<?xml version="1.0" encoding="utf-8"?>
<!-- the root web configuration file -->
<configuration>
<!-- App settings for the different applications -->
<location path="Default Web Site/Site1">
<appSettings>
<add key="ConnectionString" value="the cnn str"/>
</appSettings>
</location>
<location path="Default Web Site/Site2">
<appSettings>
<add key="ConnectionString" value="the cnn str"/>
</appSettings>
</location>
...
</configuration>
The web.config in the physical folder will override this appSetting so I also needed to remove it from that file.