Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Ulrik Nedergaard 37 posts 146 karma points
    May 08, 2021 @ 15:05
    Ulrik Nedergaard
    0

    I'm developing a webshop solution which will run multiple shops out of the same install / IIS instance. It will be small merchandise shops for customers ( shop.customer1.com, customer2shop.com, webshop.customer3.com etc, created in different root nodes with each one having its own products etc).

    So far so good, but I'm struggeling how to figure out to make the cart, terms, contact page etc as a shared thing, that I don't need to manually create under each site.

    I kind of have it working so each site will react to a MVC route called "/cart", but the page doesn't "know" that it belongs under a given site, so master template and navigation etc doesn't work properly, since it has no clue which site the visitor is seen the cart MVC under. Hope it makes sense.

    I suppose I need to do something to make the cart a virtual node, but can't figure out how to make it work.

    https://our.umbraco.com/documentation/implementation/Custom-Routing/

  • Marc Goodson 1529 posts 10230 karma points MVP 6x c-trib
    May 09, 2021 @ 07:38
    Marc Goodson
    0

    HI Ulrik

    There are a couple of options, but if you have your toe down the custom route path, then the 'bit' where you need to do the magic in the routing example:

       RouteTable.Routes.MapUmbracoRoute(
            "test", 
            "Products/{action}/{sku}",
            new
            {
                controller = "MyProduct",
                sku = UrlParameter.Optional
            },
            new UmbracoVirtualNodeByIdRouteHandler(1234));
        }
    

    Is the 'VirtualNodeRouteHandler' bit: new UmbracoVirtualNodeByIdRouteHandler(1234));

    What this saying is, when this route is requested, Umbraco NEEDS to know which IPublishedContent item /node should be associated with the request, and it's this IPublishedContent item that would give you the context of the site you are 'on' and therefore enable your navigation to work!

    It's called 'virtual' because the IPublishedContent item doesn' need to be a content item in Umbraco, just anything that implements the interface IPublishedContent (there is a base class called PublishedContentWrapped - that makes it easy)

    Anyway, in the example all the UmbracoVirtualNodeByIdRouteHandler is doing is using the Id of a ContentItem to be the 'context' for that request.

    But you may need to do some more complex logic to associate an IPublishedContent item with your request - and if so you can create yoru own VirtualNodeRouteHandler! (bit of a mouthful).

    There is an example here: https://our.umbraco.com/Documentation/Reference/Routing/custom-routes

    Essentially, I'd suggest if you are playing with this first to create a Handler that will return the 'homepage' of your site as the context for the request.

    so if you create a new class called something like

    HomePageRouteHandler

    and make it inherit from

    UmbracoVirtualNodeRouteHandler

    and override

       protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)
                {
                    return 'an IPublishedContent item'!!!
                }
    

    In there you have access to RequestContext and UmbracoContext So you can read the requested Url, and then use the UmbracoContext to find the homepage node that matches the requested Url (using the DomainService etc)

    Then when a request comes in for /cart, this code will associate the 'homepage' with it, and your 'Model' will contain properties of the homepage which will allow your navigation to be built...


    Other simpler options would include creating a Cart Document Type, and creating a Cart page under each site, and then use Route Hijackng to create a custom MVC controller which automatically handles all requests to pages based on the Cart DocumentType - then you will be using Umbraco to automatically determine which site you are on, but still be routed to a single MVC controller to do your Cart Business.

    https://our.umbraco.com/Documentation/Reference/Routing/custom-controllers

    Hope that helps give you a steer!

    regards

    Marc

  • Ulrik Nedergaard 37 posts 146 karma points
    May 12, 2021 @ 06:58
    Ulrik Nedergaard
    0

    Thank you for the thorough reply Marc.

    I'm on my way down the Routing-road, and expected that this hardcoded test ( which of course won't work with multiple sites ) - would give me success - but it's not.

    1075 is the id of the root node of the site I'm testing on. I can call /cart and it gives me an error at all code where it expects to find the umbraco stuff. My first error is trying to find the Model.Root.

    public class RegisterCustomRouteComposer : ComponentComposer<RegisterCustomRouteComponent>
    { }
    
    public class RegisterCustomRouteComponent : IComponent
    {
        private readonly IUmbracoContextFactory _context;
    
        public RegisterCustomRouteComponent(IUmbracoContextFactory context)
        {
            _context = context;
        }
    
        public void Initialize()
        {
    
    
            using (var cref = _context.EnsureUmbracoContext())
            {
                var umbracoHelper = cref.UmbracoContext.Content;
    
                RouteTable.Routes.MapUmbracoRoute("Cart", "cart", new
                {
                    controller = "Cart",
                    action = "Index"
                }, new UmbracoVirtualNodeByIdRouteHandler(1075));
    
    
            }
    
        }
    
        public void Terminate()
        {
            // Nothing to terminate
        }
    
    }
    

    Doing manual cart nodes is an option I would prefer not to use, since I would like to be able to expand it with a controller for other kinds of pages in the future without the need for manual creation. :)

  • Marc Goodson 1529 posts 10230 karma points MVP 6x c-trib
    May 12, 2021 @ 08:28
    Marc Goodson
    0

    Hi Ulrik

    What does your MVC controller look like?

    Does it inherit from RenderMvcController?

    If you put a break point on it, is the routed request going via it, and is the ContentModel populated with your 1075 content?

    public class CartController : Umbraco.Web.Mvc.RenderMvcController
    {
        public override ActionResult Index(ContentModel model)
        {
    

    (the VirtualNodeRouteHandler effectively populates the IPublishedContent property of the ContentModel here)

    In favour of having a 'Cart node' doc type + Route Hijacking approach, it would enable you to have certain 'cart settings' available for editors in Umbraco to change behaviour between different sites.

    If your DocType is called CartPage, then creating a RenderMvcController following the convention of the matching the doc type alias:

       public class CartPageController : Umbraco.Web.Mvc.RenderMvcController
        {
            public override ActionResult Index(ContentModel model)
            {
    

    Then any request to any page based on the CartPage doc type would go via this controller... so 'adding a Cart to a site' is just a case of creating the Umbraco node of that type, the page is immediately routed to the controller, and you immediately have the context of which site you are on...

    ... so it might be more flexible approach that you think.

    You can also have your own BaseRenderMvcController that sits between the core RenderMvcController and any custom route hijacked controller, to share implementation between different types of pages...

    ... anyway just a thought! but be good to get the VirtualNodeRouteHandling approach working for you anyway!

    regards

    Marc

Please Sign in or register to post replies

Write your reply to:

Draft