2016-02-26 39 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',然而在你的代码中你返回一个布尔值。 –