2012-04-20 107 views
3

我想在一個表面控制器中編寫一個childaction函數,該函數被宏調用來渲染PartialView。MVC表面控制器和Umbraco當前節點

我需要在這個功能來訪問我的當前頁面屬性,然後調整渲染的PartialView。

我從喬治Lusar對ubootstrap代碼得到這個工作得很好的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」]中的數據似乎在兩個函數之間發生變化。 。 如果我diplay DataTokens [ 「一把umbraco」]的ToString()每一個,這裏是發生了什麼:

[ChildActionOnly]公共PartialViewResult的init() - > 「表面」顯示。

On [HttpPort] public HandleSubmit(myModel model) - >「Umbraco.Cms.Web.Model.UmbracoRenderModel」顯示。

感謝這裏的任何建議。

Nicolas。

回答

0

要訪問您的當前頁,你在你的控制器

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

它使用依賴注入umbracos,以RESOLV上下文依賴,並使其提供給您,使用實現這個構造。

退房的文件,在SurfaceController https://github.com/umbraco/Umbraco5Docs/blob/5.1.0/Documentation/Getting-Started/Creating-a-surface-controller.md

+0

聽起來不錯。但我必須通過nodeID作爲宏參數?這意味着如果我想要當前頁面,在插入我的Richtext編輯器時,我仍然要在我的宏的ocntent選擇器參數中選擇當前節點?!沒有其他方式直接前進? – user1288337 2012-04-25 08:17:06

+0

如果您需要當前currentPage,您可以使用控制器中的「this.CurrentPage」。這給了你當前的hive節點。 – dunston 2012-04-25 09:05:29

+0

System.InvalidOperationException:在Umbraco.Cms.Web.Surface.SurfaceController.get_CurrentPage() – user1288337 2012-04-26 08:21:12

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

不過,似乎應該有一種更簡單的方法來做到這一點。

布萊恩

5

我使用一把umbraco 6.0.4,它是那樣簡單:

var currentNode = Umbraco.TypedContent(UmbracoContext.PageId); 
+0

上使用BeginUmbracoForm幫助器時,只能在Http POST的上下文中使用UmbracoPageResult。這在SurfaceController中不起作用。 UmbracoContext.PageId爲null。 – 2013-06-12 19:11:40

+0

如果它是空的,那麼你不在一個頁面上! – 2013-06-14 14:35:32

+0

如果它是一個表面控制器,我不在一個頁面上hehe – 2013-06-18 14:10:20

2

同樣的問題我已經在地面控制器,而阿賈克斯後,獲取當前節點ID,當我們失去隱藏值爲uformpostroutevals

即使我試圖發佈此值,從形式服用,以

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

渲染我仍然在UmbracoContext所有屬性值,所以看起來不正確初始化。

HOTFIX:我傳遞CurrentNodeId到我送由阿賈克斯每個窗體:

在一般的母版頁我創建全局JavaScript對象:

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

在任何請求它很容易使用Global.currentNodeId作爲data則params的一個:

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

請注意,它只是一個熱門的解決方案,而不是一個適當的解決方案!

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 o r UmbracoTemplatePage。

然後我會以相同的方式將模型傳遞給它。

因爲它是表面控制器上的子操作,所以已經在Index中加載的模型只傳遞給子操作。這可以防止讓GetContent代碼在管道中運行兩次。

我這樣做的原因是我有一些基本的數據,我需要初始化我的角度API層。就像它是否已通過身份驗證,登錄成員是誰等。最終,我在那裏有一些標籤,類別等等。

我也想盡可能高效地構建插件,並且沒有冗餘邏輯。我認爲所有的信息都在Master視圖模型上,爲什麼我需要再次查看它?那時我想出瞭如何做到這一點。

0
var currentNode = Umbraco.TypedContent(UmbracoContext.PageId); 

或者,如果你在地面控制器有對象

var currentNode = CurrentPage; 

(轉到定義)

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

請務必檢查空第一,因爲有少數情況您可以在不解決currentPage上下文的情況下調用該操作。

0

這是幫助我克服這一點的東西。

jquery包含後,我添加了一個自定義標題標籤,如下所示。

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

現在每個jQuery的崗位需要跨越當前一把umbraco頁。您可以從Request Header屬性中訪問此自定義標題。