Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Replacement for ExpressionHelper in ASP.NET Core 3.0?

In ASP.NET Core 2.x I was using static method GetExpressionText of ExpressionHelper class for IHtmlHelper<T> extension method:

using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;

public static class HtmlHelperExtensions
{
    public static string GetExpressionText<TModel, TResult>(
        this IHtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TResult>> expression)
    {
        return ExpressionHelper.GetExpressionText(expression);
    }
}

In ASP.NET Core 3.0 namespace Microsoft.AspNetCore.Mvc.ViewFeatures.Internal is not available any more. Therefore compiler is throwing exception:

The name 'ExpressionHelper' does not exist in the current context.

What is proper replacement for ExpressionHelper functionality?

like image 976
Nenad Avatar asked Sep 06 '19 12:09

Nenad


2 Answers

ModelExpressionProvider from Microsoft.AspNetCore.Mvc.ViewFeatures can be used.

Method GetExpressionText wraps identical method of ExpressionHelper and adds additional caching or results as described in this Github issue.

using Microsoft.AspNetCore.Mvc.ViewFeatures;

public static class HtmlHelperExtensions
{
    public static string GetExpressionText<TModel, TResult>(
        this IHtmlHelper<TModel> htmlHelper,
        Expression<Func<TModel, TResult>> expression)
    {
        var expressionProvider = htmlHelper.ViewContext.HttpContext.RequestServices
            .GetService(typeof(ModelExpressionProvider)) as ModelExpressionProvider;

        return expressionProvider.GetExpressionText(expression);
    }
}
like image 133
Nenad Avatar answered Nov 02 '22 18:11

Nenad


An alternative solution which does not depend on IHtmlHelper and can be used on other scenarios is the following:

public static class StringExtensions
{
    private static readonly ModelExpressionProvider ModelExpressionProvider = new ModelExpressionProvider(new EmptyModelMetadataProvider());

    public static string GetExpressionText<TEntity, TProperty>(this Expression<Func<TEntity, TProperty>> expression)
    {
        return ModelExpressionProvider.GetExpressionText(expression);
    }
}

Something to keep in mind is that ModelExpressionProvider holds a ConcurrentDictionary inside for caching, that's why making it static could be beneficial.

As Nenad said, ModelExpressionProvider.GetExpressionText is just a wrapper around ExpressionHelper.GetExpressionText with the addition of the cache parameter:

public class ModelExpressionProvider : IModelExpressionProvider
{
    private readonly IModelMetadataProvider _modelMetadataProvider;
    private readonly ConcurrentDictionary<LambdaExpression, string> _expressionTextCache;
    ....
    public string GetExpressionText<TModel, TValue>(Expression<Func<TModel, TValue>> expression)
    {
        if (expression == null)
        {
            throw new ArgumentNullException(nameof(expression));
        }

        return ExpressionHelper.GetExpressionText(expression, _expressionTextCache);
    }
    ....
}
like image 4
Augusto Barreto Avatar answered Nov 02 '22 17:11

Augusto Barreto