如何在Umbraco中创建虚拟节点
形势 我在Umbraco 7.3中创建了一个新的部分,可以在其中管理目录(创建、编辑和删除产品)。创建产品时,我将其所有信息存储在Umbraco数据库的表中。请注意,我没有在树中创建节点,我只是直接使用数据库 问题 例如,当我在该目录中创建“产品A”时,我会自动生成一个自定义URL“/products/Product-A”,并将其存储在数据库的表中。但是,该URL不存在,因为我没有物理节点: 找不到页面 没有与url“/products/product-A”匹配的umbraco文档如何在Umbraco中创建虚拟节点,umbraco,umbraco7,Umbraco,Umbraco7,形势 我在Umbraco 7.3中创建了一个新的部分,可以在其中管理目录(创建、编辑和删除产品)。创建产品时,我将其所有信息存储在Umbraco数据库的表中。请注意,我没有在树中创建节点,我只是直接使用数据库 问题 例如,当我在该目录中创建“产品A”时,我会自动生成一个自定义URL“/products/Product-A”,并将其存储在数据库的表中。但是,该URL不存在,因为我没有物理节点: 找不到页面 没有与url“/products/product-A”匹配的umbraco文档 由于我没有物
由于我没有物理节点,如何“创建”虚拟节点并为该URL分配模板?听起来您不需要由Umbraco处理产品URL 您需要在
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
,这里有一个很好的示例:
根据要点,是否需要创建VirtualProductNode?能否返回Umbraco页面(节点引用),然后使用该页面(模板/控制器)处理产品数据
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;
}
}
我最终会明白的。谢谢你的回答 1.为我们的虚拟页面创建一个类 第一件事是创建一个类,即
ProductVirtualPage
,它继承自publishedContentRapped
。最后一个类为包装和扩展另一个IPublishedContent
的IPublishedContent
实现提供了一个抽象基类。我们将使用属性产品从Razor视图中获取产品
,并进行渲染
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.基于umbracoVirtualNodeHandler创建我们的处理程序
在树中,我们需要创建一个引用节点,在我的例子中,它的id是3286。调用FindContent()
方法时,我们将把它传递给ProductVirtualPage(noderReference,product)
方法
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模型
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=产品模型作为产品;
}
产品信息
---------------
Id:@product.Id
名称:@product.Name
首先,非常感谢您抽出时间为我指明了正确的方向。现在的问题是,我的产品视图(需要传递产品
模型)继承了共享布局视图(需要接收渲染模型
模型),这导致了冲突。请查看以下要点,您可以在注释中看到更详细的解释:我无法实现代码中出现的FindContent
方法。基于方法签名的返回类型为ippublishedcontent
,但是在代码中返回bool。感谢共享@Filipe,您知道您是否可以劫持umbraco中的路由,从而使您的产品显示为umbraco节点的子节点吗?您是否可以访问父节点和路径属性?你能在ProductVirtualPage
类的某个地方设置这些吗?
@{
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>