Skip to content
This repository has been archived by the owner on Dec 13, 2021. It is now read-only.

DittoView: Enhancement to support unwrapping & downcasting view-models #219

Merged
merged 3 commits into from
Jul 27, 2017
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 18 additions & 6 deletions src/Our.Umbraco.Ditto/Web/Mvc/DittoView.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;
using System.Globalization;
using System.Reflection;
using System.Web.Mvc;
using Umbraco.Core.Models;
using Umbraco.Web.Models;
Expand Down Expand Up @@ -27,29 +28,40 @@ public abstract class DittoView<TViewModel>
/// <param name="viewData">The view data.</param>
protected override void SetViewData(ViewDataDictionary viewData)
{
// If model is already ditto view model, use it
if (viewData.Model is DittoViewModel<TViewModel>)
// Gather the Ditto view model
var model = viewData.Model;

// If model is already Ditto view-model, use it
if (model is DittoViewModel<TViewModel>)
{
base.SetViewData(viewData);
return;
}

// Gather ditto view model properties
var model = viewData.Model;
// Gather any processor contexts
var processorContexts = new List<DittoProcessorContext>();

// Check to see if this is a Ditto transfer model
var transferModel = model as DittoTransferModel;
if (transferModel != null)
{
model = transferModel.Model;
processorContexts = transferModel.ProcessorContexts;
}

// Check to see if we are a ditto view model at least and copy processors
// Check if the model is a Ditto base view-model; Use the assigned properties
var baseDittoViewModel = model as BaseDittoViewModel;
if (baseDittoViewModel != null)
{
processorContexts.AddRange(baseDittoViewModel.ProcessorContexts);

// Furthermore, check if the model is generic/wrapped; Unwrap the inner view-model
var modelType = model.GetType();
if (modelType.IsGenericType && modelType.GetGenericTypeDefinition() == typeof(DittoViewModel<>))
{
var viewProperty = modelType.GetProperty("View", Ditto.MappablePropertiesBindingFlags);
model = FastPropertyAccessor.GetValue(viewProperty, model);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think there needs to be some checks here to ensure it's actually castable to expected view model type before assigning it

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Interestingly, I had included an IsAssignableFrom check in there, but then thought that the as casting further down would handle that...

var typedModel = model as TViewModel;

as it would cast as null if it wasn't castable, (which is how it currently works).

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh good point, I didn't look past the change. Happy to leave as is then.

}
}

var content = default(IPublishedContent);
Expand Down Expand Up @@ -78,7 +90,7 @@ protected override void SetViewData(ViewDataDictionary viewData)

var typedModel = model as TViewModel;

// We need to give each view it's own view data dictonary
// We need to give each view its own view data dictionary
// to allow them to have different model types
var newViewData = new ViewDataDictionary(viewData)
{
Expand Down