Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Nested Web.config files are not treated as Content for publishing and transforming #83

Open
julealgon opened this issue Oct 7, 2024 · 4 comments

Comments

@julealgon
Copy link

As I switch our old WebForms projects to leverage publishing, I noticed that only the root web.config files are properly considered for deployment, transformed and copied on publish, while web.config files inside of other folders in the project (used usually for setting Location-based permissions) are completely ignored.

I believe it should be possible to treat these nested web.config files the same way as the root one so that they properly participate in the publishing pipeline.

I've not yet worked around this issue, so suggestions on how to do so besides manually marking each individual file as Content in Visual Studio are welcome.

@CZEMacLeod
Copy link
Owner

CZEMacLeod commented Oct 8, 2024

You probably want something like

<ItemGroup>
    <Content Include="**\Web.config" Exclude="Web.config" />
</ItemGroup>

This is one of the advantages of the SDK style project.

I would always use a location tag in the root web.config, instead of one in each folder, as otherwise you may end up with odd behavior as not all information is inherited. There is some special stuff in place for razor views where you need a customized web.config in the Views folder already in the Razor SDK.

<location path="some/plugin/location/handler.ashx">
  <system.web>
    <httpRuntime maxRequestLength="1048576" executionTimeout="600" />
  </system.web>
  <system.webServer>
    <security>
      <requestFiltering>
        <!-- 500MB in bytes, default is 30000000 or approx. 28.6102 Mb-->
        <requestLimits maxAllowedContentLength="1073741824" />
      </requestFiltering>
    </security>
  </system.webServer>
</location>
<location path="some/plugin2/location/otherhandler.ashx">
  <system.web>
    <pages validateRequest="false" />
    <httpRuntime requestValidationMode="2.0" executionTimeout="600" />
  </system.web>
</location>

Use the location element in the Web.config file

@julealgon
Copy link
Author

You probably want something like

<ItemGroup>
    <Content Include="**\Web.config" Exclude="Web.config" />
</ItemGroup>

This appears to have done the trick, thanks!

Do you know what would be needed to also support transformations on these non-root web.config files? I assume just the above is not enough?

I would always use a location tag in the root web.config, instead of one in each folder, as otherwise you may end up with odd behavior as not all information is inherited.

Thanks for the advice, but this would not scale well for this particular project. This is a legacy WebForms project with over a thousand pages in a multitude of folders, and we have permission management everywhere. If we concentrated all of them in the main file (or even if it was isolated in a dedicated file linked via configSource, it would be completely unmaintainable, especially as this project has multiple feature teams handling it at the same time each with their own pages and folders.

Having native support for these nested web.config files would be really nice for this use case.

@CZEMacLeod
Copy link
Owner

Do you know what would be needed to also support transformations on these non-root web.config files? I assume just the above is not enough?

Are you talking about including publish profile transforms for msdeploy, or configuration transforms like debug / release etc?
The section of the SDK that deals with this is

<ItemGroup Condition="'$(EnableWebFormsDefaultItems)'=='true'">
<Content Include="Web.config" />
<_WebConfigConfigurations Include="$(Configurations)" />
<None Include="@(_WebConfigConfigurations->'Web.%(Identity).config')">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.BindingRedirects.config" Condition="EXISTS('Web.BindingRedirects.config')">
<DependentUpon>Web.config</DependentUpon>
</None>
<!-- Altered web.*.config inclusion so these items will be in the WebDeploy Package
Where they can be used at deployment time for Environment Specific Transformation
https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/issues/43
-->
<Content Include="Web.*.config" Exclude="@(None)" />
</ItemGroup>

You might be able to something along the lines of

  <ItemGroup Condition="'$(EnableWebFormsDefaultItems)'=='true'">
    <Content Include="**\Web.config" />
    <None Include="@(_WebConfigConfigurations->'**\Web.%(Identity).config')">
      <DependentUpon>%(RelativeDir)\Web.config</DependentUpon>
    </None>
    <Content Include="**\Web.*.config" Exclude="@(None)" />
  </ItemGroup>

Thanks for the advice, but this would not scale well for this particular project. This is a legacy WebForms project with over a thousand pages in a multitude of folders, and we have permission management everywhere. If we concentrated all of them in the main file (or even if it was isolated in a dedicated file linked via configSource, it would be completely unmaintainable, especially as this project has multiple feature teams handling it at the same time each with their own pages and folders.

Fair enough. As I said - it should work - but I've had issues with this approach in non-sdk projects, let alone with the hacks the SDK does. If you get it to work for you, all the better.

Having native support for these nested web.config files would be really nice for this use case.
You might need to tweak the DependentUpon line above, but refer to https://learn.microsoft.com/en-us/visualstudio/msbuild/msbuild-well-known-item-metadata?view=vs-2022 if what I gave doesn't work.

You might need to adjust the line to be something like
<None Include="@(_WebConfigConfigurations->'**\Web.%(Identity).config')" Condition="EXISTS('@(_WebConfigConfigurations->'**\Web.%(Identity).config')'"> to work around #67 or you could implement something like the fix in #68

@julealgon
Copy link
Author

Do you know what would be needed to also support transformations on these non-root web.config files? I assume just the above is not enough?

Are you talking about including publish profile transforms for msdeploy, or configuration transforms like debug / release etc? The section of the SDK that deals with this is

<ItemGroup Condition="'$(EnableWebFormsDefaultItems)'=='true'">
<Content Include="Web.config" />
<_WebConfigConfigurations Include="$(Configurations)" />
<None Include="@(_WebConfigConfigurations->'Web.%(Identity).config')">
<DependentUpon>Web.config</DependentUpon>
</None>
<None Include="Web.BindingRedirects.config" Condition="EXISTS('Web.BindingRedirects.config')">
<DependentUpon>Web.config</DependentUpon>
</None>
<!-- Altered web.*.config inclusion so these items will be in the WebDeploy Package
Where they can be used at deployment time for Environment Specific Transformation
https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/issues/43
-->
<Content Include="Web.*.config" Exclude="@(None)" />
</ItemGroup>

You might be able to something along the lines of

  <ItemGroup Condition="'$(EnableWebFormsDefaultItems)'=='true'">
    <Content Include="**\Web.config" />
    <None Include="@(_WebConfigConfigurations->'**\Web.%(Identity).config')">
      <DependentUpon>%(RelativeDir)\Web.config</DependentUpon>
    </None>
    <Content Include="**\Web.*.config" Exclude="@(None)" />
  </ItemGroup>

I was referring to the normal transforms, using Web.Debug.config/Web.Release.config etc. We are currently not doing any XML transforms on non-root web.config files, but I know they are supposed to work on the legacy project format. If someone could implement that in this SDK it would be more complete/closer to the full capabilities of the legacy project.

Perhaps your suggestions above could help someone implementing it directly in the SDK.

Your initial suggestion unblocked me to get our publish pipeline going, but I added it to our project with a note in hopes that this is implemented as part of the SDK in the future and we can then remove the customization:

  <ItemGroup>
    <!-- 
      HACK: 
      
      Adds all nested `web.config` files manually. Ideally, this should be handled by the SDK, but it only
      considers the root `web.config` file at the moment.
      
      More information here:
      - https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/issues/83
    -->
    <Content Include="**\Web.config" Exclude="Web.config" />
  </ItemGroup>

Thankfully we've only had to add this to a single project thus far out of the 8 projects we have currently using this SDK.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants