我正在尝试创建自己的Html帮助程序,这将允许我在任何Web应用程序中重用某些功能。如果我想在单个wep应用程序中重用此控件,我可以创建一个.cshtml文件并通过Html.Partial("")方法调用它并传入模型。
然而,由于我有自定义Html助手的类库项目,因此我使用字符串构建器创建html,就像这个简化版本一样
StringBuilder htmlBuilder = new StringBuilder("<div class='myClass'>")
foreach(var item in MyItems)
{
htmlBuilder.Append($"item : {item.Name}");
}
htmlBuilder.append("</div>");
这使得特别是当我的控件获得更多功能时难以维护。
是否有推荐的方法来利用剃刀引擎,我可以使用模型在.cshtml文件中编写html,然后生成html而不是使用字符串生成器?
答案 0 :(得分:0)
是。您可以使用模板化HTML帮助程序将视图(HTML元素)与模型分开。
但是,缺点是您通常必须将模板放在/Views/Shared/DisplayTemplates
文件夹或代表当前控制器的视图文件夹内的/DisplayTemplates
文件夹中。在后一种情况下,您只能使用该特定文件夹中的模板。可以创建一个自定义视图引擎,将默认模板作为DLL文件的资源 - 请参阅MvcSiteMapProvider project以获取示例视图引擎实现。
public class MyHelperModel
{
public string Title { get; set; }
public string Body { get; set; }
}
// Extension Methods for HTML helper
public static class MyHelperExtensions
{
public static MvcHtmlString MyHelper(this HtmlHelper helper, string title, string body)
{
return MyHelper(helper, title, body, null);
}
public static MvcHtmlString MyHelper(this HtmlHelper helper, string title, string body, string templateName)
{
// Build the model
var model = BuildModel(title, body);
// Create the HTML helper for the model
return CreateHtmlHelperForModel(helper, model)
.DisplayFor(m => model, templateName);
}
private static MyHelperModel BuildModel(string title, string body)
{
// Map to model
return new MyHelperModel
{
Title = title,
Body = body
};
}
private static HtmlHelper<TModel> CreateHtmlHelperForModel<TModel>(this HtmlHelper helper, TModel model)
{
return new HtmlHelper<TModel>(helper.ViewContext, new ViewDataContainer<TModel>(model));
}
}
public class ViewDataContainer<TModel>
: IViewDataContainer
{
public ViewDataContainer(TModel model)
{
ViewData = new ViewDataDictionary<TModel>(model);
}
public ViewDataDictionary ViewData { get; set; }
}
当没有传递templateName
参数时(或null
),默认约定使用与模型同名的显示模板。因此,这将是我们的默认HTML帮助程序格式。请注意,您可以在默认情况下将HTML元素硬编码到帮助程序中,而不是使用模板(或者更进一步创建视图引擎)。
如上所述,这应该在/Views/Shared/DisplayTemplates/
文件夹中,但您可以创建自定义视图引擎以从DLL中提取默认模板。
@model MyHelperModel
<h3>@Model.Title</h3>
<p>@Model.Body</p>
这是一个命名模板,可以在应用程序中用于更改应用于HTML帮助程序的HTML元素。
如上所述,这应该在/Views/Shared/DisplayTemplates/
文件夹中,但您可以创建自定义视图引擎以从DLL中提取默认模板。
@model MyHelperModel
<h1>@Model.Title</h1>
<p><i>@Model.Body</i></p>
@Html.MyHelper(
"This is the default template",
"This is what happens when we don't pass a template name to the HTML helper.")
@Html.MyHelper(
"This is a custom template",
"This is a custom template with different HTML elements than the default template.",
"CustomHtmlHelperTemplate")
注意:为确保帮助程序在视图中可用,您需要在
/Views/Web.config
<system.web.webPages.razor><pages><namespaces>
文件中添加名称空间。
<system.web.webPages.razor>
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<pages pageBaseType="System.Web.Mvc.WebViewPage">
<namespaces>
<add namespace="System.Web.Mvc" />
<add namespace="System.Web.Mvc.Ajax" />
<add namespace="System.Web.Mvc.Html" />
<add namespace="System.Web.Optimization" />
<add namespace="System.Web.Routing" />
<!-- Add your namespaces here -->
<add namespace="MyProject.HtmlHelperNamespace" />
<add namespace="MyProject.HtmlHelperNamespace.Models" />
</namespaces>
</pages>
</system.web.webPages.razor>
答案 1 :(得分:0)
您可以使用以下代码在运行时维护并生成Razor View / PartialView(cshtml)的输出:
public static string GetViewPageHtml(Controller controller, object model, string viewName)
{
ViewEngineResult result = ViewEngines.Engines.FindPartialView(controller.ControllerContext, viewName);
if (result.View == null)
throw new Exception(string.Format("View Page {0} was not found", viewName));
controller.ViewData.Model = model;
StringBuilder sb = new StringBuilder();
using (StringWriter sw = new StringWriter(sb))
{
using (System.Web.UI.HtmlTextWriter output = new System.Web.UI.HtmlTextWriter(sw))
{
ViewContext viewContext = new ViewContext(controller.ControllerContext, result.View, controller.ViewData, controller.TempData, output);
result.View.Render(viewContext, output);
}
}
return sb.ToString();
}
你这样称呼它(来自控制器)
string result = GetViewPageHtml(this, viewModel, "~/Views/Home/Index.cshtml");