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

Unable to get Web API 2 to debug using MSBuild.SDK.SystemWeb #41

Closed gortok closed 2 years ago

gortok commented 2 years ago

I have the following ASP.NET Web API 2 project set up that has been converted over to the Sdk style using the MSBuild.SDK.SystemWeb.

<Project Sdk="MSBuild.SDK.SystemWeb/4.0.79">
  <Import Sdk="Microsoft.NET.Sdk.Publish" Project="Sdk.props" />
  <PropertyGroup>
    <TargetFramework>net472</TargetFramework>
    <UseIISExpress>true</UseIISExpress>
    <Use64BitIISExpress></Use64BitIISExpress>
    <IISExpressSSLPort />
    <IISExpresAnonymousAuthentication>disabled</IISExpressAnonymousAuthentication>
    <IISExpressWindowsAuthentication>enabled</IISExpressWindowsAuthentication>
     <IISExpressUseClassicPipelineMode></IISExpressUseClassicPipelineMode>
    <GenerateAssemblyInfo>false</GenerateAssemblyInfo>
  </PropertyGroup>
  <ItemGroup>
    <ProjectCapability Include="Web" />
    <ProjectCapability Include="DotNetCoreWeb" />
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Microsoft.AspNet.Cors" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Client" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Core" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Cors" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.Own" Version="5.2.7" />
    <PackageReference Include="Microsoft.AspNet.WebApi.WebHost" Version="5.2.7" />
    <PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="2.0.1" GeneratePathProperty="true" />
    <PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
    <PackageReference Include="Microsoft.Net.Http" Version="2.2.29" />
    <PackageReference Include="Microsoft.Owin" Version="4.0.1" />
    <PackageReference Include="Microsoft.Owin.Cors" Version="4.0.1" />
    <PackageReference Include="Microsoft.Owin.Host.SystemWeb" Version="4.0.1" />
    <PackageReference Include="Microsoft.Owin.Security" Version="4.0.1" />
    <PackageReference Include="Microsoft.Owin.Security.Jwt" Version="4.0.1" />
    <PackageReference Include="Microsoft.Owin.Security.OAuth" Version="4.0.1" />
    <PackageReference Include="Owin" Version="1.0" />
    <PackageReference Include="System.Buffers" Version="4.5.1" />
    <PackageReference Include="System.ComponentModel.Annotations" Version="4.7.0" />
    <PackageReference Include="System.Configuration.ConfigurationManager" Version="4.7.0" />
    <PackageReference Include="System.Memory" Version="4.5.4" />
    <PackageReference Include="System.Numerics.Vectors" Version="4.5.0" />
    <PackageReference Include="System.Runtime.CompilerServices.Unsafe" Version="5.0.0" />
    <PackageReference Include="System.Security.AccessControl" Version="4.7.0" />
    <PackageReference Include="System.Security.Permissions" Version="4.7.0" />
    <PackageReference Include="System.Security.Principal.Windows" Version="4.7.0" />
    <PackageReference Include="System.ValueTuple" Version="4.5.0" />
    <PackageReference Include="ValueInjecter" Version="3.1.3" />
  </ItemGroup>
  <ItemGroup>
    <Reference Include="System.Net" />
    <Reference Include="System.Net.Http" />
    <Reference Include="System.Net.Http.WebRequest" />
    <Reference Include="System.Security" />
    <Reference Include="System" />
    <Reference Include="System.Web.Entity" />
    <Reference Include="System.Drawing" />
    <Reference Include="System.Web" />
    <Reference Include="WindowsBase" />
  </ItemGroup>
    <ProjectExtensions>
      <VisualStudio>
        <FlavorProperties GUID="{349c5851-65df-11da-9384-00065b846f21}">
          <WebProjectProperties>
           <UseIIS>True</UseIIS>
           <AutoAssignPort>True</AutoAssignPort>
           <DevelopmentServerPort>56462</DevelopmentServerPort>
           <DevelopmentServerVPath>/</DevelopmentServerVPath>
           <IISUrl>http://localhost:56462/</IISUrl>
           <NTLMAuthentication>false</NTLMAuthentication>
           <UseCustomServer>False</UseCustomServer>
           <CustomServerUrl>
           </CustomServerUrl>
           <SaveServerSettingsInUserFile>False</SaveServerSettingsInUserFile>
          </WebProjectProperties>
        </FlavorProperties>
      </VisualStudio>
    </ProjectExtensions>
  <Import Sdk="Microsoft.NET.Sdk.Publish" Project="Sdk.targets" />
</Project>

The problem I'm running into is when I try to debug (Debug -> Start New Instance), I get the following error:

Unable to run your project. The "RunCommand" property is not defined.

A few questions:

  1. Does MSBuild.SDK.SystemWeb support ASP.NET Web API 2 projects?
  2. If so, what am I missing in order to have it debug through Visual Studio?
CZEMacLeod commented 2 years ago

Yes it supports webapi2. I'm not sure the exact issue you are encountering - but depending on how you have converted it, you are probably missing the launchsettings.json file from your properties directory. Remove the ProjectExtensions section and all the *IISExpress* properties from the project. All of that is handled by launchsettings.json. Also, you don't need any ProjectCapability entries. The ones supported/required are automatically applied by the SDK. Look at the empty web sample for the minimum required.

https://github.com/CZEMacLeod/MSBuild.SDK.SystemWeb/tree/main/samples/ExampleEmptyWebApplication

There is also an Owin example here https://github.com/CZEMacLeod/OwinStaticFilesUsingCore - note that it was a small experiment to wrap the aspnetcore StaticFiles IContentTypeProvider into an Owin version due to some filetypes being missing in Owin. The references to Microsoft.AspNetCore should not normally be used in this system.

Also Microsoft.CodeDom.Providers.DotNetCompilerPlatform is not automatically included by the SDK. By default it is version 3.6.0. There are some issues with the older versions in this scenario which are resolved in this version. You can move to a newer version by setting the property <MicrosoftCodeDomProvidersDotNetCompilerPlatform_Version></MicrosoftCodeDomProvidersDotNetCompilerPlatform_Version>

You may need to adjust the system.codedom section of your web.config to match the assembly version:

  <system.codedom>
    <compilers>
      <compiler language="c#;cs;csharp" extension=".cs" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.CSharpCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:1659;1699;1701" />
      <compiler language="vb;vbs;visualbasic;vbscript" extension=".vb" type="Microsoft.CodeDom.Providers.DotNetCompilerPlatform.VBCodeProvider, Microsoft.CodeDom.Providers.DotNetCompilerPlatform, Version=3.6.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" warningLevel="4" compilerOptions="/langversion:default /nowarn:41008 /define:_MYTYPE=\&quot;Web\&quot; /optionInfer+" />
    </compilers>
  </system.codedom>

I doubt you need most of the Reference items either. System.Web is automatically included by the SDK, and System, and System.Drawing are included by the base SDK. You also (unlike in the original packages.config or legacy project format) do not need to include the complete hierarchy of packages (unless you want to use a newer version of a referenced package). Including Microsoft.AspNet.WebApi will include Microsoft.AspNet.WebApi.WebHost which will include Microsoft.AspNet.WebApi.Core which will include Microsoft.AspNet.WebApi.Client which will add the framework reference to System.Net.Http as well as Newtonsoft.Json You might want to include the Newtonsoft.Json package directly to use a newer version - e.g. 12.0.3 or 13.0.1. See the ExampleFullWebApplication for more information. I recommend playing with the example templates which are available for c# and vb as either empty or a full stack to understand more.

You also appear to have misspelt Microsoft.AspNet.WebApi.Own - it should be Microsoft.AspNet.WebApi.Owin and as far as I can remember you should only have 1 of Microsoft.AspNet.WebApi.Owin or Microsoft.AspNet.WebApi.WebHost depending on whether you are running WebAPI2 directly on System.Web or under Owin, regardless of whether Owin is selfhosted (Microsoft.Owin.SelfHost) or running under System.Web (Microsoft.Owin.Host.SystemWeb).

I created a MVP of WebAPI2 in Owin on MSBuild.SDK.SystemWeb here - https://github.com/CZEMacLeod/WebAPI2-Owin Hope this helps.

gortok commented 2 years ago

@CZEMacLeod This is wonderful work, thank you. Far above and beyond my expectations. I'm still getting

"Unable to run your project. The "RunCommand" Property is not defined."

There's a workaround here that I'll try: https://github.com/dotnet/sdk/issues/833

gortok commented 2 years ago

Interestingly; what ended up fixing it was going into the project debug settings (through "properties" in visual studio) and ensuring the appropriate start up options were chosen. For whatever reason they were all blanked out and it wasn't picking it up from the launchSettings.json.

CZEMacLeod commented 2 years ago

@gortok Great that you found a solution. My testing showed the RunCommand error shows if the launchSettings.json file is missing (or corrupted). I'm guessing it was either in the wrong location, had a spelling mistake, or had bad content - all easily done. I might try and add some more examples to the project here, and possibly extend the templates with more options, maybe to more closely match the options for the built-in ASP.Net 4 Web Application templates.

gortok commented 2 years ago

Yea, Once I fixed everything via the 'properties' tab debugging worked just fine.

@CZEMacLeod One issue I'm running into now is when I run Build -> Publish <ProjectName>, I get the following error:

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.

I also receive this error when trying to publish in Azure Devops On-Premise.

From what I read this is caused by an intermediate directory obj containing the web config as well as the bin directory; but I'm unclear on how to resolve the issue.

CZEMacLeod commented 2 years ago

@gortok Regarding Publish - I don't think there is any good solution to publish from within VS. I noticed that your project file had includes for Microsoft.NET.Sdk.Publish which should not be used with this SDK.

The original publish mechanism for ASP.NET4 Web Application Projects does work though if you invoke it from the command line. There is some discussion of this in issue #12.

msbuild "path\to\your\solution.sln" /t:rebuild ^
                    /p:Configuration=Release ^
                    /p:DeployOnBuild=True ^
                    /p:DeployDefaultTarget=WebPublish ^
                    /p:WebPublishMethod=FileSystem ^
                    /p:DeleteExistingFiles=True ^
                    /p:publishUrl="path\to\your\output\folder"

If you create the publish profiles on a legacy project then copy them into your project, they should work.

msbuild /t:Rebuild /p:DeployOnBuild=true /p:PublishProfile=FolderProfile.pubxml

Note that I would recommend that you always do a nuget restore command before. This should also work with CI/CD e.g. Azure DevOps.

I'm closing this here - if you want to open a specific issue regarding publish, open a new issue.