Использование HtmlHelper в контроллере

Можно ли использовать HtmlHelper в контроллере, например, чтобы получить метод TextBox (...)? не то, что я не могу написать html, который он генерирует сам, но я просто хочу понять, как это работает, чтобы я мог создать наилучшее решение.

Ответ 1

Здесь приведен пример из this:

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

Обратите внимание, что это взломать, это можно сделать, но я не думаю, что есть веские причины для этого...

Ответ 2

Вы можете использовать такой метод:

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();
    }
}

Ответ 3

HtmlHelper является частью механизма просмотра по дизайну и должен рассматриваться отдельно от частей контроллера и модели MVC. Я не уверен, почему вы хотите генерировать элементы управления внутри контроллера, поскольку роль заключается в доставке данных в представление для рендеринга.

Я не говорю, что вы не можете этого достичь, но для хорошего дизайна было бы лучше.

Можете ли вы объяснить, что вы пытаетесь достичь, и тогда мы могли бы посмотреть на это с помощью "способа MVC"?

Ответ 4

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)

Ответ 5

Для.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);
            }
        }
    }

Обязательно зарегистрируйтесь в сервисах:

services.AddSingleton<IActionContextAccessor, ActionContextAccessor>();

Ответ 6

Если кто-то пытается это сделать без контроллера (например, при модульном тестировании), возникают дополнительные проблемы, так как многие из этих методов (которые, как я знаю, не были сценарием тестирования, но для этого сценария) бросали Null исключения (ViewContext.ScopeCache). Вы можете видеть это следующим образом (обратите внимание, что все эти способы требуют создания экземпляра ViewContext, который является одним из параметров, которые вы вставляете в конструктор экземпляра HtmlHelper, и так на этом объекте):

viewContext.UnobtrusiveJavaScriptEnabled = false;

Просто установка этого значения вызывает исключение со многими из этих методов, но проблема была исправлена ​​для меня этим ответом, см., как он получает HtmlHelper ( см. также здесь).

Ответ 7

  • с использованием System.Web.Mvc;
  • используя 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());