Search code examples
modulemanifestdotnetnuke

How do I make .dnn manifest file to create parent node in web.config for my child not if parent node doesn't exist?


I'm working on a DNN module. I need to edit web.config via .dnn manifest file. I need to add rule for url rewrite. I need it to look like this:

<rewrite>
  <rules>
    <rule name="rule1">
      {some content here}
    </rule>
    <rule name="rule2">
      {some content here}
    </rule>
  </rules>
</rewrite>

So main goal is actually to add 1 rule on install and delete it on module deletion. Here is the code from .dnn file that I tried first:

<component type="Config">
  <config>
    <configFile>web.config</configFile>
    <install>
      <configuration>
        <nodes>
          <!--<node path="/configuration/system.webServer" action="add" collision="overwrite">
            <rewrite>
              <rules>
              </rules>
            </rewrite>
          </node>-->

          <node path="/configuration/system.webServer/rewrite/rules" action="add" collision="overwrite">
            <rule name="rule1">
              {some content here}
            </rule>
          </node>
        </nodes>
      </configuration>
    </install>
    <uninstall>
      <configuration>
        <nodes>
          <node path="/configuration/system.webServer/rewrite/rules/rule[@name='rule1']" action="remove">
          </node>
        </nodes>
      </configuration>
    </uninstall>
  </config>
</component>

Problem is that if nodes "rewrite" and "rules" don't exist they are not created and nothing is happening at all on install.

So I tried to add the code that is commented above to create node "rewrite" and "rules" inside of it with collision="ignore" to avoid duplicates. But it doesn't work properly. If "rewrite/rules" exists and it contains already some rules - then DNN thinks that those nodes are different because the existing one contains children and the one that needs to be created has no children. And duplicated "rewrite" is created. Like this:

<rewrite>
  <rules>
    <rule name="rule_existing_before_module_install">
      {some content here}
    </rule>
    <rule name="rule_added_on_module_install">
      {some content here}
    </rule>
  </rules>
</rewrite>
<rewrite> <!--duplicated nod created by uncommented code-->
  <rules>
  </rules>
</rewrite>

If I try to add all the nodes at once by wrapping my rule inside "rewrite" and "rules" then it's not merged with existing "rewrite" but instead creates second one and I end up with web.config like this:

<rewrite>
  <rules>
    <rule name="rule1">
      {some content here}
    </rule>
  </rules>
</rewrite>
<rewrite>
  <rules>
    <rule name="rule2">
      {some content here}
    </rule>
  </rules>
</rewrite>

So eventually if there was a way to create "rewrite/rules" nodes on condition only if they don't exist and make it work both for node with and without children or make my "rewrite/rules" to merge with existing one - it would solve the problem. Tried to google - didn't find anything helpful for this case. Overwriting existing rules with mine and deleting existing rules is not an option. Currently I'm thinking of manual "rewrite/rules" creation and the rest to leave for module's .dnn manifest file but it's not the best option.

Any suggestions?

P.S. I tried to add existing tag "dnn-module" but editor doesn't find it in tag search for some reason. Maybe a bug because it exists but has no questions so far?


Solution

  • I don't believe that this scenario, is really the targeted goal, as not all installations will actually support this section. (Rewrites is an optional IIS feature, adding this section without it enabled will take a site down)

    As such, the current configuration merge functionality doesn't support this exact pathway as you are actually potentially introducing new features/breaking changes so the behavior that it only works with those sections existing is expected.

    If you feel that you MUST do this, you could use IUpgradable to have your own custom code modify this, but again, be aware if building for public consumption you run the risk of doing real harm to a site.