Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a MVC5 MvcHtmlString in ASP.NET Core

I wonder if someone can help with demonstrating how to create a IHtmlContent or HtmlString in ASP.NET Core, similar to what I previously have done in MVC5. I would normally declare a new MvcHtmlString method within a Helper class like so:

HtmlExtender.cs

using System.Text;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;

namespace WebApplication1.Helpers
{
    public static class HtmlExtender
    {
        public static MvcHtmlString MenuLink(this HtmlHelper htmlHelper, string linkText, string controller, string action, string area, string anchorTitle)
        {
            var urlHelper = new UrlHelper(htmlHelper.ViewContext.RequestContext);

            var url = urlHelper.Action(action, controller, new { area });

            var anchor = new TagBuilder("a") {InnerHtml = HttpUtility.HtmlEncode(linkText)};
            anchor.MergeAttribute("href", url);
            anchor.Attributes.Add("title", anchorTitle);

            var listItem = new TagBuilder("li") {InnerHtml = anchor.ToString(TagRenderMode.Normal)};

            if (CheckForActiveItem(htmlHelper, controller, action, area))
            {
                listItem.GenerateId("menu_active");
            }

            return MvcHtmlString.Create(listItem.ToString(TagRenderMode.Normal));
        }

        private static bool CheckForActiveItem(HtmlHelper htmlHelper, string controller, string action, string area)
        {
            if (!CheckIfTokenMatches(htmlHelper, area, "area"))
                return false;

            if (!CheckIfValueMatches(htmlHelper, controller, "controller"))
                return false;

            return CheckIfValueMatches(htmlHelper, action, "action");
        }
    }
}

To use in a View would be @Html.MenuLink("Home", "Home", "Index", "", "Home") also the inclusion of @using WebApplication1.Helpers at the top of the View.

I'm unsure as to the use of HtmlString or IHtmlContent to achieve what I need, but my method requires access to the HttpContextAccessor, but I am a little unsure how to do this.

I have declared the HttpContextAccessor in the Startup.cs as I believe in ASP.NET Core 2.0 it is not declared by default as shown below but require assistance as how to use within the helper method.

Startup.cs

public void ConfigureServices(IServiceCollection serviceCollection)
{
    serviceCollection.AddMvc();
    serviceCollection.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
like image 404
iggyweb Avatar asked Aug 04 '17 09:08

iggyweb


1 Answers

The new primitives in MVC Core are nice and easy to use. The TagBuilder implements IHtmlContent which can and should be used everywhere you are currently using MvcHtmlString. For your example above, simply remove the MvcHtmlString.Create and return the TagBuilder directly (adjusting to return IHtmlContent).

Other useful classes is HtmlContentBuilder, another type returning IHtmlContent, that can AppendHtml, similar to StringBuilder but for HTML content specifically. You can append many tag builders, which is very handy.

This is theoretically what you are after (I am found this GetUrlHelper extension elsewhere, I forget where).

    public static IUrlHelper GetUrlHelper(this IHtmlHelper html)
    {
        var urlFactory = html.ViewContext.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>();
        var actionAccessor = html.ViewContext.HttpContext.RequestServices.GetRequiredService<IActionContextAccessor>();
        return urlFactory.GetUrlHelper(actionAccessor.ActionContext);
    }
    public static IHtmlContent MenuLink(this IHtmlHelper htmlHelper, string linkText, string controller, string action, string area, string anchorTitle)
    {

        var urlHelper = htmlHelper.GetUrlHelper();

        var url = urlHelper.Action(action, controller, new { area });

        var anchor = new TagBuilder("a");
        anchor.InnerHtml.Append(linkText);
        anchor.MergeAttribute("href", url);
        anchor.Attributes.Add("title", anchorTitle);

        var listItem = new TagBuilder("li");
        listItem.InnerHtml.AppendHtml(anchor);

        if (CheckForActiveItem(htmlHelper, controller, action, area))
        {
            listItem.GenerateId("menu_active", "_");
        }

        return listItem;
    }
like image 196
ocdi Avatar answered Oct 30 '22 14:10

ocdi