CZEMacLeod / MSBuild.SDK.SystemWeb

This MSBuild SDK is designed to allow for the easy creation and use of SDK (shortform) projects targeting ASP.NET 4.x using System.Web.
MIT License
151 stars 8 forks source link

It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level #75

Closed p74DDone closed 2 months ago

p74DDone commented 2 months ago

Hey & thanks for putting together what looks like it should be a perfect solution to my problem.

We've got an ASP.Net WebForms project in .NET 4.7.2 that has recently migrated to the SDK style. However since migrating to the SDK-style VS users have been unable to launch the application with an error about RunCommand not being defined.

I stumbled across a post saying to use this project instead and for the most part I got it working! I changed the project SDK tag to be "MSBuild.SDK.SystemWeb/4.0.88" and low and behold (with some tweaks to the launchSettings.json file) it all worked nicely again.

However, we use TeamCity for publishing the app using a web deploy with a publish profile using the following the msbuild command:

"MSBuild.exe" "C:\Projects\Etc\Project.sln" -p:Configuration=Release /m /p:DeployOnBuild=true /p:PublishProfile=WebDeploy.pubxml /p:DesktopBuildPackageLocation=C:\TeamCity\buildAgent3\work\21ab493d7c62fcd6\Published\Web "/p:Platform=Any CPU" /p:TreatWarningsAsErrors="true"

When this runs I got the error:

Could not open Source file: Could not find file 'C:\TeamCity\buildAgent3\work\21ab493d7c62fcd6\Etc\Web.config;Web.config'.

I found this SO post which lead to a post here, which resolved that issue. However, now I get a new error that I can't get to the bottom of:

MvcBuildViews: C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v temp -p C:> \Projects\Etc "C:\Projects\Etc\Project.sln" (default target) (1) -> "C:\Projects\Etc\Project.csproj" (default target) (30) -> (MvcBuildViews target) -> C:\Projects\Etc\obj\release\aspnetcompilemerge\source\web.config(96): error ASPCONFIG: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application level. This error can be caused by a virtual directory not being configured as an application in IIS. [C:\Projects\Etc\Project.csproj]

I don't know why it's complaining about IIS when generating the webdeploy, because it doesn't complain with the SDK style changes until I switch it over to MSBuild.SDK.SystemWeb.

I was wondering if anyone could potentially point me in the right direction as it feels like I'm so close to getting this working. In case it's related to Web.configs, the following are the files:

image

And in the csproj:

<Content Include="Web.config">
      <SubType>Designer</SubType>
    </Content>
        <None Update="Web.Debug.config">
      <DependentUpon>Web.config</DependentUpon>
      <SubType>Designer</SubType>
    </None>
    <None Update="Web.Release.config">
      <DependentUpon>Web.config</DependentUpon>
      <SubType>Designer</SubType>
    </None>
CZEMacLeod commented 2 months ago

Quickly I can tell you that you don't need any of the Web.config lines in the csproj file as the SDK takes care of all that for you. You should be able to pretty much remove all items from the project file and they should be picked up automatically.

Note - I do NOT recommend using <EnableWebFormsDefaultItems>false</EnableWebFormsDefaultItems>.

tomkerkhove commented 2 months ago

I see this as well, but sporadically

p74DDone commented 2 months ago

Quickly I can tell you that you don't need any of the Web.config lines in the csproj file as the SDK takes care of all that for you. You should be able to pretty much remove all items from the project file and they should be picked up automatically.

Note - I do NOT recommend using <EnableWebFormsDefaultItems>false</EnableWebFormsDefaultItems>.

I've removed all the web.config references in the csproj and I've removed EnableWebFormsDefaultItems. Note I was using:

`

false

`

However, changing that to true and removing the content includes doesn't fix it either.

So right now, unfortunately I am still getting an identical error. Is there anything else you can suggest I try?

leusbj commented 2 months ago

@p74DDone

Your build command/parameters appears to trigger a build and package/publish with a specific Publishing Profile (WebDeploy.pubxml) and so I suspect that the issue might be the convergence of three factors.

Can provide a few more details about your project? Specifically focus on the three areas described below:

PrecompileBeforePublish

Can you confirm that this publishing profile is set to have PreCompileBeforePublish (If you open the WebDeploy.pubxml in the editor does it contain lines like the following)?

<PrecompileBeforePublish>true</PrecompileBeforePublish>
<EnableUpdateable>true</EnableUpdateable>
<DebugSymbols>false</DebugSymbols>
<WDPMergeOption>DonotMerge</WDPMergeOption>

When you have this PreCompileBeforePublish it will utilize the $(IntermediateOutputPath)AspnetCompileMerge\Source aka obj\AspnetCompileMerge\Source directory to feed into the AspNetMergeCompiler.

MvcBuildViews

Can you confirm that you have not explicitly set the MvcBuildViews property in your .csproj with something like this <MvcBuildViews>false<MvcBuildViews>?

The default behavior for this SDK, is to set MvcBuildViews to true when in Release Configuration. This will execute several targets after the Afterbuild target (meaning also after the Package and AspNetPreCompile targets)

Config File allowDefinition

Can you confirm that your project root web.config either

Either of these in your project root web.config will cause aspnet compiler errors if ever copied to a subfolder (and will cause aspnet compiler errors for the MvcBuildView target even when in a subfolder of the "obj/")

The allowDefinition attribute when set in machine.config; applicationHost.config; Web.config can prevent lower nested web.config files from attempting to set certain configurations

p74DDone commented 2 months ago

Hey, everything is configured as above already:

PrecompileBeforePublish

    <PrecompileBeforePublish>true</PrecompileBeforePublish>
    <EnableUpdateable>false</EnableUpdateable>
    <DebugSymbols>false</DebugSymbols>
    <WDPMergeOption>DonotMerge</WDPMergeOption>

MvcBuildViews Can confirm this does not appear in the csproj file.

Config File allowDefinition Can confirm that the webc.config does not contain any section, or the words, allowDefinition.

Other Info

Is there anything else I can try or anything that would be helpful to provide? Here's the publish profile:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <WebPublishMethod>Package</WebPublishMethod>
    <SiteUrlToLaunchAfterPublish />
    <DesktopBuildPackageLocation>C:\Published\Package.zip</DesktopBuildPackageLocation>
    <PackageAsSingleFile>true</PackageAsSingleFile>
    <DeployIisAppPath>Default Web Site/EtcDemo</DeployIisAppPath>
    <PublishDatabaseSettings>
      <Objects xmlns="">
        <ObjectGroup Name="etcConnectionString" Order="1" Enabled="False">
          <Destination Path="" />
          <Object Type="DbDacFx">
            <PreSource Path="Data Source=.\;Initial Catalog=Etc.16;Integrated Security=True;Connect Timeout=30;TrustServerCertificate=True" includeData="False" />
            <Source Path="$(IntermediateOutputPath)AutoScripts\etcConnectionString_IncrementalSchemaOnly.dacpac" dacpacAction="Deploy" />
          </Object>
          <UpdateFrom Type="Web.Config">
            <Source MatchValue="Data Source=.\;Initial Catalog=Etc.16;Integrated Security=true;Connect Timeout=30;TrustServerCertificate=True;" MatchAttributes="$(UpdateFromConnectionStringAttributes)" />
          </UpdateFrom>
        </ObjectGroup>
        <ObjectGroup Name="redis" Order="8" Enabled="False">
          <Destination Path="" />
          <Object Type="DbDacFx">
            <PreSource Path="localhost:6379" includeData="False" />
            <Source Path="$(IntermediateOutputPath)AutoScripts\redis_IncrementalSchemaOnly.dacpac" dacpacAction="Deploy" />
          </Object>
          <UpdateFrom Type="Web.Config">
            <Source MatchValue="localhost:6379" MatchAttributes="$(UpdateFromConnectionStringAttributes)" />
          </UpdateFrom>
        </ObjectGroup>
      </Objects>
    </PublishDatabaseSettings>
    <LastUsedBuildConfiguration>Release</LastUsedBuildConfiguration>
    <LastUsedPlatform>Any CPU</LastUsedPlatform>
    <ExcludeApp_Data>false</ExcludeApp_Data>
    <LaunchSiteAfterPublish>false</LaunchSiteAfterPublish>
    <CopyAllFilesToSingleFolderForMsdeployDependsOn>CustomCollectFiles;
      ;</CopyAllFilesToSingleFolderForMsdeployDependsOn>
    <PrecompileBeforePublish>true</PrecompileBeforePublish>
    <EnableUpdateable>false</EnableUpdateable>
    <DebugSymbols>false</DebugSymbols>
    <WDPMergeOption>DonotMerge</WDPMergeOption>
  </PropertyGroup>
  <PropertyGroup>
    <OnBeforePackageUsingManifest>AddCustomSkipRules</OnBeforePackageUsingManifest>
  </PropertyGroup>
  <Target Name="AddCustomSkipRules">
    <ItemGroup>
      <MsDeploySkipRules Include="SkipDownloadsFiles">
        <SkipAction>Delete</SkipAction>
        <ObjectName>filePath</ObjectName>
        <AbsolutePath>.*\\Exports\\.*$</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
      <MsDeploySkipRules Include="SkipUploadsFolderDirectories">
        <SkipAction>Delete</SkipAction>
        <ObjectName>dirPath</ObjectName>
        <AbsolutePath>.*\\Uploads\\</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
      <MsDeploySkipRules Include="SkipUploadsFolderFiles">
        <SkipAction>Delete</SkipAction>
        <ObjectName>filePath</ObjectName>
        <AbsolutePath>.*\\Uploads\\.*$</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
      <MsDeploySkipRules Include="SkipLicenceFile">
        <SkipAction>Update</SkipAction>
        <ObjectName>filePath</ObjectName>
        <AbsolutePath>.*\\licence.lic</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
      <MsDeploySkipRules Include="SkipCustomImages">
        <SkipAction>Delete</SkipAction>
        <ObjectName>filePath</ObjectName>
        <AbsolutePath>.*\\Images\\Custom\\.*$</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
      <MsDeploySkipRules Include="SkipAvatarImages">
        <SkipAction>Delete</SkipAction>
        <ObjectName>filePath</ObjectName>
        <AbsolutePath>.*\\Images\\FollowableAvatars\\.*$</AbsolutePath>
        <XPath>
        </XPath>
      </MsDeploySkipRules>
        <MsDeploySkipRules Include="SkipAvatarImages">
            <SkipAction>Delete</SkipAction>
            <ObjectName>filePath</ObjectName>
            <AbsolutePath>.*\\Images\\FollowableAvatars\\.*$</AbsolutePath>
            <XPath>
            </XPath>
        </MsDeploySkipRules>
    </ItemGroup>
  </Target>
  <Target Name="CustomCollectFiles">
    <ItemGroup>
      <_CustomFiles Include="bin\Package.Api.xml" />
      <_CustomFiles Include="bin\Package.Api.Models.xml" />
      <FilesForPackagingFromProject Include="%(_CustomFiles.Identity)">
        <DestinationRelativePath>bin\%(Filename)%(Extension)</DestinationRelativePath>
      </FilesForPackagingFromProject>
    </ItemGroup>
  </Target>
  <ItemGroup>
    <MSDeployParameterValue Include="$(DeployParameterPrefix)redis-Web.config Connection String" />
    <MSDeployParameterValue Include="$(DeployParameterPrefix)etcConnectionString-Web.config Connection String" />
  </ItemGroup>
</Project>

Final note Something that is a bit odd is that it actually seems to generate all the publish files as expected. I haven't tested the installed output, but from a cursory check, all the files are generated and I can install it using the usual "projectname.webdeploy /y" command.

p74DDone commented 2 months ago

Going through the command line log, it is successfully doing what I want it to do, but it then runs another MvcBuildViews thing which errors (note this project is a legacy project using WebForms, not MVC in case that's relevant):

Successfully executed Web deployment task. Package "Project.zip" is successfully created as single file at the following location: file:///C:/TeamCity/buildAgent3/work/21ab493d7c62fcd6/Published/Web To get the instructions on how to deploy the web package please visit the following link: https://go.microsoft.com/fwlink/?LinkId=124618 GenerateSampleDeployScript: Sample script for deploying this package is generated at the following location: C:\TeamCity\buildAgent3\work\21ab493d7c62fcd6\Published\Web\Etc.deploy.cmd For this sample script, you can change the deploy parameters by changing the following file: C:\TeamCity\buildAgent3\work\21ab493d7c62fcd6\Published\Web\Etc.SetParameters.xml PipelineDeployPhase: Publish Pipeline Deploy Phase CleanupForBuildMvcViews: SNIP - Lots of file deletions MvcBuildViews: C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_compiler.exe -v temp -p C:\Projects\Project\etc 30>C:\Projects\Point74\RP\RP2-1\Etc\obj\release\aspnetcompilemerge\source\web.config(96): error ASPCON FIG: It is an error to use a section registered as allowDefinition='MachineToApplication' beyond application lev el. This error can be caused by a virtual directory not being configured as an application in IIS. [C:\Projects \Project\Etc\Etc.csproj] 30>Done Building Project "C:\Projects\Project\Etc\Etc.csproj" (default targets) -- FAILED. 1>Done Building Project "C:\Projects\Project\Etc\Etc.sln" (default targets) -- FAILED.

So there's a final step that's occurring here after it's successfully compiled and published the zip file which then errors.

leusbj commented 2 months ago

@p74DDone Thanks for confirming my suspicion that it is the MvcBuldViews step that is failing and that you had configured your publish profile to perform the precompile. You are correct that it would only ever happens during "Release" configuration builds.. This SDK enables MvcBuildViews when in "Release" configuration, so it isn't happening during "Debug"

The MvcBuildViews can be helpful for providing quick developer feedback when some code will error out during aspnet compilation. But it is not mandatory, and none of that step's output are included in the final build output.

You can disable it across the board (both local development and CICD Builds) by adding this into your "Etc.csproj"

<PropertyGroup>
  <MvcBuildViews>false</MvcBuildViews>
</PropertyGroup>

Or you might use a conditional to disable it only on your teamcity CI/CD builds

p74DDone commented 2 months ago

That seems to be working nicely now! Thanks for the help.