首页 > 解决方案 > 使用 C# 修改运行时 > 探测属性 web.config

问题描述

我在 IIS 上托管具有以下结构的应用程序:

IISAPP
  - bin
  - plugins
  - scripts
  - default1.aspx
  - web.config

在 Plugins 目录中,我在它自己的目录中托管了其他几个 ASPX 应用程序,因此结构如下所示:

IISAPP
  - bin
  - plugins
    - MyPlugin
      - bin
      - scripts
      - default2.aspx
      - web.config
  - scripts
  - default1.aspx
  - web.config

当我导航到http://IISAPP/时,会提供 default1.aspx 页面,这很棒。当我导航到http://IISAPP/plugins/MyPlugin/default2.aspx 时,该页面未提供服务,并且抱怨找不到 dll。这是因为插件应用程序正在寻找 bin 文件夹顶级应用程序中的 dll。

我继续添加<probing privatePath="plugins/MyPlugin/bin" />标签。这解决了提供 default2.aspx 的问题。

问题

这些插件将使用安装程序安装。我必须以某种方式更改该私有路径以包含所有文件夹。因此,如果我添加一个“MyPlugin2”,我将不得不将顶层 web.config 中的探测标记修改为<probing privatePath="plugins/MyPlugin/bin;plugins/MyPlugin/bin" />.

我需要使用 C# 修改部分元素privatePath内的以下 web.config 中的属性,然后保存配置文件。我尝试使用配置管理器执行此操作,但找不到正确的路径。当它看起来正确时,它会导致 null。probingruntime

我也玩过以下游戏:

var config = System.Xml.Linq.XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("~/Web.config"));
var runtimeNode = config.Root.Element("runtime").Element("assemblyBinding").Element("probing").Attribute("privatePath");

在这种情况下,文档会加载,但在我的一生中,我无法获得该 privatepath 值来更新它并保存配置。

我也尝试过XMLDocument,但由于 web.config 中的第 1 行,我无法加载 xml。我真的不想删除它,除此之外,解决方案感觉有点草率。

更新 我尝试了以下方法:

var config = System.Xml.Linq.XDocument.Load(System.Web.HttpContext.Current.Server.MapPath("~/Web.config"));
System.Xml.Linq.XElement runtimeNode = config.Root.Element("runtime");
System.Xml.Linq.XElement assemblyBindingNode = runtimeNode.Element("assemblyBinding");
System.Xml.Linq.XElement probingNode = assemblyBindingNode.Element("probing");
System.Xml.Linq.XAttribute att = probingNode.Attribute("privatePath");

att.Value = "new value";
config.Save(System.Web.HttpContext.Current.Server.MapPath("~/Web.config.xml"));

它适用于运行时节点。就像在运行时节点中找不到 assemblyBinding 节点一样。

网络配置

<?xml version="1.0"?>
<configuration>
  <configSections>
    <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
      <section name="MyProject.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
    </sectionGroup>
  </configSections>
  <appSettings>
    <add key="WebFilePath" value="D:\Web Solutions\WEB" />
  </appSettings>
  <system.web>
    <compilation debug="true" targetFramework="4.6.2"/>
    <httpRuntime targetFramework="4.5"/>
    <httpModules>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web"/>
    </httpModules>
  </system.web>
  <connectionStrings>
    <add name="DB" connectionString="" providerName="System.Data.SqlClient"/>
  </connectionStrings>
  <system.webServer>
    <handlers>
      <remove name="ExtensionlessUrlHandler-Integrated-4.0"/>
      <remove name="OPTIONSVerbHandler"/>
      <remove name="TRACEVerbHandler"/>
      <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="*" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0"/>
    </handlers>
    <validation validateIntegratedModeConfiguration="false"/>
    <modules>
      <remove name="ApplicationInsightsWebTracking"/>
      <add name="ApplicationInsightsWebTracking" type="Microsoft.ApplicationInsights.Web.ApplicationInsightsHttpModule, Microsoft.AI.Web" preCondition="managedHandler"/>
    </modules>
  </system.webServer>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-5.2.3.0" newVersion="5.2.3.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35"/>
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0"/>
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
        <bindingRedirect oldVersion="0.0.0.0-6.0.0.0" newVersion="6.0.0.0"/>
      </dependentAssembly>
      <probing privatePath="INeedToChangeThisValue" />
    </assemblyBinding>
  </runtime>
  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:6 /nowarn:1659;1699;1701"/>
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:14 /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+"/>
    </compilers>
  </system.codedom>
</configuration>

标签: c#asp.net

解决方案


看起来这是一个 xml 命名空间问题,使用XmlDocument. 我唯一担心的是,通常 ASP.Net 会在启动时进行程序集解析,这意味着您可能需要在设置privatePath我使用过的 之后重新启动应用程序ConfigurationManager.RefreshSection("runtime"),这可能会刷新该部分并使事情正常运行。

XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(Server.MapPath("~/web.config"));

XmlNamespaceManager nsmgr = new XmlNamespaceManager(xmlDoc.NameTable);
nsmgr.AddNamespace("ass", "urn:schemas-microsoft-com:asm.v1");

var probing = xmlDoc.SelectSingleNode("//runtime/ass:assemblyBinding/ass:probing", nsmgr) as XmlElement;
probing?.SetAttribute("privatePath", "bin;plugins/bin");

xmlDoc.Save(Server.MapPath("~/web.config"));

ConfigurationManager.RefreshSection("runtime");

推荐阅读