How can I iterate through file names in the 'Default Document' IIS feature for an application in C#?
I am using Microsoft.Web.Administration.ServerManager.
Thanks
You can do it using its "loosely" typed model, basically for reading it for Default Web Site would look like:
using (ServerManager serverManager = new ServerManager())
{
Configuration webConfig = serverManager.GetWebConfiguration("Default Web Site");
ConfigurationSection section = webConfig.GetSection("system.webServer/defaultDocument");
foreach (ConfigurationElement item in section.GetCollection("files"))
{
Console.WriteLine(item["value"]);
}
}
You can also generate strongly-typed wrappers for collections and entries you want to use frequently which makes it a lot cleaner and prevents mistakes, that would make it look like:
using (ServerManager serverManager = new ServerManager())
{
Configuration webConfig = serverManager.GetWebConfiguration("Default Web Site");
DefaultDocumentSection section = (DefaultDocumentSection)webConfig.GetSection("system.webServer/defaultDocument", typeof(DefaultDocumentSection));
foreach (FileElement item in section.Files)
{
Console.WriteLine(item.Value);
}
}
And for that to work you need the following "strongly-typed-wrappers":
public class DefaultDocumentSection : ConfigurationSection
{
private FilesCollection _files;
public FilesCollection Files
{
get
{
if (_files == null)
{
_files = (FilesCollection)base.GetCollection("files", typeof(FilesCollection));
}
return _files;
}
}
}
public class FilesCollection : ConfigurationElementCollectionBase<FileElement>
{
protected override FileElement CreateNewElement(string elementTagName)
{
return new FileElement();
}
}
public class FileElement : ConfigurationElement
{
public string Value { get { return (string)base["value"]; } }
}
Related
Visual Studio has the option to apply a Build Action for the App.config file as "Embedded Resource", which means including in the same final exe the content of the App.config.
Fine.
The problem is: how to read the data inside the embedded App.config? For example an appSetting value from a given key?
The code I used before to read from the App.config (the one phisically written on the disk which usually is nameoftheprogram.exe.config), seems to be not working anymore.
string s = System.Configuration.ConfigurationManager.AppSettings["mykey"];
Probably it must be re-adapted with other C# classes designed for this job.
Any ideas?
You can have interface IConfigUtility with method :
IConfigUtility.cs:
public interface IConfigUtility
{
string LogFilePath
{
get;
}
string GetAppSetting(string key);
}
ConfigUtility.cs
using System;
using System.Configuration;
public class ConfigUtility : IConfigUtility
{
Configuration config = null;
public string LogFilePath
{
get
{
return GetAppSetting(#"Code to read the log file path");
}
}
public ConfigUtility()
{
var exeConfigPath = this.GetType().Assembly.Location;
try
{
config = ConfigurationManager.OpenExeConfiguration(exeConfigPath);
}
catch (Exception)
{
//handle error here.. means DLL has no satellite configuration file.
}
}
public virtual string GetAppSetting(string key)
{
if (config != null)
{
KeyValueConfigurationElement element = config.AppSettings.Settings[key];
if (element != null)
{
string value = element.Value;
if (!string.IsNullOrEmpty(value))
return value;
}
}
return string.Empty;
}
}
Now you can use the above ConfigUtility.cs and read your appsettings key from the App.config file
I'm trying to make a simple plugin system in which a plugins are dynamically loaded from .dll files on application's startup and show up in the UI.
This Answer seems to be exactly what I'm looking for. It uses MEF to load the plugins. I tried to create a simple project and follow the instructions. My solution has the following structure:
MeftTest (contains main MefTest.exe, references only MefTest.SDK and not plugins)
MefTest.SDK (contains the IPlugin.cs and IPluginViewModel.cs and the Engine.cs which loads the plugins from the application's directory)
MefTest.Plugin1 (contains first plugin, references MefTest.SDK)
MefTest.Plugin2 (contains second plugin, references MefTest.SDK)
MefTest.SDK -> IPlugin.cs
public interface IPlugin
{
IPluginViewModel ViewModel { get; }
ResourceDictionary View { get; }
string Title { get; }
}
MefTest.SDK -> Engine.cs
public class Engine
{
[ImportMany]
private IEnumerable<IPlugin> plugins { get; set; }
public async Task<ObservableCollection<IPlugin>> GetPlugins()
{
try
{
var folder = AppDomain.CurrentDomain.BaseDirectory;
var catalog = new AggregateCatalog();
//catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly()));
catalog.Catalogs.Add(new DirectoryCatalog(folder));
var container = new CompositionContainer(catalog);
container.ComposeParts(this);
var result = new ObservableCollection<IPlugin>();
foreach (var p in plugins)
{
result.Add(p);
}
return result;
}
catch (Exception ex)
{
//I get the exception here...
var t = ex;
throw;
}
}
}
MefTest.Plugin1 -> Plugin1.cs
[Export(typeof(IPlugin))]
public class Plugin1 : IPlugin
{
private MainViewModel viewModel { get; set; }
public IPluginViewModel ViewModel
{
get { return viewModel; }
}
public ResourceDictionary View
{
get { return viewDictionary; }
}
private ResourceDictionary viewDictionary = new ResourceDictionary();
public string Title
{
get { return "Plugin 1"; }
}
[ImportingConstructor]
public Plugin1()
{
//I get the error here. tried both of these, none of them work
viewDictionary.Source =
// new Uri("pack://application:,,,/MefTest.Plugin1;component/views/main.xaml", UriKind.Absolute);
new Uri("/MefTest.Plugin1;component/views/main.xaml",
UriKind.Relative);
}
public override string ToString()
{
return Title;
}
}
however, I get the error Could not load file or assembly 'MefTest.Plugin1.dll, Culture=neutral' or one of its dependencies. The system cannot find the file specified.
The Main.xaml file is in MefTest.Plugin1\Views\Main.xaml folder. Output type of the project is ClassLibrary and Build Action of the xaml file is Page.
PS: I tried to reference the plugin directly and add it without the MEF (Plugins.Add(new Plugin3.Plugin3());) and it still threw the same exception. So I don't think the problem is with the MEF part of the solution.
How can I fix this? Also, is there a better option to this approach?
i do it this way in an xbap application...to retreive distant xaml. Try to do the same with your local resourtce
private ResourceDictionary LoadDictionary(string source)
{
Stream streamInfo = null;
ResourceDictionary dictionary = null;
try
{
streamInfo = DistantManager.Instance.GetResource(source);
if (streamInfo != null)
{
Uri baseUri = DistantManager.Instance.GetUri(source);
dictionary = XamlReader.Load(streamInfo) as ResourceDictionary;
dictionary.Source = baseUri;
}
}
catch (Exception e)
{
BusinessLogger.Manage(e);
return null;
}
return dictionary;
}
something like
Uri baseUri = new Uri(Mysource);
dictionary = XamlReader.Load(XXXX) as ResourceDictionary;
dictionary.Source = baseUri;
but on the other hand I do not understand why you want a ResourceDictionary as your plugin view...? just create the plugin user control ??
I've been trying to create some custom check-in policies in TFS 2010 recently, I created a DLL and added a registry key as outlined in the following link:
https://msdn.microsoft.com/en-us/library/bb668980.aspx
(Note: I already know this link is retired, but I'm unable to do it in the updated fashion indicated here: http://blogs.msdn.com/b/jimlamb/archive/2010/03/31/how-to-implement-package-and-deploy-custom-check-in-policy-for-tfs-2010.aspx)
I didn't necessarily expect my own DLL to work correctly from the start in a functional sense, but Step 4 only shows the out of the box policies, mine is not available.
What could be causing mine to not appear? Below is the code I'm using (I've removed what it actually does as I don't think that's important)
[Serializable]
public class CheckInPolicy : PolicyBase
{
private string _status = string.Empty;
public override string Description
{
get { return "My description"; }
}
public override string Type
{
get { return "My type"; }
}
public override string TypeDescription
{
get { return "My type description"; }
}
public override bool Edit(IPolicyEditArgs policyEditArgs)
{
return true;
}
public override PolicyFailure[] Evaluate()
{
// Check if the check in meets the policy rules
// ...
// ...
// ...
}
public override void Activate(PolicyFailure failure)
{
base.Activate(failure);
}
public override void DisplayHelp(PolicyFailure failure)
{
MessageBox.Show(
"My policy help notification", "Policy Help");
}
}
This link mentioned that the policy needs to be placed in a different registry path if the OS is x64, but the server I'm using is a 32-bit Windows Server 2003 machine. The key is placed in:
[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\9.0\TeamFoundation\SourceControl\Checkin Policies]
I guess you have a 64-bit machine, in that case the correct registry entry would be the 32-bit path:
[HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\VisualStudio\11.0\TeamFoundation\SourceControl\Checkin Policies
In addition to this, you usually need to build the Policy for each version of Visual Studio, as it also has references to the appropriate TeamExplorer libraries.
EDIT:
You can prohibit developers from overriding policies, if you extend your server side with a plugin, that declines all checkins with overridden policies.
You need to place the DLL under this TFS path (of course depending on your version):
Program Files\Microsoft Team Foundation Server 11.0\Application Tier\Web Services\bin\Plugins\
Here the code of this plugin class (some of the referenced DLLs can only be found on TFS servers). We allow to override if all files are in published folder, but you can of course define your own exclusions:
using System;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Server;
using Microsoft.TeamFoundation.VersionControl.Server;
using System.IO;
using System.Text.RegularExpressions;
using Microsoft.TeamFoundation.Framework.Server.Alm;
namespace TFS.CheckinPolicyOverrideEventHandler
{
public sealed class CheckinPolicyOverrideEventHandler : ISubscriber
{
public Type[] SubscribedTypes()
{
return new Type[1] { typeof(CheckinNotification) };
}
public EventNotificationStatus ProcessEvent(TeamFoundationRequestContext requestContext, NotificationType notificationType, object notificationEventArgs,
out int statusCode, out string statusMessage, out ExceptionPropertyCollection properties)
{
statusCode = 0;
properties = null;
statusMessage = String.Empty;
try
{
if (notificationType == NotificationType.DecisionPoint && notificationEventArgs is CheckinNotification)
{
CheckinNotification ev = notificationEventArgs as CheckinNotification;
if (ev != null && ev.PolicyOverrideInfo != null)
{
if (ev.PolicyOverrideInfo.PolicyFailures != null)
{
// One or more of the checkin policies have been overridden
// If all the files being checked in are in the published folder, then allow overridding the policies since those are installation packages
foreach (string file in ev.GetSubmittedItems(null))
{
if (!Regex.IsMatch(file, #"/published", RegexOptions.IgnoreCase) &&
!Regex.IsMatch(Path.GetDirectoryName(file), #"/published", RegexOptions.IgnoreCase))
{
statusCode = -1;
break;
}
}
if (statusCode != 0)
{
// One or more of the checkin policies have been overridden and not all files are installation files (in the published folder)
statusMessage = Resource.CheckinCancelledStatusMessage;
foreach (PolicyFailureInfo policy in ev.PolicyOverrideInfo.PolicyFailures)
{
statusMessage = String.Concat(statusMessage, "\n > ", policy.PolicyName, ": ", policy.Message);
}
return EventNotificationStatus.ActionDenied;
}
}
}
return EventNotificationStatus.ActionPermitted;
}
}
catch (Exception exception)
{
// decide what you want to do, if exception occurs
}
return EventNotificationStatus.ActionPermitted;
}
public string Name
{
get { return "TFS.CheckinPolicyOverrideEventHandler"; }
}
public SubscriberPriority Priority
{
get { return SubscriberPriority.Normal; }
}
}
}
I have localized MVC according to Nadeem Afana's blog and using a script translator similar to Mads Kristensen's blog. The problem is that bundles are registered in Application_Start method. This causes the scripts are translated in one - default - language and stored in the browser/server cache. Changing the language/culture will not generate their linguistic equivalent. Is it possible to implement a cache profile VaryByCustom = "culture" similarly to Views? Is there any better practice/solution? Is it possible to use HTML5 Application Cache with translated scripts?
Script translator class:
public class ScriptTranslator : IBundleTransform {
public ScriptTranslator(ResourceManager manager) {
RM = manager;
}
public void Process(BundleContext context, BundleResponse response) {
response.Content = TranslateScript(response.Content);
}
private static ResourceManager RM;
private static Regex REGEXP = new Regex( #"translate\(""([^\))]*)""\)", RegexOptions.Singleline | RegexOptions.Compiled);
private string TranslateScript(string text) {
MatchCollection matches = REGEXP.Matches(text);
foreach (Match key in matches) {
object obj = RM.GetObject(kay.Groups[1].Value);
if (obj != null) {
text = text.Replace(kay.Value, CleanText(obj.ToString()));
}
}
return text;
}
private static string CleanText(string text) {
return string.Format("\"{0}\"", text.Replace("\\", "\\\\"));
}
}
Resource files using Custom tool namespace Resources.Javascript; My bundle config is:
public class BundleConfig {
public static void RegisterBundles(BundleCollection bundles) {
var DEFAULT_SCRIPT_PATH = "~/Scripts/Modules/";
var DEFAULT_SCRIPT_BOUNDLE_PATH = "~/ScriptBundles/";
var mainBoundle = new ScriptBundle(DEFAULT_SCRIPT_BOUNDLE_PATH + "main")
.Include(DEFAULT_SCRIPT_PATH + "test.js");
mainBoundle.Transforms.Clear();
mainBoundle.Transforms.Add(new ScriptTranslator(Resources.JavaScript.test.ResourceManager));
mainBoundle.Transforms.Add(new JsMinify());
bundles.Add(mainBoundle);
}
}
Our solution for this problem was not only to store different bundles by controller/action combination but also by CurrentUICulture.
string.Format("scriptsDependency{0}{1}_{2}", controler, action, Thread.CurrentThread.CurrentUICulture.Name);
I also recommend to store static libraries like JQuery or Bootstrap. But for dynamic content i would recommend NoCache policy.
public class NonCacheableTransformer : IBundleTransform
{
public void Process(BundleContext context, BundleResponse response)
{
context.UseServerCache = false;
response.Cacheability = HttpCacheability.NoCache;
}
}
I want to use a custom path for a user.config file, rather than have .NET read it from the default location.
I am opening the file like this:
ExeConfigurationFileMap configMap = new ExeConfigurationFileMap();
configMap.ExeConfigFilename = String.Format("{0}\\user.config",AppDataPath);
Configuration config = ConfigurationManager.OpenMappedExeConfiguration(configMap, ConfigurationUserLevel.PerUserRoamingAndLocal);
But I can't figure out how to actually read settings out of it, I get a compile error saying that the values are inaccessible when I try to get a value through AppData or ConfigurationSection.
Do I need to create some sort of a wrapper class to consume the data properly?
I was recently tasked with a similar problem, I had to change the location of where settings files were read from the default location in AppData to the Application directory. My solution was to create my own settings files that derived from ApplicationSettingsBase which specified a custom SettingsProvider. While the solution felt like overkill at first, I've found it to be more flexible and maintainable than I had anticipated.
Update:
Sample Settings File:
public class BaseSettings : ApplicationSettingsBase
{
protected BaseSettings(string settingsKey)
{ SettingsKey = settingsKey.ToLower(); }
public override void Upgrade()
{
if (!UpgradeRequired)
return;
base.Upgrade();
UpgradeRequired = false;
Save();
}
[SettingsProvider(typeof(MySettingsProvider)), UserScopedSetting]
[DefaultSettingValue("True")]
public bool UpgradeRequired
{
get { return (bool)this["UpgradeRequired"]; }
set { this["UpgradeRequired"] = value; }
}
}
Sample SettingsProvider:
public sealed class MySettingsProvider : SettingsProvider
{
public override string ApplicationName { get { return Application.ProductName; } set { } }
public override string Name { get { return "MySettingsProvider"; } }
public override void Initialize(string name, NameValueCollection col)
{ base.Initialize(ApplicationName, col); }
public override void SetPropertyValues(SettingsContext context, SettingsPropertyValueCollection propertyValues)
{
// Use an XmlWriter to write settings to file. Iterate PropertyValueCollection and use the SerializedValue member
}
public override SettingsPropertyValueCollection GetPropertyValues(SettingsContext context, SettingsPropertyCollection props)
{
// Read values from settings file into a PropertyValuesCollection and return it
}
static MySettingsProvider()
{
appSettingsPath_ = Path.Combine(new FileInfo(Application.ExecutablePath).DirectoryName, settingsFileName_);
settingsXml_ = new XmlDocument();
try { settingsXml_.Load(appSettingsPath_); }
catch (XmlException) { CreateXmlFile_(settingsXml_); } //Invalid settings file
catch (FileNotFoundException) { CreateXmlFile_(settingsXml_); } // Missing settings file
}
}
A few improvements:
1) Load it up a bit simpler, no need for the other lines:
var config = ConfigurationManager.OpenExeConfiguration(...);
2) Access AppSettings properly:
config.AppSettings.Settings[...]; // and other things under AppSettings
3) If you want a custom configuration section, use this tool: http://csd.codeplex.com/
I never ended up getting the Configuration Manager approach working. After spending a half day muddling with no progress, I decided to roll my own solution as my needs are basic.
Here is the solution I came up with in the end:
public class Settings
{
private XmlDocument _xmlDoc;
private XmlNode _settingsNode;
private string _path;
public Settings(string path)
{
_path = path;
LoadConfig(path);
}
private void LoadConfig(string path)
{
//TODO: add error handling
_xmlDoc = null;
_xmlDoc = new XmlDocument();
_xmlDoc.Load(path);
_settingsNode = _xmlDoc.SelectSingleNode("//appSettings");
}
//
//use the same structure as in .config appSettings sections
//
public string this[string s]
{
get
{
XmlNode n = _settingsNode.SelectSingleNode(String.Format("//add[#key='{0}']", s));
return n != null ? n.Attributes["value"].Value : null;
}
set
{
XmlNode n = _settingsNode.SelectSingleNode(String.Format("//add[#key='{0}']", s));
//create the node if it doesn't exist
if (n == null)
{
n=_xmlDoc.CreateElement("add");
_settingsNode.AppendChild(n);
XmlAttribute attr =_xmlDoc.CreateAttribute("key");
attr.Value = s;
n.Attributes.Append(attr);
attr = _xmlDoc.CreateAttribute("value");
n.Attributes.Append(attr);
}
n.Attributes["value"].Value = value;
_xmlDoc.Save(_path);
}
}
}