Umbraco 7 Частичное представление макроса

В Umbraco 7.0.3 я:

  1. Создан тип данных с именем Macro Container с помощью редактора свойств контейнера Macro.
  2. Создан тип документа с именем Contact Form со свойством Body с типом макроконтейнер
  3. Создано частичное представление с именем _contactForm.cshtml (в Views\MacroPartials)
  4. Создан макрос с названием Contact Form с частичным представлением MVC _contactFrom.cshtml
  5. Добавлен контент типа контактной формы под названием Связаться с нами
  6. Добавлен макрос контактной формы в свойство контейнера макроса, которое называется Body, на моей странице контактов

Тогда у меня есть 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, которую я могу вызвать в контроллере для рендеринга макроса на основе идентификатора страницы и псевдонима макроса?

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, это могло бы быть намного, намного чище. Конечно, возможно, есть лучший способ сделать это, если это так, у меня все уши.

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

Ваше имя контроллера должно содержать "Поверхность" в своем имени.

JsSurfaceController

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

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

Другие вопросы по тегам