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