3

I have a project in ASP.NET 5 RC1 which I used to get the the urlHelper from the HtmlHelper Context in my HTMLHelper static methods

    public static IHtmlContent MyHtmlHelperMethod<TModel, TResult>(
            this IHtmlHelper<TModel> htmlHelper,
            Expression<Func<TModel, TResult>> expression)
    {



       //get the context from the htmlhelper and use it to get the urlHelper as it isn't passed to the method from the view
        var urlHelper = GetContext(htmlHelper).RequestServices.GetRequiredService<IUrlHelper>();

        var controller = htmlHelper.ViewContext.RouteData.Values["controller"].ToString();
        string myLink;
        if (htmlHelper.ViewContext.RouteData.Values["area"] == null)
        {
            myLink= urlHelper.Action("index", controller);

        } else
        {

            string area = htmlHelper.ViewContext.RouteData.Values["area"].ToString();
            myLink = urlHelper.Action("index", controller, new { area = area });

        }  
        string output = "<div><a href = \"" + myLink + "\" class=\"myclass\"><blabla></blabla>My Link</a></div>;
        return new HtmlString(output.ToString());
    }

However in ASP.NET Core it no longer works and I get the runtime error

>InvalidOperationException: No service for type 'Microsoft.AspNetCore.Mvc.IUrlHelper' has been registered.

The solution posted in this stackoverflow answer is to inject IUrlHelperFactory, however I am using static html helper methods I call in my cshtml and not classes which is used in taghelpers.

How do I change my code to work in ASP.net Core ?

Esko
  • 4,109
  • 2
  • 22
  • 37
dfmetro
  • 4,462
  • 8
  • 39
  • 65

2 Answers2

7

Microsoft may have moved things about a bit in .net core 2.1. It is slightly simpler than the accepted answer. I hope this is helpful to somebody.

using Microsoft.AspNetCore.Html;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.Extensions.DependencyInjection;

namespace MyApp.Extensions
{
    public static class WebApiHelperExtension
    {
        public static IHtmlContent WebApiUrl(this IHtmlHelper htmlHelper)
        {
            var urlHelperFactory = htmlHelper.ViewContext.HttpContext.RequestServices.GetRequiredService<IUrlHelperFactory>();
            var urlHelper = urlHelperFactory.GetUrlHelper(htmlHelper.ViewContext);
            //...
        }
    }
}
Dirk R
  • 602
  • 7
  • 14
  • but where would you get htmlhelper instance? – LP13 May 08 '19 at 21:15
  • 1
    It is passed in automatically via DependencyInjection, so you don't need to get it. You can call the function from a .cshtml file without the parameter: ```@Html.WebApiUrl()``` – Dirk R May 13 '19 at 09:29
5

Change your original code to:

var urlHelperFactory = GetContext(htmlHelper).RequestServices.GetRequiredService<IUrlHelperFactory>();
var actionContext = GetContext(htmlHelper).RequestServices.GetRequiredService<IActionContextAccessor>().ActionContext;
var urlHelper = urlHelperFactory.GetUrlHelper(actionContext); 
devfric
  • 7,304
  • 7
  • 39
  • 52
  • Thanks for the solution but I got to say it is not beautiful and I would have like asp.net core developers to make this a little easier – Yepeekai Oct 26 '17 at 19:40
  • 1
    I don't know if this is a new .net core 2.1 thing, but the above now yields an error for me saying IActionContextAccessor is not registered. See my answer below, which is now down to two lines of code. Yay. – Dirk R Jul 25 '18 at 13:00