Using HtmlHelper in a Controller

asp.net Mvc

asp.net Mvc Problem Overview


Is it possible to use HtmlHelper in a controller, for-example to get the TextBox(...) method? not that I can't write the html that it generates myself, but I just want to understand how this works so I can create the best solution.

asp.net Mvc Solutions


Solution 1 - asp.net Mvc

Here's an example adapted from this:

var h = new HtmlHelper(new ViewContext(ControllerContext, new WebFormView("omg"), new ViewDataDictionary(), new TempDataDictionary()), new ViewPage());
h.TextBox("myname");

Note that this is a hack, it can be done but I don't think there's any good reason to do this...

Solution 2 - asp.net Mvc

You can use method like this:

public static HtmlHelper GetHtmlHelper(this Controller controller)
{
	var viewContext = new ViewContext(controller.ControllerContext, new FakeView(), controller.ViewData, controller.TempData, TextWriter.Null);
	return new HtmlHelper(viewContext, new ViewPage());
}

public class FakeView : IView
{
	public void Render(ViewContext viewContext, TextWriter writer)
	{
		throw new InvalidOperationException();
	}
}

Solution 3 - asp.net Mvc

The HtmlHelper is part of the View mechanism by design and should be considered separate to the Controller and Model parts of MVC. I am not sure why you would want to generate controls inside the controller as it's role is to deliver the Data to the view for rendering.

I am not saying that you cannot achieve it, but for good design it would be better.

Can you explain what you are trying to achieve and then we could look at doing it in an "MVC way"?

Solution 4 - asp.net Mvc

using System.Web.Mvc;
using System.Web.Mvc.Html;

var h = new HtmlHelper<Effort>(new ViewContext(ControllerContext, new WebFormView(ControllerContext, "omg"), new ViewDataDictionary(), new TempDataDictionary(), new StringWriter()), new ViewPage());

h.DisplayFor(e => Model.Efforts[i].Content.Offer.Price1.Value)

Solution 5 - asp.net Mvc

For .NET Core 2 MVC: https://github.com/aspnet/Mvc/issues/7321

using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Infrastructure;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.AspNetCore.Mvc.Routing;
using Microsoft.AspNetCore.Mvc.ViewEngines;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.Mvc.ViewFeatures.Internal;
using Microsoft.Extensions.Options;
using System.IO;
using System.Text.Encodings.Web;
using System.Threading.Tasks;


    public class HelperGenerator
    {
        private readonly IHtmlGenerator _htmlGenerator;
        private readonly ICompositeViewEngine _compositeViewEngine;
        private readonly IModelMetadataProvider _modelMetadataProvider;
        private readonly IViewBufferScope _viewBufferScope;
        private readonly IActionContextAccessor _actionContextAccessor;
        private readonly HtmlHelperOptions _htmlHelperOptions;

        public HelperGenerator(IHtmlGenerator htmlGenerator, ICompositeViewEngine compositeViewEngine, IModelMetadataProvider modelMetadataProvider, IViewBufferScope viewBufferScope, IActionContextAccessor actionContextAccessor, IOptions<MvcViewOptions> options)
        {
            _htmlGenerator = htmlGenerator;
            _compositeViewEngine = compositeViewEngine;
            _modelMetadataProvider = modelMetadataProvider;
            _viewBufferScope = viewBufferScope;
            _actionContextAccessor = actionContextAccessor;
            _htmlHelperOptions = options.Value.HtmlHelperOptions;
        }
        public IHtmlHelper HtmlHelper(ViewDataDictionary ViewData, ITempDataDictionary TempData)
        {
            var helper = new HtmlHelper(_htmlGenerator, _compositeViewEngine, _modelMetadataProvider, _viewBufferScope, HtmlEncoder.Default, UrlEncoder.Default);
            var viewContext = new ViewContext(_actionContextAccessor.ActionContext,
               new FakeView(),
               ViewData,
               TempData,
               TextWriter.Null,
               _htmlHelperOptions);
            helper.Contextualize(viewContext);
            return helper;
        }
        private class FakeView : IView
        {
            public string Path => "View";

            public Task RenderAsync(ViewContext context)
            {
                return Task.FromResult(0);
            }
        }
    }

Make sure to register in services:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

Solution 6 - asp.net Mvc

If someone is trying to do this from without a Controller (like when unit testing), there are further problems to deal with, as many of these methods (which I know, were not a testing scenario, but for that scenario) were throwing Null exceptions (ViewContext.ScopeCache). You can see this by the following (note all of these ways require a ViewContext instance to be formed, which is one of the parameters you insert into the constructor of the HtmlHelper instance, so on that object):

viewContext.UnobtrusiveJavaScriptEnabled = false;

Simply setting that value throws an exception with many of these methods, but the problem was fixed for me by this answer, see how he gets an HtmlHelper (see also here).

Solution 7 - asp.net Mvc

  • using System.Web.Mvc;

  • using System.Web.Mvc.Html;

      HtmlHelper helper = new HtmlHelper(new ViewContext(ControllerContext, new            WebFormView(ControllerContext, "Index"), new ViewDataDictionary(), new TempDataDictionary(), new System.IO.StringWriter()), new ViewPage());
        
    

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionGilView Question on Stackoverflow
Solution 1 - asp.net MvcMauricio SchefferView Answer on Stackoverflow
Solution 2 - asp.net MvcVitaliy UlantikovView Answer on Stackoverflow
Solution 3 - asp.net MvcRichardView Answer on Stackoverflow
Solution 4 - asp.net MvcAnubisView Answer on Stackoverflow
Solution 5 - asp.net MvcjonmeyerView Answer on Stackoverflow
Solution 6 - asp.net MvcNicholas PetersenView Answer on Stackoverflow
Solution 7 - asp.net MvcHossein HajizadehView Answer on Stackoverflow