Situation
I have created a new section in Umbraco 7.3 where I can manage a catalogue (create, edit, and delete products). When I create a product, I store all its information in a table in the Umbraco database. Please note that I do not create a node in the tree, I just work directly with the database.
Question
For example, when I create the "Product A" in that catalogue, I automatically generate and store a custom URL "/products/product-A" in a table in the database. However, that URL does not exist as I do not have a physical node:
Page not found
No umbraco document matches the url '/products/product-A'.
As I do not have a physical node for it, how can I "create" a virtual node and assign a template for that URL?
I could figure this out at the end. Thank you for your answers!
First thing is to create a class i.e ProductVirtualPage
which inherits from PublishedContentWrapped
. This last class provides an abstract base class for IPubslihedContent
implementations that wrap and extender another IPublishedContent
. We will use the property Product to get the Product
from the Razor view and render.
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
In the tree we need to create a reference node, which in my case it has the id 3286. We will pass it to the ProductVirtualPage(nodeReference, product)
method when the FindContent()
method is called.
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);
}
}
We need to add our custom route using MapUmbracoRoute
and bind it to the ApplicationStarted
method that provides 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());
}
}
The controller will just return the View, passing our RenderModel model
.
public class ProductController : RenderMvcController
{
public ActionResult GetProduct(RenderModel model, int id)
{
return View("Product", model);
}
}
@{
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>
It sounds like you don't need your product urls to be handled by Umbraco.
You need to add a custom route into your RouteConfig.cs
file e.g.
routes.MapRoute(
name: "Products",
url: "Products/{id}",
defaults: new { controller = "Products", action = "Product", id = UrlParameter.Optional }
);
and then create a ProductsController
public class ProductsController : Controller
{
public ActionResult Product(int id)
{
// Retrieve product from database
// Return view
}
If you need access to the UmbracoContext
, there is a good example here:
http://shazwazza.com/post/Custom-MVC-routing-in-Umbraco
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With