3

我正在尝试在表面控制器中编写一个子动作函数,该函数被宏调用以呈现 PartialView。

我需要在这个函数中访问我当前的页面属性,然后调整渲染的 PartialView。

我从 ubootstrap 上的 Jorge Lusar 代码中得到了这个,它在 HttpPost ActionResult 函数上运行良好:

var renderModel = (UmbracoRenderModel)ControllerContext.RouteData.DataTokens["umbraco"];
var currentPage = renderModel.CurrentNode.AsDynamic();

问题是我在[ChildActionOnly] PartialViewResult函数上抛出了这个错误:

Unable to cast object of type 'System.String' to type 'Umbraco.Cms.Web.Model.UmbracoRenderModel'.
on 'var renderModel = (UmbracoRenderModel)ControllerContext.RouteData.DataTokens["umbraco"];'

DataTokens["umbraco"] 中的数据似乎在两个函数之间发生变化。如果我在每一个上显示 DataTokens["umbraco"].ToString(),会发生以下情况:

[ChildActionOnly] public PartialViewResult Init() -> "Surface"显示。

[HttpPort] public HandleSubmit(myModel model) -> "Umbraco.Cms.Web.Model.UmbracoRenderModel"上显示。

感谢您在这里的任何建议。

尼古拉斯。

4

7 回答 7

6

我正在使用 Umbraco 6.0.4,它很简单:

var currentNode = Umbraco.TypedContent(UmbracoContext.PageId);
于 2013-06-05T16:40:35.207 回答
2

当我们失去uformpostroutevals.

即使我试图发布这个值,通过从表单中获取它,由

@using (Html.BeginUmbracoForm("<ActionName>", "<Controller Name>Surface"))

我在 的所有属性中仍然有 null UmbracoContext,所以看起来它没有正确初始化。

HOTFIX:我将 CurrentNodeId 传递给我通过 Ajax 发送的每个表单:

在一般母版页中,我正在创建全局 javascript 对象:

<script type="text/javascript">
  var Global = {
    //..List of another variables which can be usefull of frontend
    currentNodeId: @CurrentPage.Id
  };
</script>

在任何请求中,它都很容易Global.currentNodeId用作以下参数之一data

var sendData = {
    currentNodeId: Global.currentNodeId,
    // another params 
};

$.ajax({
    method: 'POST',
    data: JSON.stringify(sendData),
    contentType: 'application/json; charset=utf-8',
    url: '/Umbraco/Surface/<ControllerName>Surface/<ActionName>',
    dataType: 'json',
    cache: false
})

请注意,这只是一个热修复,而不是正确的解决方案!

于 2013-12-26T09:39:45.107 回答
0

要访问您的 currentPage,请在 Controller 中实现此构造函数

public class CommentSurfaceController : SurfaceController
{
    private readonly IUmbracoApplicationContext context;
    public CommentSurfaceController(IUmbracoApplicationContext context)
    {
        this.context = context;
    }
}

它使用 umbracos 依赖注入,来解决 Context 依赖,并使其可供您使用。

查看 SurfaceController 上的文档 https://github.com/umbraco/Umbraco5Docs/blob/5.1.0/Documentation/Getting-Started/Creating-a-surface-controller.md

于 2012-04-23T11:31:30.517 回答
0

虽然我更愿意找到一种更简单的方法,但我认为我找到了一个可行的解决方案。关键是区分操作方法是作为子操作(通常通过 HTTP GET)还是直接(通过 HTTP POST)调用的。

下面是一个自定义基类,它公开了一个“CurrentContent”属性,然后可以通过继承表面控制器来使用。

using System.Web.Mvc;
using Umbraco.Cms.Web;
using Umbraco.Cms.Web.Surface;
using Umbraco.Cms.Web.Model;

namespace Whatever
{
    public abstract class BaseSurfaceController : SurfaceController
    {
        private object m_currentContent = null;

        public dynamic CurrentContent
        {
            get
            {
                if (m_currentContent == null)
                {
                    if (Request.HttpMethod == "POST")
                    {
                        m_currentContent = GetContentForSubmitAction();
                    }
                    else
                    {
                        m_currentContent = GetContentForChildAction();
                    }
                }
                return m_currentContent;
            }
        }

        // from Lee Gunn's response
        // http://our.umbraco.org/forum/core/umbraco-5-general-discussion/29178-In-a-controller-how-do-I-get-the-current-pages-hiveId?p=2

        private object GetContentForChildAction()
        {
            ViewContext vc = ControllerContext.RouteData.DataTokens[
                    "ParentActionViewContext"] as ViewContext;
            var content = vc.ViewData.Model
                    as global::Umbraco.Cms.Web.Model.Content;
            return content.AsDynamic();
        }

        // from Nicholas Ruiz
        // http://our.umbraco.org/forum/core/umbraco-5-general-discussion/30928-Surface-Controller-and-Current-Node-Properties

        private object GetContentForSubmitAction()
        {
            UmbracoRenderModel rm =
                    ControllerContext.RouteData.DataTokens["umbraco"] as UmbracoRenderModel;
            if (rm == null)
            {
                return GetContentForChildAction();
            }
            return rm.CurrentNode.AsDynamic();
        }
    }
}

尽管如此,似乎应该有一种更简单的方法来做到这一点。

布莱恩

于 2012-05-30T22:49:29.410 回答
0
var currentNode = Umbraco.TypedContent(UmbracoContext.PageId);

或者,如果您在表面控制器中有对象

var currentNode = CurrentPage;

(转到定义)

 //
 // Summary:
 //     Gets the current page.
 protected virtual IPublishedContent CurrentPage { get; }

确保首先检查 null,因为在某些情况下您可以在没有解析 currentPage 上下文的情况下调用操作。

于 2016-06-01T15:45:49.333 回答
0

在 Umbraco 7.2.1 中,我使用 ChildActionOnly 属性并将模型从父级传递给局部视图。

        [ChildActionOnly]
    public ActionResult InitializeDataJson(KBMasterModel model)
    {
        var pluginUrl = string.Concat("/App_Plugins/", KBApplicationCore.PackageManifest.FolderName);
        bool isAuthenticated = Request.IsAuthenticated;
        IMember member = null;
        if (isAuthenticated)
            member = UmbracoContext.Application.Services.MemberService.GetByUsername(User.Identity.Name);
        var data = new { CurrentNode = model.IContent, IsAuthenticated = isAuthenticated, LogedOnMember = member, PluginUrl = pluginUrl };
        var json = JsonConvert.SerializeObject(data, Formatting.None, new JsonSerializerSettings() { ReferenceLoopHandling = ReferenceLoopHandling.Ignore });
        var kbData = new TLCKBData() { InitializationJson = json };
        return PartialView(kbData);
    }

现在部分视图代码:

@model TLCKBData
<script>
    (function () {
        var data = JSON.parse('@Html.Raw(Model.InitializationJson)');
        tlckb.init(data);
    })();
</script>

以及呈现子操作的父视图:

@section FooterScript {
    @{Html.RenderAction("InitializeDataJson", "KBPartialSurface", new { model = Model });}
}

注意:我正在使用强模型,因为我已经为我正在开发的插件路由劫持了我的所有文档类型,但是如果我正在路由劫持并且只使用 UmbracoTemplatePage 模型(在 Umbraco 中默认),那么我将更改我的子操作的参数只取 RenderModel 或 UmbracoTemplatePage。

然后我会以同样的方式将模型传递给它。

因为它是表面控制器上的子动作,所以已经在 Index 中加载的模型只是传递给子动作。这可以防止 GetContent 代码在管道中运行两次。

我这样做的原因是我需要一些基本数据来初始化我的 Angular API 层。比如它是否经过身份验证,登录成员是谁等。最终我在那里有一些标签,类别等。

我还想尽可能高效地构建插件,并且没有多余的逻辑。我认为所有信息都在主视图模型上,为什么我必须再次查找它?就在那时,我想出了如何做到这一点。

于 2015-07-14T05:16:45.663 回答
0

这是帮助我克服这个问题的东西。

在 jquery 包含后,我添加了一个自定义标题标签,如下所示。

    <script type="text/javascript">
        $.ajaxSetup({
            headers: { 'umbraco-page-id': '@CurrentPage.Id' }
        });
    </script> 

现在每个 jquery 帖子都会跨越当前的 umbraco 页面。您可以从请求标头属性访问此自定义标头。

于 2018-02-22T11:26:37.897 回答