2016-02-26 41 views
3

形勢如何一把umbraco創建一個虛擬節點

我已經創建了一把umbraco 7.3一個新的部分,在那裏我可以管理目錄(創建,編輯和刪除產品)。當我創建產品時,我將其所有信息存儲在Umbraco數據庫的表格中。請注意,我沒有在樹中創建節點,我只是直接與數據庫一起工作。

問題

例如,當我在那個目錄中創建了「產品A」,我會自動生成並存儲自定義URL「/產品/產品-A」在數據庫中的表。然而,網址不存在,因爲我沒有一個物理節點:

頁找不到

沒有一把umbraco文檔的URL「/產品/產品-A」匹配。

由於我沒有爲它一個物理節點,我怎麼能「創造」一個虛擬節點,並指定該URL的模板?

回答

9

我可以在最後看出這一點。謝謝您的回答!

1.創建一個類爲我們的虛擬頁

第一件事情就是創建一個類即ProductVirtualPagePublishedContentWrapped繼承。這最後一類爲IPubslihedContent實現提供了一個抽象基類,它實現了另一個IPublishedContent的換行和擴展。我們將使用產品以從剃刀視圖中獲取Product並進行渲染。

public class ProductVirtualPage : PublishedContentWrapped 
{ 
    private readonly Product _product; 

    public ProductVirtualPage(IPublishedContent content, Product product) : base(content) 
    { 
    if (product.Name == null) throw new ArgumentNullException("productName"); 
    _product = product; 
    } 

    public Product Product 
    { 
     get 
     { 
      return _product; 
     } 
    } 
} 

2.創建一個基於UmbracoVirtualNodeRouteHandler

在我們需要創建一個參考節點,這在我的情況下,它的ID爲3286.樹我們的處理程序,我們將它傳遞給ProductVirtualPage(nodeReference, product)方法時, FindContent()方法被調用。

public class ProductVirtualNodeRouteHandler : UmbracoVirtualNodeRouteHandler 
{ 
    private ProductService _productService; 

    protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext) 
    { 
     // Get the real Umbraco IPublishedContent instance as a reference point 
     var nodeReference = new UmbracoHelper(umbracoContext).TypedContent(3286); 

     //Get the product Id from the URL (http://example.com/Products/product/57) 
     var productId = umbracoContext.HttpContext.Request.Url.Segments[3]; 

     // Create an instance for the ProductService 
     _productService = new ProductService(new ProductRepository(), new SiteRepository()); 

     // Get the product from the database 
     var product = _productService.GetById(Convert.ToInt32(productId)); 

     // Get the virtual product 
     return new ProductVirtualPage(nodeReference, product); 
    } 
} 

3.註冊我們的定製路線

我們需要使用MapUmbracoRoute添加我們的自定義路由,並將其綁定到ApplicationStarted方法,提供ApplicationEventHandler

public class ContentServiceEventsController : ApplicationEventHandler 
{ 

    protected override void ApplicationStarted(UmbracoApplicationBase umbracoApplication, 
     ApplicationContext applicationContext) 
    { 
     // Add a route for the Products 
     RouteTable.Routes.MapUmbracoRoute(
      "ProductPage", 
      "Products/Product/{id}/", 
      new 
      { 
       controller = "Product", 
       action = "GetProduct" 
      }, 
      new ProductVirtualNodeRouteHandler()); 
    } 
} 

4.創建控制器

控制器將只返回查看,通過我們RenderModel model

public class ProductController : RenderMvcController 
{ 
    public ActionResult GetProduct(RenderModel model, int id) 
    { 
     return View("Product", model); 
    } 
} 

5.有

@{ 
    Layout = "~/Views/Shared/_MasterLayout.cshtml"; 
    var productModel = Model.Content.Product; 
    var product = productModel as Product; 
} 
<pre> 
    Product Info 
    --------------- 

    Id: @product.Id 
    Name: @product.Name 
</pre> 
1

這聽起來像你不需要你的產品網址由Umbraco處理。

您需要將自定義路線添加到您的RouteConfig.cs文件中,例如

routes.MapRoute(
    name: "Products", 
    url: "Products/{id}", 
    defaults: new { controller = "Products", action = "Product", id = UrlParameter.Optional } 
); 

,然後創建一個ProductsController

public class ProductsController : Controller 
{ 
    public ActionResult Product(int id) 
    { 
     // Retrieve product from database 
     // Return view 
    } 

如果您需要訪問UmbracoContext,這裏有一個很好的例子: http://shazwazza.com/post/Custom-MVC-routing-in-Umbraco

+0

首先,非常感謝你的時間和指導我在正確的方向。 現在的事情是,我的產品視圖 - 需要傳遞一個'產品'模型 - 從共享佈局視圖繼承 - 需要接收'RenderModel'模型,這會導致衝突。 請看下面的要點,你可以在評論中看到更詳細的解釋: https://gist.github.com/felipecruz91/9291fe25892d8c7f4cf2#file-productvirtualnoderoutehandler-cs-L31 –

0

從你的要點,你需要創建VirtualProductNode?您能否返回Umbraco頁面(nodeReference),然後使用該頁面(模板/控制器)來處理產品數據?

protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext) 
{ 
    // Get the real Umbraco IPublishedContent instance as a reference point 
    var nodeReference = new UmbracoHelper(umbracoContext).TypedContent(3286); 

    contentRequest.PublishedContent = nodeReference; 

    return contentRequest.PublishedContent != null; 
} 

我們做了一些類似於存儲在媒體部分中的pdf文檔的列表頁面。 pdf文檔被組織在映射到虛擬url結構的文件夾中。內容部分沒有頁面。

(我們不想編輯上傳所有的PDF文檔,然後不得不進入內容部分,創建一個頁面,然後再次選擇PDF文件 - 不必要的額外工作)

有一個頁面定義該部分,其模板將根據url顯示正確的pdf。該模板使用url在媒體部分查找相應的文件夾並列出PDF文件。

public class ProductsContentFinder : IContentFinder 
{ 
    public bool TryFindContent(PublishedContentRequest contentRequest) 
    { 
     if (contentRequest != null) 
     { 
      // url: /store/products/product-name 
      var path = contentRequest.Uri.GetAbsolutePathDecoded(); 
      var parts = path.Split(new[] { '/' }, System.StringSplitOptions.RemoveEmptyEntries); 
      if (parts.Length > 1) 
      { 
       var level1 = string.Concat('/', string.Join("/", parts.Take(2)), '/'); 
       var node = contentRequest.RoutingContext.UmbracoContext.ContentCache.GetByRoute(level1); 
       //find product page 
       var products = node.AncestorOrSelf("Products"); 

       if (products != null) 
       { 
        contentRequest.PublishedContent = products; 
       } 
      } 
     } 

     return contentRequest.PublishedContent != null; 
    } 
} 
+0

我無法實施它在代碼中出現的FindContent方法。基於方法簽名的返回類型是'IPublishedContent',然而在你的代碼中你返回一個布爾值。 –