自定义Html助手通过视图.cshtml文件

时间:2016-05-19 10:51:23

标签: html asp.net-mvc razor html-helper

我正在尝试创建自己的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而不是使用字符串生成器?

2 个答案:

答案 0 :(得分:0)

是。您可以使用模板化HTML帮助程序将视图(HTML元素)与模型分开。

但是,缺点是您通常必须将模板放在/Views/Shared/DisplayTemplates文件夹或代表当前控制器的视图文件夹内的/DisplayTemplates文件夹中。在后一种情况下,您只能使用该特定文件夹中的模板。可以创建一个自定义视图引擎,将默认模板作为DLL文件的资源 - 请参阅MvcSiteMapProvider project以获取示例视图引擎实现。

模板化HTML帮助程序示例

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

MyHelperModel.cshtml

当没有传递templateName参数时(或null),默认约定使用与模型同名的显示模板。因此,这将是我们的默认HTML帮助程序格式。请注意,您可以在默认情况下将HTML元素硬编码到帮助程序中,而不是使用模板(或者更进一步创建视图引擎)。

如上所述,这应该在/Views/Shared/DisplayTemplates/文件夹中,但您可以创建自定义视图引擎以从DLL中提取默认模板。

@model MyHelperModel

<h3>@Model.Title</h3>
<p>@Model.Body</p>

CustomHtmlHelperTemplate.cshtml

这是一个命名模板,可以在应用程序中用于更改应用于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");