Umbraco-v8-Community-Website-StarterKit icon indicating copy to clipboard operation
Umbraco-v8-Community-Website-StarterKit copied to clipboard

Setup SurfaceController for Events

Open TimGeyssens opened this issue 3 years ago • 5 comments

In order to keep things as DRY as possible we'll use a surface controller to handle the events fetching, both from a homepage widget and the events page

TimGeyssens avatar Oct 08 '20 19:10 TimGeyssens

Hello, I've been tinkering with controllers (not done loads with them tbh) whilst I've been playing around with Setup Events and Event doctypes #36. A few questions if thats okay.

How would people pass the 'event' children to the view (the event landing page that lists the children) ? - Would you create a scaled-down 'eventItem' class to model of an event page? This would be used for list items e.g.

new classes

namespace Our.Umbraco.NonProfitFramework.Core.Models.Items
{
    public class BaseListItem //other list items can inherit from this
    {
        public string Heading { get; set; }
        public IHtmlString Excerpt { get; set; }
        public string Url { get; set; }
        public string ImageUrl { get; set; }
    }
}
namespace Our.Umbraco.NonProfitFramework.Core.Models.Items
{
    public class EventItem : BaseListItem
    {
        public string StartDate { get; set; }
        public string EndDate { get; set; }

        public string StartTime { get; set; }
        public string EndTime { get; set; }
        
        public string Location { get; set; }
    }
}

ViewModel

namespace Our.Umbraco.NonProfitFramework.Core.Models.ViewModels
{
    public class EventsLandingPageViewModel : EventsLandingPage
    {
        public EventsLandingPageViewModel(IPublishedContent content) : base(content)
        {
        }

        public IOrderedEnumerable<EventItem> Events { get; set; }
    }
}

controller

        public override ActionResult Index(ContentModel model)
        {
            if (!(model.Content is EventsLandingPage eventLandingPage))
                return null; //somethings gone wrong

            //do all the date formatting and assign values from eventLandingPage.Children.OfType<EventPage>() etc
            IOrderedEnumerable<EventItem> eventItems = BuildEventItems(eventLandingPage);

            var eventsLandingPageViewModel = new EventsLandingPageViewModel(eventLandingPage)
            {
                Events = eventItems
            };
            
            return CurrentTemplate(eventsLandingPageViewModel);
        }

eventslanding page view

@using Our.Umbraco.NonProfitFramework.Core.Models.ViewModels;
@inherits Umbraco.Web.Mvc.UmbracoViewPage<EventsLandingPageViewModel>

                    @foreach (var item in Model.Events)
                    {
                          //example props
                          item.Heading
                          item.StartDate
                          item.StartTime
                          item.ImgUrl

                    }

I am unsure what the standard practice would be and whether the above is overkill seems as you have access to the event child model e.g. Model.Children.OfType<EventPage>()? Do you do all the processing in the view e.g. formatting the dates .tostring("MMMM dd yyyy") in view, use all the available HTML helpers to do things like truncating e.g. @Html.Truncate, and LINQ to order children?

What's the preference here? My understanding is that this starter kit is designed to help people who might be unfamiliar with Umbraco learn about it so I don't want to lead them up the wrong path. Plus its good for my learning also :)

Good to get your thoughts on this :)

prgriffithsdev avatar Oct 13 '20 08:10 prgriffithsdev

Hey sure thing :) well currently we are thinking of using surface controllers to handle that... so not route hijacking...

A small example can be found in the hybrid framework...

https://github.com/jbreuer/Hybrid-Framework-Best-Practices/blob/master/development/Umbraco.Extensions/Controllers/NewsOverviewController.c

That way we can keep it DRY...

So no need for an EventsLandingPageViewModel and a custom @inherits Umbraco.Web.Mvc.UmbracoViewPage<EventsLandingPageViewModel>

a scaled down version makes sense... maybe call it teaser? and use the default mapper used in umbraco to map from full to teaser?

https://our.umbraco.com/documentation/Reference/Mapping/

Does that make sense?

TimGeyssens avatar Oct 13 '20 12:10 TimGeyssens

Hey Tim, such a busy day!

I need to read up some more on the differences\advantages between surface controllers and route hijacking. I seem to use surface controllers whenever I do a contact form and route hijacking any other time. I've probably found a tutorial to follow at the time :)

Thanks for the links

prgriffithsdev avatar Oct 13 '20 19:10 prgriffithsdev

Yes, that is what most do... but say you have an events landing page and an events widget on home... both need to fetch events data... to keep it DRY best is to handle that in a single controller ... can't do that when doing route hijacking... I'll see if I can find a good example tomorrow :)

TimGeyssens avatar Oct 13 '20 22:10 TimGeyssens

Thanks, Tim, examples are always good if you have them. The DRY principles makes sense with the surface controller. I would always create HTML.Action() calls to a home page controller but you are essentially doing the same thing. Looping through children to process a list item etc.

All learning for me 👍

prgriffithsdev avatar Oct 14 '20 20:10 prgriffithsdev