使用.net标准2.0将.net4.0旧库转换为多个目标会导致HtmlString引用错误

时间:2018-02-06 11:41:49

标签: c# asp.net .net asp.net-mvc .net-standard

我正在移植一个旧的类库,因此它可以多个目标.net4.0和.net标准。我需要在.net核心项目中使用相同的库。

图书馆严重依赖System.Web.Mvc,我正在使用此处描述的策略1: Upgrading ASP.NET Libraries to .NET Standard

我无法解决的错误是:

  

1 - 对'HtmlString类型的引用声称它是在'System.Web'中定义的,但是找不到它   It looks like this on VS2017:

     

2 - 'MvcHtmlString'不包含'ToHtmlString'的定义,也没有可以找到接受类型'MvcHtmlString'的第一个参数的扩展方法'ToHtmlString'(你是否缺少using指令或汇编引用?)   It looks like this on VS2017:

我创建了一个新的.net标准类库项目并将文件复制过来。这是我的csproj文件:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
      <PackageReference Include="Microsoft.AspNet.Mvc" Version="3.0.50813.1" />
  </ItemGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">     
    <Reference Include="mscorlib" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Web" />
  </ItemGroup>
</Project>

我尝试将其添加到netstandard2.0 ItemGroup,但它没有帮助:

<Reference Include="System.Web" />

我需要做些什么来修复?我已经阅读了一些关于这个主题的内容,但它仍然令人困惑,我找到的链接也无济于事。

我最终只为.NET Core使用了新的代码库。 我的.csproj是这样的:

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup>
    <PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.DataAnnotations" Version="2.0.2" />
    <PackageReference Include="Microsoft.AspNetCore.Mvc.ViewFeatures" Version="1.1.0" />
  </ItemGroup>
</Project>

正如@ NightOwl888解释的那样,我需要Microsoft.AspNetCore.Html.Abstractions,因此我可以使用HtmlString代替MvcHtmlString

Microsoft.AspNetCore.Mvc.ViewFeatures是必要的,因此SelectExtensions例如DropDownListFor可能会返回与HtmlString兼容的类型。

我还必须将所有HtmlHelper替换为IHtmlHelper,将ModelMetaData替换为ModelExplorer

ModelMetadata.FromLambdaExpression现在是ExpressionMetadataProvider.FromLambdaExpression

1 个答案:

答案 0 :(得分:2)

根据article you linked

  

如果库没有调用超出.NET Standard 2.0可用范围的任何功能,则兼容模式将起作用。

在.NET Standard上代替MvcHtmlString,您可以按照this answer使用Microsoft.AspNetCore.Html.HtmlString类型。

由于.NET 4.0中MvcHtmlString的基类是HtmlString,因此您应该返回HtmlString,它将在两种情况下都有效(尽管您需要为每个引用一个不同的命名空间)。

#if NET40
    using HtmlString = System.Web.HtmlString;
#else
    using HtmlString = Microsoft.AspNetCore.Html.HtmlString;
#endif

您需要在netstandard2.0定向引荐中引用Microsoft.AspNetCore.Html.Abstractions才能使用该类型。

<Project Sdk="Microsoft.NET.Sdk">

  <PropertyGroup>
    <TargetFrameworks>netstandard2.0;net40</TargetFrameworks>
  </PropertyGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0'">
      <PackageReference Include="Microsoft.AspNetCore.Html.Abstractions" Version="2.0.0" />
  </ItemGroup>

  <ItemGroup Condition=" '$(TargetFramework)' == 'net40' ">     
    <Reference Include="mscorlib" />
    <Reference Include="System" />
    <Reference Include="System.Core" />
    <Reference Include="Microsoft.CSharp" />
    <Reference Include="System.Web" />
  </ItemGroup>
</Project>

至于ToHtmlString(),我很困惑Microsoft intends to do about it。但是,在#if NETSTANDARD2.0#endif块之间添加扩展方法(或者有条件地包含在编译中的文件)在您的库中是一个非常直接的事情。

然而,正如John Skeet在评论中指出的那样,通过相同的API公开2种不同的类型可能不是最好的主意。您可能最好为.NET Framework和.NET Core制作单独的API,并将它们放在单独的以平台为目标的库中,这些库引用包含共享业务逻辑的.NET Standard库。