Umbraco 7 Визуализация макросов с частичным видом

В Umbraco 7.0.3 I:

  1. Создан тип данных под названием «Контейнер макросов» с редактором свойств контейнера макросов.
  2. Создан тип документа под названием «Контактная форма» со свойством «Тело» с контейнером макроса «Тип».
  3. Создан частичный вид с именем _contactForm.cshtml (в Views\MacroPartials)
  4. Создан макрос под названием «Контактная форма» с частичным представлением MVC _contactFrom.cshtml
  5. Добавлен контент типа «Контактная форма» под названием «Свяжитесь с нами».
  6. Добавлен макрос контактной формы в свойство контейнера макросов под названием «Тело» на моей странице «Свяжитесь с нами».

Затем у меня есть Surface Controller, который я вызываю с некоторыми AJAX для отображения страницы (точнее, свойства страницы Body):

public class JsController : SurfaceController
{
    public ActionResult GetPage(int id)
    {
        var page = new Node(id);

        if (page == null || page.GetProperty("body") == null)
            return Content(@"Hmm, something went wrong. Unable to find what you're looking for.");

        return Content(page.GetProperty("body").Value);
    }
}

Эта настройка почти работает, но проблема в том, что вместо отображаемой формы возвращается следующее:

<!--?UMBRACO_MACRO macroAlias="ContactForm" /-->

Итак, теперь мне нужно отобразить этот макрос\форму\частичное представление... Я думаю, что мне, вероятно, нужно сделать это в контроллере, но если я смогу сделать это с другой стороны (через Javascript), это тоже сработает. Есть ли функция Umbraco, которую я могу вызвать в контроллере для отображения макроса на основе идентификатора страницы и псевдонима макроса?


person Serj Sagan    schedule 20.02.2014    source источник


Ответы (3)


Итак, проведя несколько часов, злясь на то, как болезненно глупа команда Umbraco сделала этот процесс, читая темы вроде этот и это, я, наконец, нашел довольно уродливый, но работающий способ... все было бы намного проще, если бы конструктор класса PublishedContentRequest не был internal!

В любом случае, вот что мне пришлось сделать: 1) Расширить EnsurePublishedContentRequestAttribute

public class CreatePublishedContentRequestAttribute
    : EnsurePublishedContentRequestAttribute
{
    public CreatePublishedContentRequestAttribute() : base(0) { }

    protected override void ConfigurePublishedContentRequest(
        PublishedContentRequest publishedContentRequest,
        ActionExecutedContext filterContext)
    {
        var contentId = filterContext.RouteData.Values["id"];
        int id = 0;

        if (contentId != null && int.TryParse(contentId.ToString(), out id))
        {
            var content = UmbracoContext.ContentCache.GetById(id);
            publishedContentRequest.PublishedContent = content;

            var defaultLanguage = Language.GetAllAsList().FirstOrDefault();
            publishedContentRequest.Culture = (defaultLanguage == null)
                ? CultureInfo.CurrentUICulture
                : new CultureInfo(defaultLanguage.CultureAlias);

            publishedContentRequest.ConfigureRequest();

            HttpContext.Current.Session["PublishedContentRequest"]
                = publishedContentRequest;
        }
    }
}

2) Перенаправить на действие, украшенное этим атрибутом, которое перенаправляет обратно на мое действие GetPage и извлекает PCR из файла Session. Теперь мы можем визуализировать наш макрос:

public ActionResult GetPage(int id)
{
    var publishedContent = UmbracoContext.ContentCache.GetById(id);
    if (publishedContent == null || publishedContent.GetProperty("body") == null)
    { return Content(@"Unable to find what you're looking for."); }

    if (UmbracoContext.PublishedContentRequest == null
        && Session["PublishedContentRequest"] == null)
    { return RedirectToAction("CreatePublishedContentRequest", new { id }); }

    UmbracoContext.PublishedContentRequest =
        (PublishedContentRequest) Session["PublishedContentRequest"];
    Session["PublishedContentRequest"] = null;

    UmbracoContext.HttpContext.Items["pageID"] = id;

    return Content(GetHtmlContent(publishedContent));
}

[CreatePublishedContentRequest]
public ActionResult CreatePublishedContentRequest(int id)
{
    return RedirectToAction("GetPage", new { id });
}

private string GetHtmlContent(IPublishedContent publishedContent)
{
    string content = publishedContent.GetProperty("body").Value.ToString();
    if (string.IsNullOrEmpty(content) || !content.Contains("UMBRACO_MACRO"))
    { return content;}

    int startIndex = content.IndexOf("macroAlias=") + 12;
    int length = content.LastIndexOf('"') - startIndex;
    var macroAlias = content.Substring(startIndex, length);

    return (Umbraco.RenderMacro(macroAlias) ?? new HtmlString("")).ToString();
}

Это работает, но это довольно хакерские вещи. Если бы команда Umbraco создала конструктор PublishedContentRequest public, он мог бы быть намного чище. Конечно, вероятно, есть лучший способ сделать это, если это так, я весь в ушах.

person Serj Sagan    schedule 21.02.2014
comment
Конструктор класса PublishedContentRequest теперь общедоступен в более новых версиях Umbraco, но мне не удалось найти подходящее использование для этого варианта использования. - person Marko Jovanov; 13.04.2016

нельзя было использовать umbraco.library.RenderMacroContent?

person Vlax    schedule 27.07.2015
comment
Комментарий без проверенного примера кода не очень полезен. - person Serj Sagan; 13.04.2016

Имя вашего контроллера должно содержать слово «Surface».

JsSurfaceController

Также добавьте атрибут [HttpPost] в метод ActionResult.

http://our.umbraco.org/documentation/Reference/Mvc/surface-controllers http://our.umbraco.org/documentation/Reference/Mvc/forms

person Daniel Bardi    schedule 27.03.2014
comment
Ни одно из этих предложений не нужно и даже неправильно. [HttpPost] был бы нужен только в том случае, если бы у меня было 2 метода с одинаковым именем или я пытался предотвратить GET-трафик, которым я не являюсь, и на самом деле сейчас на него идет только GET-трафик... Сделка с Surface является только предложением. ..это на самом деле не требуется. - person Serj Sagan; 31.03.2014