I would create a controller that response with the third-party IHtmlContent created through IHtmlHelper interface without using View() method. Actually I'm using a workaround:
I have created an extension function of IHtmlHelper that behaves like a "master" and other static function that behaves like "slaves". The master function call slaves based on data structure that It has received as a parameter. Slaves create the IHtmlContent based on third-party library. When all slave functions are completed, the controller send back the response. This behaviour is inside cshtml view called by controller.
Is possible to have IHtmlHelper as controller constructor parameter using dependency Injection?
Something like
public class MyTestController
{
private readonly IHtmlHelper _html;
public MyTestController(IHtmlHelper html) {
_html = html;
}
}
If it were possible I would simplify many operations because I'm using this Master/Slave functions to replicate the behaviours of a class
Here you can find a pure example of how my code works now and how I would like to change it https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs
I need this component because the third-party library is an extension of IHtmlHelper
Short answer : Yes .
If you look into the source code of MVC, you will find that the IHtmlHelper is registered as a transient service :
internal static void AddViewServices(IServiceCollection services)
{
...
//
// HTML Helper
//
services.TryAddTransient<IHtmlHelper, HtmlHelper>();
services.TryAddTransient(typeof(IHtmlHelper<>), typeof(HtmlHelper<>));
services.TryAddSingleton<IHtmlGenerator, DefaultHtmlGenerator>();
services.TryAddSingleton<ModelExpressionProvider>();
// ModelExpressionProvider caches results. Ensure that it's re-used when the requested type is IModelExpressionProvider.
services.TryAddSingleton<IModelExpressionProvider>(s => s.GetRequiredService<ModelExpressionProvider>());
services.TryAddSingleton<ValidationHtmlAttributeProvider, DefaultValidationHtmlAttributeProvider>();
services.TryAddSingleton<IJsonHelper, DefaultJsonHelper>();
...
}
In other words, you could inject the IHtmlHelper service as you like.
Just as a reminder, we should always prefer to using IHtmlHelper within View Layer.
I thank Itminus for answering me.
However call IHtmlHelper on controller constructor it is not enough, you must contextualize IHtmlHelper before using it.
I want to share another solution that I found and solve my problem, maybe It can be useful for other users. Please see https://gist.github.com/Blackleones/eb0d02b9dd99164271af88e22143d72b#file-example-cs to remember what my goal is.
public class MyHtmlHelperAdapter
{
public IHtmlHelper _html;
public NubessHtmlHelperAdapter(IHtmlHelper html)
{
_html = html;
}
public IHtmlHelper Html => _html;
public ViewContext ViewContext => _html.ViewContext;
public HttpContext HttpContext => _html.ViewContext.HttpContext;
public ViewDataDictionary ViewData => _html.ViewData;
public IServiceProvider provider => _html.ViewContext.HttpContext.RequestServices;
}
public static class MyBuilderExtension
{
public static MyBuilder Nubess(this IHtmlHelper html)
{
return new MyBuilder(new MyHtmlHelperAdapter(html));
}
}
where MyBuilder is
public class MyBuilder
{
private readonly MyHtmlHelperAdapter _htmlHelper;
public MyBuilder(MyHtmlHelperAdapter htmlHelper)
{
_htmlHelper = htmlHelper;
}
public FormBuilder<object> Form<T>(IDictionary<string, string> customizeArgs = null, FormBuilder<object> externalForm = null)
{
return new FormBuilder(_htmlHelper, typeof(T), customizeArgs, externalForm).Build();
}
}
public class FormBuilder
{
private MyHtmlHelperAdapter _htmlHelper;
private readonly IStringLocalizer<SharedResources> _localizer;
private readonly LinkGenerator _linkGenerator;
private readonly IEngine _engine;
private readonly IEngineElement _element;
private readonly Type _typeDescriptor;
private readonly IDictionary<string, string> _descriptorArgs;
/* variabili per semplificare la gestione del builder */
private readonly FormBuilder<object> Form;
private readonly FormConfig Config;
private readonly IList<FormGroupConfig> Groups;
private readonly IList<FormItemConfig> Items;
private readonly IDictionary<string, string> FormOptions;
private readonly string _clientPrefix = "smtForm_{0}_";
public FormBuilder(MyHtmlHelperAdapter htmlHelper, Type typeDescriptor, IDictionary<string, string> ModelCustomizeArgs = null, FormBuilder<object> externalForm = null)
{
_htmlHelper = htmlHelper;
_localizer = _htmlHelper.provider.GetRequiredService<IStringLocalizer<SharedResources>>() ?? throw new ArgumentNullException();
_linkGenerator = _htmlHelper.provider.GetRequiredService<LinkGenerator>() ?? throw new ArgumentNullException();
_engine = _htmlHelper.provider.GetRequiredService<IEngine>() ?? throw new ArgumentNullException();
//code..
}
public FormBuilder<object> Build()
{
//code..
return Form;
}
//methods..
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With