I have this HTML on the page:
@using MyHelpers
@model FluentHtmlHelpers.Models.SampleAlertModel
@{
ViewBag.Title = "Strongly Typed";
}
<h2>Strongly Typed</h2>
<span>Html.AlertFor(m => m.AlertBoxText).Success()</span>
@Html.AlertFor(m => m.AlertBoxText).Success()
<span>Html.AlertFor(m => m.AlertBoxText, m => m.AlertBoxStyle)</span>
@Html.AlertFor(m => m.AlertBoxText, m => m.AlertBoxStyle)
SampleAlertModel:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using MyHelpers;
namespace FluentHtmlHelpers.Models
{
public class SampleAlertModel
{
public string AlertBoxText { get; set; }
public MyHelpers.AlertStyle AlertBoxStyle { get; set; }
}
}
AlertHtmlHelper:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
namespace MyHelpers
{
/// <summary>
/// Generates an Alert message
/// </summary>
public static class AlertHtmlHelper
{
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox Alert(this IHtmlHelper html,
string text,
AlertStyle alertStyle = AlertStyle.Default,
bool hideCloseButton = false,
object htmlAttributes = null)
{
return new AlertBox(text, alertStyle, hideCloseButton, htmlAttributes);
}
// Strongly typed
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox AlertFor<TModel, TTextProperty>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TTextProperty>> expression,
AlertStyle alertStyle = AlertStyle.Default,
bool hideCloseButton = false,
object htmlAttributes = null)
{
var metadata = ExpressionMetadataProvider.FromLambdaExpression(expression, html.ViewData, html.MetadataProvider);
return new AlertBox((string)metadata.Model, alertStyle, hideCloseButton, htmlAttributes);
}
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox AlertFor<TModel, TTextProperty, TStyleProperty>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TTextProperty>> textExpression,
Expression<Func<TModel, TStyleProperty>> styleExpression,
bool hideCloseButton = false,
object htmlAttributes = null)
{
var text = (string) ExpressionMetadataProvider.FromLambdaExpression(textExpression, html.ViewData, html.MetadataProvider).Model;
var alertStyle = (AlertStyle)ExpressionMetadataProvider.FromLambdaExpression(styleExpression, html.ViewData, html.MetadataProvider).Model;
return new AlertBox(text, alertStyle,hideCloseButton, htmlAttributes);
}
}
}
But I get this error:
TypeLoadException: Could not load type 'Microsoft.AspNetCore.Mvc.ViewFeatures.Internal.ExpressionMetadataProvider' from assembly 'Microsoft.AspNetCore.Mvc.ViewFeatures, Version=8.0.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60'.
Believe that you are installing the NuGet package: Microsoft.AspNetCore.Mvc.ViewFeatures version 2 in your MyHelpers project. This results in the compatibility issue when integrating with ASP.NET Core 3 or above (.NET 5 and above) MVC web application.
Hence, you need to do some migrations to resolve the compatibility issue.
Pre-requisites: The class library is using .NET 8.
Remove the Microsoft.AspNetCore.Mvc.ViewFeatures from the project via NuGet. (This can be ignored if you are working with blank new project)
Add the following packages to the MyHelpers.csproj file.
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
So it should look as below to use the Microsoft.AspNetCore.Mvc libraries:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="Microsoft.AspNetCore.Razor.Design" Version="2.1.2" PrivateAssets="All" />
</ItemGroup>
</Project>
Remove the line using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
in all class files.
Migrate the ExpressionMetadataProvider.FromLambdaExpression
method due to reported Microsoft.AspNetCore.Mvc.ViewFeatures.Internal has been moved to internal
.
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using System.Linq.Expressions;
public static class AlertHtmlHelper
{
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox Alert(this IHtmlHelper html,
string text,
AlertStyle alertStyle = AlertStyle.Default,
bool hideCloseButton = false,
object htmlAttributes = null
)
{
return new AlertBox(text, alertStyle, hideCloseButton, htmlAttributes);
}
// Strongly typed
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox AlertFor<TModel, TTextProperty>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TTextProperty>> expression,
AlertStyle alertStyle = AlertStyle.Default,
bool hideCloseButton = false,
object htmlAttributes = null
)
{
var expresionProvider = html.ViewContext.HttpContext.RequestServices.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
var exp = expresionProvider.CreateModelExpression(html.ViewData, expression);
return new AlertBox((string)exp.Model, alertStyle, hideCloseButton, htmlAttributes);
}
/// <summary>
/// Generates an Alert message
/// </summary>
public static AlertBox AlertFor<TModel, TTextProperty, TStyleProperty>(this IHtmlHelper<TModel> html,
Expression<Func<TModel, TTextProperty>> textExpression,
Expression<Func<TModel, TStyleProperty>> styleExpression,
bool hideCloseButton = false,
object htmlAttributes = null
)
{
var expresionProvider = html.ViewContext.HttpContext.RequestServices.GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;
var textExp = expresionProvider.CreateModelExpression(html.ViewData, textExpression);
var styleExp = expresionProvider.CreateModelExpression(html.ViewData, styleExpression);
var text = (string)textExp.Model;
var alertStyle = (AlertStyle)styleExp.Model;
return new AlertBox(text, alertStyle, hideCloseButton, htmlAttributes);
}
}
InnerHtml
property from the TagBuilder
instance for text appending, it no longer supports the +=
or =
operators as it is read-only. You need to migrate to:<TagBuilder instance>.InnerHtml.AppendHtml(/* Html value */);