Copied to clipboard

Flag this post as spam?

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


  • Nikolay Yeryomenko 7 posts 97 karma points
    Aug 12, 2018 @ 18:08
    Nikolay Yeryomenko
    0

    Umbraco and External data

    What is the correct way to combine content from Umbraco with external data?

    What is the correct way to display list of entities and details from custom database table?

    I need to load content for the products list page from Umbraco and products list from external database. For this page I need url like: /products. The page template should display IPublishedContent for this type of pages and paged list of products.

    For the product page I need to load content from the Umbraco and product from external database. For this page I need url like: /product/{id}. The page template should display IPublishedContent for this type of pages and details about product by id.

    I need to combine content from Umbraco with external data and use custom routes.

  • Alex Brown 129 posts 620 karma points
    Aug 13, 2018 @ 11:30
    Alex Brown
    101

    This is quite a big question but I'll try summarise it down into steps I'd do.

    1. Create a document type and template named Products
    2. Create that node in your content tree in the Content section
    3. Create a content finder which detects when contentRequest.Uri.AbsolutePath contains /products/{id} and then sets the contentRequest.PublishedContent property to the products node your just created using UmbracoHelper. Content finder docs: https://our.umbraco.com/Documentation/Reference/Routing/Request-Pipeline/IContentFinder
    4. Now Umbraco knows to route those requests to that document type and template, so we'll need to intercept that call using a RenderMvcController. Guide here: https://abrowndev.co.uk/blog/intercepting-umbraco-controllers/
    5. Call a service/repo from that controller which connects to the database through ApplicationContext.Current.DatabaseContext.Database;, you can use methods such as Fetch
    6. Create a view model for this data. It needs to inherit from RenderModel so that IPublishedContent can be used on your view. Do something along the lines of the following

    ProductsViewModel.cs

    public class ProductsViewModel : RenderModel
    {
        public ProductsViewModel(IPublishedContent content) : base(content)
        {
        }
        public List<ProductViewModel> Products { get; set; }
    }
    

    Then you should be able to return your ActionResult in your controller with the view model attached.

    Then in your view you'll be able to access product data from your custom view model and Model.Content for the IPublishedContent data.

    Hope this all makes sense as it's very summarised and you'll have to take a look at those links.

    Also, you'll need to repeat all steps for the singular Product page, since it'll have a custom url/route.

  • Nikolay Yeryomenko 7 posts 97 karma points
    Aug 13, 2018 @ 13:07
    Nikolay Yeryomenko
    0

    Thank you for description.

  • Nikolay Yeryomenko 7 posts 97 karma points
    Aug 13, 2018 @ 16:44
    Nikolay Yeryomenko
    0

    I developed code according to your suggestions, but have one question to you. I will explain using code.

    I use custom route for url {lang}/product/{id}:

    routes.MapUmbracoRoute(
                    "ProductById",
                    "{lang}/product/{id}",
                    new { controller = "Product", action = "Product", id = UrlParameter.Optional },
                    new ProductRouteHandler()
                //new UmbracoVirtualNodeByIdRouteHandler(1133)
                );
    

    The ProductRouteHandler finds dummy product node in Umbraco:

    public class ProductRouteHandler : UmbracoVirtualNodeRouteHandler
        {
            protected override IPublishedContent FindContent(RequestContext requestContext, UmbracoContext umbracoContext)
            {
                var umbracoHelper = new UmbracoHelper(umbracoContext);
            var lang = (string)requestContext.RouteData.Values["lang"];
            var homePage = umbracoHelper.TypedContentAtRoot()
                .Where(x => x.Name == lang)
                .FirstOrDefault();
            var content = homePage.Children
                .Where(x => x.Name == "Dummy Product")
                .FirstOrDefault();
    
            return content;
            }                
    }
    

    ProductController:

    public class ProductController : RenderMvcController
        {               
            // GET: Product
            public ActionResult Product(IPublishedContent content)
            {
                string lang = (string)RouteData.Values["lang"];
    
                var homePage = Umbraco.TypedContentAtRoot()
                    .Where(pc => pc.Name == lang)
                    .FirstOrDefault();
    
                if (homePage == null)
                {
                    var url = String.Format("/{0}/404", lang);
                    return RedirectPermanent(url);
                }
    
                string languageName = homePage.GetPropertyValue<string>("languageName");
    
                var model = new ProductViewModel(content);
                model.Product = new Product
                {
                    Name = "Product 1"
                };
    
                return View(model);
            }
        }
    

    Product.cshtml:

    @using Tutorial.Models;
    @inherits Umbraco.Web.Mvc.UmbracoViewPage<ProductViewModel>
    @using ContentModels = Umbraco.Web.PublishedContentModels;
    @{
        Layout = "Master.cshtml";
    }
    @section header
    {
        @{ Html.RenderAction("RenderHeader", "MasterSurface"); }
    }
    <div id="main-container">
        <div id="main" class="wrapper clearfix">
            <section>
                <h2>@Model.Product.Name</h2>            
            </section>
        </div>
    </div>
    

    MasterSurfaceController:

    public class MasterSurfaceController : SurfaceController
        {
            [ChildActionOnly]
            public ActionResult RenderHeader()
            {
                ViewBag.HomePage = CurrentPage.AncestorOrSelf(1);
                //ViewBag.HomePage = Umbraco.AssignedContentItem.AncestorOrSelf(1);
    
                RenderModel model = new RenderModel(this.CurrentPage);
                //RenderModel model = new RenderModel(Umbraco.AssignedContentItem);
    
                return PartialView("~/Views/Partials/Master/Header.cshtml", model);
            }
    
            [ChildActionOnly]
            public ActionResult RenderFooter()
            {
                return PartialView("~/Views/Partials/Master/Footer.cshtml");
            }
        }
    

    For Umbraco pages works okay, for custom product route CurrentPage is unavailable, message:

    Cannot find the Umbraco route definition in the route values, the request must be made in the context of an Umbraco request

    How to make CurrentPage available?

    Umbraco.AssignedContentItem is available, but I would like to find solution for CurrentPage.

  • Alex Brown 129 posts 620 karma points
    Aug 13, 2018 @ 16:49
    Alex Brown
    0

    @Model.Content will provide you with a strongly typed “CurrentPage”.

    CurrentPage is dynamic, whereas Model.Content is an IPublishedContent.

    IPublishedContent has methods such as .GetPropertyValue() if that’s what you need it for

  • Nikolay Yeryomenko 7 posts 97 karma points
    Aug 13, 2018 @ 17:03
    Nikolay Yeryomenko
    0

    I was asking about CurrentPage in SurfaceController, but for now I only see the way to use Umbraco.AssignedContentItem. The CurrentPage is of type IPublishedContent in SurfaceController.

    In the views everything as you described. I'm looking for the way to get CurrentPage in SurfaceController, but most of all this is not possible with custom route.

  • Alex Brown 129 posts 620 karma points
    Aug 14, 2018 @ 06:28
    Alex Brown
    0

    Hmm I can’t help with that I’m sorry.

    Why do you need the master controller? I see you’re using the viewbag and returning a model but there may be a way around this pattern

Please Sign in or register to post replies

Write your reply to:

Draft