场合
我在Umbraco 7.3中创建了一个新部分,我可以在其中管理目录(创建,编辑和删除产品)。当我创建产品时,我将其所有信息存储在Umbraco数据库的表中。请注意我不在树中创建节点,我只是直接使用数据库。
问题
例如,当我创建"产品A"在该目录中,我自动生成并存储自定义URL" / products / product-A"在数据库中的表中。但是,该URL不存在,因为我没有物理节点:
找不到网页
没有umbraco文档与网址' / products / product-A'匹配。
由于我没有物理节点,我怎样才能创建" 虚拟节点并为该URL分配模板?
答案 0 :(得分:12)
我最终可以解决这个问题。谢谢你的回答!
首先要创建一个继承自ProductVirtualPage
的{{1}}类。最后一个类为PublishedContentWrapped
实现提供了一个抽象基类,它包装和扩展了另一个IPubslihedContent
。我们将使用属性 Product 从Razor视图中获取IPublishedContent
并进行渲染。
Product
在树中我们需要创建一个引用节点,在我的例子中它具有id 3286.当调用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;
}
}
}
方法时,我们将它传递给UmbracoVirtualNodeRouteHandler
方法。
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);
}
}
的{{1}}方法。
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());
}
}
答案 1 :(得分:2)
听起来你不需要你的产品网址由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
答案 2 :(得分:0)
从你的Gist,你需要创建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 - 不必要的额外工作)
有一个页面定义了该部分,其模板将根据网址显示正确的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;
}
}