Проблемы с RazorEngine с @Html

Я использую RazorEngine для визуализации некоторого базового контента (очень грубой системы управления контентом).

Он отлично работает, пока я не добавлю синтаксис @Html в разметку.

Если разметка содержит @html, я получаю следующую ошибку:

Невозможно скомпилировать шаблон. Имя «Html» не существует в текущем контексте

Это представление, которое отображает разметку:

@Model Models.ContentPage @{ ViewBag.Title = Model.MetaTitle; Layout = "~/Views/Shared/Templates/_" + Model.Layout + "Layout.cshtml"; } @Html.Raw(RazorEngine.Razor.Parse(Model.Markup, Model)) 

Я видел на сайте Codeplex для RazorEngine использование @Html (я знаю, что версия устарела, и я получил свою версию через nuget).

Любая помощь в этом была бы замечательной.

    Свойства помощника Html и Url являются актуальными функциями реализации MVC Razor в их механизмах просмотра. В настоящее время Html и Url не поддерживаются без специального шаблона базы данных.

    Предстоящая версия v3 будет сопровождаться соответствующим выпуском RazorEngine.Web, который, мы надеемся, будет содержать базовый шаблон, совместимый с MVC3, с поддержкой Html и Url .

    Пример, который я написал на главной странице проекта, является просто примером использования настраиваемого базового шаблона.

    Вы можете узнать больше о v3 на странице https://github.com/Antaris/RazorEngine

    Проверьте страницу https://github.com/Antaris/RazorEngine/wiki/6.-Encoding-Values . Я копирую / миную его здесь:

    По умолчанию RazorEngine настроен на кодирование как HTML. Иногда это создает проблемы, когда определенные символы кодируются как HTML, когда вы хотите, чтобы результат был как есть.

    Чтобы вывести что-то в необработанном формате, используйте встроенный метод @Raw (), как показано в следующем примере:

     string template = "@Raw(Model.Data)"; var model = new { Data = "My raw double quotes appears here \"hello!\"" }; string result = Razor.Parse(template, model); 

    Это должно привести к:

     My raw double quotes appears here "hello!" 

    Это довольно старый вопрос, но я нашел хороший ответ на coderwall . Решение состоит в том, чтобы использовать:

     @(new RawString("Bold!")) 

    или просто:

     @(new RawString(Model.YourHTMLStrinInModel)) 

    Надеюсь, это полезно.

    Это больше года, но так как я не нашел рабочую копию в любом месте в Интернете, а страница github неактивна, я решил поделиться своей реализацией с добавлением синтаксиса @Html helper для RazorEngine. Вот реализация, с которой я закончил, используя реализацию Абу Хайдера в качестве отправной точки.

    Предоставлено комментарий miketrash: если вы пытаетесь использовать @ Html.Action (), вам нужно будет добавить RequestContext (вы можете использовать HttpContext.Current.Request.RequestContext ). Я не включил контекст запроса, потому что он не всегда доступен для моего приложения.

     [RequireNamespaces("System.Web.Mvc.Html")] public class HtmlTemplateBase:TemplateBase, IViewDataContainer { private HtmlHelper helper = null; private ViewDataDictionary viewdata = null; public HtmlHelper Html { get { if (helper == null) { var writer = this.CurrentWriter; //TemplateBase.CurrentWriter var vcontext = new ViewContext() { Writer = writer, ViewData = this.ViewData}; helper = new HtmlHelper(vcontext, this); } return helper; } } public ViewDataDictionary ViewData { get { if (viewdata == null) { viewdata = new ViewDataDictionary(); viewdata.TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = string.Empty }; if (this.Model != null) { viewdata.Model = Model; } } return viewdata; } set { viewdata = value; } } public override void WriteTo(TextWriter writer, object value) { if (writer == null) throw new ArgumentNullException("writer"); if (value == null) return; //try to cast to RazorEngine IEncodedString var encodedString = value as IEncodedString; if (encodedString != null) { writer.Write(encodedString); } else { //try to cast to IHtmlString (Could be returned by Mvc Html helper methods) var htmlString = value as IHtmlString; if (htmlString != null) writer.Write(htmlString.ToHtmlString()); else { //default implementation is to convert to RazorEngine encoded string encodedString = TemplateService.EncodedStringFactory.CreateEncodedString(value); writer.Write(encodedString); } } } } 

    Мне также пришлось переопределить метод WriteTo для TemplateBase , потому что иначе RazorEngine будет html-кодировать результат вспомогательного метода, означая, что вы избежите «<», «>» и кавычек (см. Этот вопрос ). Завершение добавляет проверку того, что значение является IHtmlString прежде чем IHtmlString к выполнению кодирования.

    Мои извинения, у меня нет требуемой 50 репутации, чтобы добавить комментарий, чтобы ответить.

    Если кому-то интересно (как JamesStuddart был), метод SetTemplateBase () отсутствует, но вы можете создать экземпляр конфигурации для инициализации службы с помощью базового шаблона.

    Из http://razorengine.codeplex.com/discussions/285937 Я адаптировал свой код, чтобы он выглядел так:

     var config = new RazorEngine.Configuration.TemplateServiceConfiguration { BaseTemplateType = typeof(MyHtmlTemplateBase<>) }; using (var service = new RazorEngine.Templating.TemplateService(config)) { // Use template service. Razor.SetTemplateService(service); result = Razor.Parse(templateString, model); } 

    Модификация ответа mao47 для последнего синтаксиса бритвы, это также поддержит частичные представления.

     using System; using System.Collections.Concurrent; using System.IO; using System.Linq; using System.Web.Hosting; using System.Xml.Linq; using RazorEngine.Configuration; using RazorEngine.Templating; public static class DynamicRazorTemplateParser { private static readonly IRazorEngineService service = RazorEngineService.Create(TemplateServiceConfiguration); public static string RunCompile(string template, string placeholder, T model, DynamicViewBag viewBag) where T : class { var templateSource = new LoadedTemplateSource(template); return RunCompile(templateSource, placeholder, model, viewBag); } public static string RunCompile(ITemplateSource template, string placeholder, T model, DynamicViewBag viewBag) where T : class { return service.RunCompile(template, placeholder, model.GetType(), model, viewBag); } public static string RunCompile(ITemplateSource template, string placeholder) { return service.RunCompile(template, placeholder); } private static TemplateServiceConfiguration TemplateServiceConfiguration { get { var config = new TemplateServiceConfiguration { BaseTemplateType = typeof(HtmlTemplateBase<>), TemplateManager = new TemplateManager() }; //TODO: Is this the best way? var xDocument = XDocument.Load(AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/Views/Web.config"); if (xDocument.Root != null) { var sysWeb = xDocument.Root.Element("system.web.webPages.razor"); if (sysWeb == null) return config; var pages = sysWeb.Element("pages"); if (pages != null) { var namespaces = pages.Element("namespaces"); if (namespaces != null) { var namespacesAdd = namespaces.Elements("add") .Where(x => x.Attribute("namespace") != null) .Select(x => x.Attribute("namespace").Value ); foreach (var ns in namespacesAdd) { config.Namespaces.Add(ns); } } } } return config; } } private class TemplateManager : ITemplateManager { private readonly ConcurrentDictionary _dynamicTemplates = new ConcurrentDictionary(); private readonly string baseTemplatePath; public TemplateManager() { baseTemplatePath = HostingEnvironment.MapPath("~/Views/"); } public ITemplateSource Resolve(ITemplateKey key) { ITemplateSource templateSource; if (this._dynamicTemplates.TryGetValue(key, out templateSource)) return templateSource; string template = key.Name; var ubuilder = new UriBuilder(); ubuilder.Path = template; var newURL = ubuilder.Uri.LocalPath.TrimStart('/'); string path = Path.Combine(baseTemplatePath, string.Format("{0}", newURL)); string content = File.ReadAllText(path); return new LoadedTemplateSource(content, path); } public ITemplateKey GetKey(string name, ResolveType resolveType, ITemplateKey context) { return new NameOnlyTemplateKey(name, resolveType, context); } public void AddDynamic(ITemplateKey key, ITemplateSource source) { this._dynamicTemplates.AddOrUpdate(key, source, (k, oldSource) => { if (oldSource.Template != source.Template) throw new InvalidOperationException("The same key was already used for another template!"); return source; }); } } } using System; using System.IO; using System.Web; using System.Web.Mvc; using System.Web.Routing; using RazorEngine.Templating; using RazorEngine.Text; // ReSharper disable ClassWithVirtualMembersNeverInherited.Global // ReSharper disable MemberCanBePrivate.Global namespace Common.Core.Razor { [RequireNamespaces("System.Web.Mvc.Html")] public class HtmlTemplateBase : RazorEngine.Templating.HtmlTemplateBase, IViewDataContainer { private HtmlHelper helper; private ViewDataDictionary viewdata; private TempDataDictionary tempdata; private AjaxHelper ajaxHelper; private ViewContext viewContext; private UrlHelper urlHelper; private readonly RequestContext _requestContext = HttpContext.Current.Request.RequestContext; public UrlHelper Url => urlHelper ?? (urlHelper = new UrlHelper(_requestContext)); public ViewContext ViewContext { get { if (viewContext != null) return viewContext; viewContext = GetViewContext(); return viewContext; } } public AjaxHelper Ajax { get { if (ajaxHelper != null) return ajaxHelper; ajaxHelper = new AjaxHelper(ViewContext, this); return ajaxHelper; } } public HtmlHelper Html { get { if (helper != null) return helper; helper = new HtmlHelper(ViewContext, this); return helper; } } public ViewDataDictionary ViewData { get { if (viewdata == null) { viewdata = new ViewDataDictionary { TemplateInfo = new TemplateInfo() { HtmlFieldPrefix = string.Empty } }; if (Model != null) { viewdata.Model = Model; } } return viewdata; } set { viewdata = value; } } public TempDataDictionary TempData { get { return tempdata ?? (tempdata = new TempDataDictionary()); } set { tempdata = value; } } public virtual string RenderView() { using (var writer = new StringWriter()) { ViewContext.View.Render(ViewContext, CurrentWriter); return writer.GetStringBuilder().ToString(); } } private ViewContext GetViewContext() { if (HttpContext.Current == null) throw new NotImplementedException(); var requestContext = _requestContext; var controllerContext = ControllerContext(requestContext); var view = GetView(requestContext, controllerContext); //Can't check if string writer is closed, need to catch exception try { var vContext = new ViewContext(controllerContext, view, ViewData, TempData, CurrentWriter); return vContext; } catch { using (var sw = new StringWriter()) { var vContext = new ViewContext(controllerContext, view, ViewData, TempData, sw); return vContext; } } } private IView GetView(RequestContext requestContext, ControllerContext controllerContext) { if ((string)requestContext.RouteData.DataTokens["Action"] != null) { requestContext.RouteData.Values["action"] = (string)requestContext.RouteData.DataTokens["Action"]; } var action = requestContext.RouteData.GetRequiredString("action"); var viewEngineResult = ViewEngines.Engines.FindPartialView(controllerContext, action); if (viewEngineResult != null && viewEngineResult.View != null) { return viewEngineResult.View; } viewEngineResult = ViewEngines.Engines.FindView(controllerContext, action, null); if (viewEngineResult == null) { throw new Exception("No PartialView assigned in route"); } return viewEngineResult.View; } public void SetView(string view) { _requestContext.RouteData.DataTokens["Action"] = view; } private ControllerContext ControllerContext(RequestContext requestContext) { ControllerBase controllerBase; var routeDataValue = "EmptyController"; if (requestContext.RouteData.Values["controller"] != null && (string)requestContext.RouteData.Values["controller"] != routeDataValue) { var controllerName = (string)requestContext.RouteData.Values["controller"]; IController controller = ControllerBuilder.Current.GetControllerFactory().CreateController(requestContext, controllerName); controllerBase = controller as ControllerBase; } else { var controller = new EmptyController(); controllerBase = controller; //ControllerBase implements IController which this returns requestContext.RouteData.Values["controller"] = routeDataValue; } var controllerContext = new ControllerContext(requestContext.HttpContext, requestContext.RouteData, controllerBase); return controllerContext; } private class EmptyController : Controller { } public override void WriteTo(TextWriter writer, object value) { if (writer == null) throw new ArgumentNullException("writer"); if (value == null) return; //try to cast to RazorEngine IEncodedString var encodedString = value as IEncodedString; if (encodedString != null) { writer.Write(encodedString); } else { //try to cast to IHtmlString (Could be returned by Mvc Html helper methods) var htmlString = value as IHtmlString; if (htmlString != null) writer.Write(htmlString.ToHtmlString()); else { //default implementation is to convert to RazorEngine encoded string base.WriteTo(writer, value); } } } } } 

    Простое решение Html.Raw ! Требуется 3 шага

    Шаг 1: Наследовать от TemplateBase:

     public class HtmlSupportTemplateBase : TemplateBase { public HtmlSupportTemplateBase() { Html = new MyHtmlHelper(); } public MyHtmlHelper Html { get; set; } } 

    Шаг 2. Создайте объект, который позволяет использовать все методы Html, используемые вашим шаблоном. В этом примере html.Raw и Html.Encode становятся доступными в cshtml. шаблон

     public class MyHtmlHelper { ///  /// Instructs razor to render a string without applying html encoding. ///  ///  ///  public IEncodedString Raw(string htmlString) { return new RawString(htmlString); } public string Encode(string value) { return System.Net.WebUtility.HtmlEncode(value); } public string Encode(object value) { return "do whatever"; } } 

    Шаг 3:

     var config = new TemplateServiceConfiguration { TemplateManager = templateManager, BaseTemplateType = typeof(HtmlSupportTemplateBase<>) }; 
    Давайте будем гением компьютера.