57

The new .csproj format includes some significant improvements over the classic files, including tight integration with NuGet package management and significantly less-verbose structure. I want to gain these benefits whilst still using the .NET Framework 4.6 and ASP.NET (because my project depends on Umbraco which has yet to produce a .NET Core version).

The biggest challenge would seem to be the debugging experience - an ASP.NET Core project expects to run a dotnet core application and set up a reverse proxy to an IIS instance. This process is completely alien to the .NET Framework model and I wouldn't know where to start trying to set up debugging in Visual Studio.

Is there any way to get these two project models to mix?

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • You are focussing on an IIS web project now not any console .net framework application? – Joel Harkes Apr 04 '18 at 13:03
  • cool question i havent tried, but i think this could work. as far as i know the 'new' project structure gets completely rewritten to old structure by `.prop` files. unless the old tags are invalid this would still work. atleast definitly for console and class projects. – Joel Harkes Apr 04 '18 at 13:06
  • 1
    This is specifically: can I get an **ASP.NET Framework** project to build and debug from Visual Studio whilst using the new .csproj file format? If there are things which *also* work for console applications and other hosting mechanisms, that's great too. – Paul Turner Apr 04 '18 at 13:13
  • Does this match your scenario? this link explains some have and have nots for doing such: https://learn.microsoft.com/en-us/dotnet/standard/choosing-core-framework-server#current-net-framework-applications –  Apr 04 '18 at 15:53

3 Answers3

80

There is a bunch of open issues on GitHub regarding support of new csproj format for ASP.NET (non-Core) applications. Some of them:

As you probably already understood, new csproj format is not yet supported for ASP.NET applications. It's possible to make it work, however it won't be smooth.

Some time ago I have tried to create ASP.NET MVC project in new csproj format, just for fun. I made it work, however I had not played with it a lot. So it will be interesting to know your experience.

The steps are following:

  1. Remove old unrequired project files:

    • MvcApplication.csproj
    • MvcApplication.csproj.user
    • packages.config
  2. Create new MvcApplication.csproj with the following content:

    <Project Sdk="Microsoft.NET.Sdk">
    
      <PropertyGroup>
        <TargetFramework>net461</TargetFramework>
      </PropertyGroup>
    
      <PropertyGroup>
        <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
        <OutputPath>bin\</OutputPath>
      </PropertyGroup>
    
      <ItemGroup>
        <PackageReference Include="Antlr" version="3.4.1.9004" />
        <PackageReference Include="bootstrap" version="3.0.0" />
        <PackageReference Include="jQuery" version="1.10.2" />
        <PackageReference Include="jQuery.Validation" version="1.11.1" />
        <PackageReference Include="Microsoft.ApplicationInsights" version="2.2.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.Agent.Intercept" version="2.0.6" />
        <PackageReference Include="Microsoft.ApplicationInsights.DependencyCollector" version="2.2.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.PerfCounterCollector" version="2.2.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.Web" version="2.2.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.WindowsServer" version="2.2.0" />
        <PackageReference Include="Microsoft.ApplicationInsights.WindowsServer.TelemetryChannel" version="2.2.0" />
        <PackageReference Include="Microsoft.AspNet.Mvc" version="5.2.3" />
        <PackageReference Include="Microsoft.AspNet.Razor" version="3.2.3" />
        <PackageReference Include="Microsoft.AspNet.Web.Optimization" version="1.1.3" />
        <PackageReference Include="Microsoft.AspNet.WebPages" version="3.2.3" />
        <PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="1.0.5" />
        <PackageReference Include="Microsoft.CSharp" Version="4.4.1" />
        <PackageReference Include="Microsoft.jQuery.Unobtrusive.Validation" version="3.2.3" />
        <PackageReference Include="Microsoft.Net.Compilers" version="2.1.0" developmentDependency="true" />
        <PackageReference Include="Microsoft.Web.Infrastructure" version="1.0.0.0" />
        <PackageReference Include="Modernizr" version="2.6.2" />
        <PackageReference Include="Newtonsoft.Json" version="6.0.4" />
        <PackageReference Include="Respond" version="1.2.0" />
        <PackageReference Include="WebGrease" version="1.5.2" />
      </ItemGroup>
    
      <ItemGroup>
        <DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.0" />
      </ItemGroup>
    
      <ItemGroup>
        <Reference Include="System.Web" />
      </ItemGroup>
    
      <ItemGroup>
        <Compile Update="Global.asax.cs">
          <DependentUpon>Global.asax</DependentUpon>
        </Compile>
      </ItemGroup>
    
      <ItemGroup>
        <Content Include="Web.config">
          <SubType>Designer</SubType>
        </Content>
        <Content Include="Web.*.config">
          <DependentUpon>Web.config</DependentUpon>
          <SubType>Designer</SubType>
        </Content>
      </ItemGroup>
    
    </Project>
    

    The long package list above includes default packages added for default ASP.NET MVC application. You should add other packages used by your application.

    Don't forget to add the Microsoft.CSharp package, otherwise you'll get following compilation error on ViewBag assignments:

    error CS0656: Missing compiler required member 'Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo.Create'

    In ASP.NET projects, Microsoft.CSharp is added as reference to the project. But it's better to consume it as NuGet package.

    The only direct reference that could not be avoided is a System.Web.

  3. Debugging the project

    You were right when said that debugging could be a pain. Since Visual Studio does not know it's an ASP.NET application, there is no instant method to start debugging session.

    I see 2 possible solutions here:

    a. Use IIS Express for debugging.

    It's quite easy to configure debugging based on IIS Express executable. Just create the following debugging profile:

    enter image description here

    Corresponding launchSettings.json:

    {
      "profiles": {
        "ASP.NET Old csproj": {
          "commandName": "Executable",
          "executablePath": "c:\\Program Files\\IIS Express\\iisexpress.exe",
          "commandLineArgs": "/path:\"$(SolutionDir)$(ProjectName)\" /port:12345"
        }
    }
    

    b. Use IIS for debugging.

    In IIS Manager create application that points to directory with your project. Now you could debug your application by attaching to w3wp.exe process.

Here is Sample Project on GitHub. It is basically default ASP.NET MVC project migrated to new csproj format following above steps. It could be compiled, executed and debugged (profile for IIS Express included)

CodeFuller
  • 30,317
  • 3
  • 63
  • 79
  • That's a nice approach for using IIS Express. The only thing missing from being a perfect solution is how ASP.NET Core uses a "wwwroot" folder to contain all the static assets, where this still uses the project root. I assume a change to the `/path` switch when launching the application would be an answer. – Paul Turner Apr 05 '18 at 18:39
  • 3
    Not sure I understood you correctly. Yes, ASP.NET Core changed the handling of static files and now all static content resides in [wwwroot](https://learn.microsoft.com/en-us/aspnet/core/fundamentals/static-files). It's just a location used by ASP.NET Core Web Host by default. However it does not relate to csproj file structure. And since we discuss ASP.NET (non-Core), `wwwroot` does not come into play here. All ASP.NET static content folders (like `Content`, `fonts`, `Scripts`) have the same relative location within both project directory and directory of deployed application . – CodeFuller Apr 05 '18 at 19:55
  • It's important because "source" files (anything outside of `wwwroot`) aren't used as part of the application, which makes it much easier to work with content-processors like webpack. I don't think the ASP.NET Framework build process particularly cares where files are, as long as they're in the project structure somewhere, but I was never able to set the application to run using `wwwroot` as the virtual directory of the site when running under the .NET Framework. Using the `/path` switch might be the answer I am looking for. – Paul Turner Apr 06 '18 at 12:50
  • I had to change app args to this: `/path:$(SolutionDir)$(ProjectName) /port:1234` otherwise it wouldn't start. For some reason the quotes around the path wouldn't work. `"/path:$(SolutionDir)$(ProjectName)" /port:1234` worked too. – skb Sep 28 '18 at 19:00
  • 3
    This also appears to break web publishing — it only seems to offer a folder target now, not stuff like WebDeploy. – Sören Kuklau Nov 12 '18 at 16:30
  • The app args described in this solution and information from @skb did not work for me. I had to use the real full path to get it working. – Stef Heyenrath Mar 25 '19 at 16:32
  • 3
    Did anyone manage to deploy this via the command line? `dotnet publish` doesn't seem to produce valid output. The sample project gives me a 403 error when running inside iis express. – ilivewithian Jun 10 '19 at 11:11
  • 1
    `false` and `bin` was why my IIS couldn't find my DLLs. IIS looks in `.\bin` and not `.\bin\DebugOrRelease\net451` – Eliasar Sep 18 '19 at 15:10
  • @CodeFuller can you update your very nice answer with the latest changes meanwhile. Full support is still missing – Falco Alexander Jun 09 '20 at 10:50
  • I got this all to work, except VS doesn't seem to pick up the namespaces in the web.config file in the views folder, so I get all red squigles when editing a razor view... Any idea how to solve this? – fretje Dec 06 '20 at 22:33
  • @ilivewithian I already deployed using msbuild before I changed the project format, and everything still seems to work fine that way (msbuild /p:DeployOnBuild=True) – fretje Dec 06 '20 at 22:38
  • How do you debug httpS localhost? – Michael Blake Jan 15 '21 at 12:46
  • @CodeFuller FYI, your github project is missing the launchSettings.json file. you had it in the .gitignore – AlignedDev Oct 15 '21 at 19:08
18

I am following this github issue regarding this, and the latest comments posted add the last missing pieces. Basically, with a .csproj file like this:

<Project>
  <Import Project="Sdk.props" Sdk="Microsoft.NET.Sdk" />
  <PropertyGroup>
    <OutputType>Library</OutputType>
    <OutputPath>bin\</OutputPath>
    <TargetFramework>net48</TargetFramework>
    <AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
    <PublishProfileImported>true</PublishProfileImported>
  </PropertyGroup>
  <ItemGroup>
    <ProjectCapability Include="DotNetCoreWeb" />
    <ProjectCapability Include="SupportsSystemWeb" />
  </ItemGroup>
  <!-- add your packagereference/content/etc includes here -->
  <PropertyGroup>
    <VisualStudioVersion Condition="'$(VisualStudioVersion)' == ''">15.0</VisualStudioVersion>
    <VSToolsPath Condition="'$(VSToolsPath)' == ''">$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)</VSToolsPath>
  </PropertyGroup>
  <!-- order is important! -->
  <Import Project="Sdk.targets" Sdk="Microsoft.NET.Sdk" />
  <Import Project="$(VSToolsPath)\WebApplications\Microsoft.WebApplication.targets" />
</Project>

everything works!

  • The normal run and debug experience with visual studio starting iisexpress with the right applicationhost.config. If you fill out the sslport in launchsettings, it even works with ssl.
  • The normal edit and debug razor experience without any red squiggles and with working intellisense/autocomplete.

The only thing that still seems to be missing is right click deploy functionality... But as you can use msbuild /p:DeployOnBuild=True to deploy, I finally don't see anything missing anymore that stops me from upgrading.

fretje
  • 8,322
  • 2
  • 49
  • 61
  • 2
    +1 if this question were asked in 2020 / 2021, this should be the accepted answer! wish i had read it first. – nicholas Feb 25 '21 at 22:56
  • 2
    I needed to add `` and `` for my project to build. – Dai Jun 13 '21 at 06:04
  • This builds and the website runs for me. When I try to run and debug it in visual studio though, I get the error "Unable to run your project. The "RunCommand" property is not defined." – Garrett Banuk Oct 18 '22 at 17:01
  • @GarrettBanuk - for the 'Unable to run your project. The "RunCommand" property is not defined' issue, [this answer](https://stackoverflow.com/a/71016227) worked for me. – Frank Alvaro Jul 19 '23 at 13:19
3

The best way to migrate ASP.NET MVC to new csproj format is using try-convert using the following command:

try-convert -p .\project.csproj --keep-current-tfms --no-backup --force-web-conversion

Thanks to the --keep-current-tfms option your target framework will not change.

After that you should change project SDK to MSBuild.SDK.SystemWeb because the default SDK doesn't support old ASP.NET MVC.

<Project Sdk="MSBuild.SDK.SystemWeb/4.0.66">

Thanks to MSBuild.SDK.SystemWeb you should be able to use every function of VS in the same way like with the old csproj format. There you can file the documentation about this library.