asp.net-mvc 在控制器中使用 HtmlHelper
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/621235/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Using HtmlHelper in a Controller
提问by Gil
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.
是否可以在控制器中使用 HtmlHelper,例如获取 TextBox(...) 方法?并不是我不能编写它自己生成的 html,而是我只想了解它是如何工作的,以便我可以创建最佳解决方案。
采纳答案by Mauricio Scheffer
Here's an example adapted from this:
这是一个改编自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...
请注意,这是一个黑客,它可以完成,但我认为没有任何充分的理由这样做......
回答by Vitaliy Ulantikov
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();
}
}
回答by Richard
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.
HtmlHelper 按照设计是 View 机制的一部分,应该被视为独立于 MVC 的 Controller 和 Model 部分。我不确定您为什么要在控制器内生成控件,因为它的作用是将数据传送到视图进行渲染。
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"?
您能解释一下您要实现的目标,然后我们可以考虑以“MVC 方式”来实现吗?
回答by Anubis
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)
回答by jonmeyer
For .NET Core 2 MVC: https://github.com/aspnet/Mvc/issues/7321
对于 .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>();
回答by Nicholas Petersen
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 ViewContextinstance to be formed, which is one of the parameters you insert into the constructor of the HtmlHelper instance, so on that object):
如果有人试图在没有控制器的情况下执行此操作(例如单元测试时),则还有更多问题需要处理,因为这些方法中有许多(我知道,这不是测试场景,但对于该场景)抛出 Null异常(ViewContext.ScopeCache)。您可以通过以下方式看到这一点(注意所有这些方式都需要ViewContext形成一个实例,这是您插入到 HtmlHelper 实例的构造函数中的参数之一,依此类推):
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).
使用这些方法中的许多方法简单地设置该值会引发异常,但此答案已为我解决了问题,看看他是如何获得的HtmlHelper(另请参见此处)。
回答by Hossein Hajizadeh
- 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());
- 使用 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());

