Skip to main content

A DD4T.net Implementation - Strong-Typed Model in Component Controller

In the previous post, I was mentioning that a Component controller can be reused in both cases when the Component Presentation is embedded on the Page, as well as when it is published as Dynamic Component Presentation (DCP). In this post I will elaborate this topic.

The Component controller consists of the following sample code:

    public class DeviceController : MyControllerBase
    {
        public ActionResult Index(int? publication, int? component, string view)
        {
            Device device;
            string viewName;
            ResolveModelAndView<Device>(publication, component, view, out device, out viewName);

            return View(viewName, device);
        }
    }

Two things to note here:
  • DeviceController is a specialization of MyControllerBase;
  • Method ResolveModelAndView is defined in a parent class and is in charge with figuring out both the strongly-typed model for the Component and the view name;

The method implementation, as defined in the MyControllerBase, is the following:

    public void ResolveModelAndView<T>(int? publication, int? component, string view, out T model, out string viewName) where T : ModelBase
    {
        model = GetModel<T>(publication, component, view);
        viewName = GetViewName(view);

        if (model == null || string.IsNullOrEmpty(viewName))
        {
            throw new HttpException(404, "Page Not Found");
        }
    }

The model is retrieved by method GetModel showcased below. The method behaves differently based on whether the Component Presentation is embedded on the Page or not.

If on the Page, calling GetComponentPresentation method defined in TridionControllerBase will give us the IComponentPresentation model; otherwise, we resort to using the ModelFactory to load the strongly-typed model.

One extra check is made on whether the Component Presentation is dynamic or not, this affecting the way we load its strong-typed model.

    public T GetModel<T>(int? publication, int? component, string view) where T : ModelBase
    {
        T model = null;
        string componentUri = null;
        IComponentPresentation componentPresentation = GetComponentPresentation();

        if (componentPresentation == null)
        {
            if (publication == null || component == null)
            {
                return null;
            }
            else
            {
                componentUri = string.Format("tcm:{0}-{1}", publication, component);
                model = ModelFactory.GetModel<T>(componentUri, view);
            }
        }
        else
        {
            if (componentPresentation.IsDynamic)
            {
                componentUri = componentPresentation.Component.Id;
                string templateUri = componentPresentation.ComponentTemplate.Id;
                model = ModelFactory.GetModel<T>(componentUri, templateUri);
            }
            else
            {
                model = ModelFactory.GetModel<T>(componentPresentation.Component);
            }
        }

        return model;
    }

The other method, GetViewName(string view) is quite straight forward, as it simply looks at the Component Template metadata to retrieve the view field.

    public string GetViewName(string view)
    {
        IComponentPresentation componentPresentation = GetComponentPresentation();
        return componentPresentation == null ? view : GetViewName(componentPresentation);
    }

    public string GetViewName(IComponentPresentation componentPresentation)
    {
        IComponentTemplate template = componentPresentation.ComponentTemplate;
        IFieldSet fields = template.MetadataFields;

        string viewName = fields.StringValue("view");
        if (string.IsNullOrEmpty(viewName))
        {
            viewName = template.Title;
        }

        return viewName;
    }

In case the Component Presentation is not present on the Page, there will be no Component Template model either, and as such, we need to provide our own view parameter (that we require as input parameter).



Comments