Introduced SetViewDataAsync on UmbracoViewPage

Signed-off-by: Bjarke Berg <mail@bergmania.dk>
This commit is contained in:
Bjarke Berg
2020-10-20 21:30:45 +02:00
parent d315d2120e
commit 35c22f9074
2 changed files with 243 additions and 193 deletions

View File

@@ -1,7 +1,10 @@
using System;
using System.Text;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using Umbraco.Core;
@@ -11,6 +14,7 @@ using Umbraco.Core.IO;
using Umbraco.Core.Logging;
using Umbraco.Core.Models.PublishedContent;
using Umbraco.Core.Strings;
using Umbraco.Web.Common.ModelBinders;
namespace Umbraco.Web.Common.AspNetCore
{
@@ -29,6 +33,7 @@ namespace Umbraco.Web.Common.AspNetCore
private ContentSettings ContentSettings => Context.RequestServices.GetRequiredService<IOptions<ContentSettings>>().Value;
private IProfilerHtml ProfilerHtml => Context.RequestServices.GetRequiredService<IProfilerHtml>();
private IIOHelper IOHelper => Context.RequestServices.GetRequiredService<IIOHelper>();
private ContentModelBinder ContentModelBinder => new ContentModelBinder();
protected IUmbracoContext UmbracoContext => _umbracoContext ??= UmbracoContextAccessor.UmbracoContext;
@@ -85,5 +90,58 @@ namespace Umbraco.Web.Common.AspNetCore
base.WriteLiteral(value);
}
// maps model
protected async Task SetViewDataAsync(ViewDataDictionary viewData)
{
// capture the model before we tinker with the viewData
var viewDataModel = viewData.Model;
// map the view data (may change its type, may set model to null)
viewData = MapViewDataDictionary(viewData, typeof (TModel));
// bind the model
var bindingContext = new DefaultModelBindingContext();
await ContentModelBinder.BindModelAsync(bindingContext, viewDataModel, typeof (TModel));
viewData.Model = bindingContext.Result.Model;
// set the view data
ViewData = (ViewDataDictionary<TModel>) viewData;
}
// viewData is the ViewDataDictionary (maybe <TModel>) that we have
// modelType is the type of the model that we need to bind to
//
// figure out whether viewData can accept modelType else replace it
//
private static ViewDataDictionary MapViewDataDictionary(ViewDataDictionary viewData, Type modelType)
{
var viewDataType = viewData.GetType();
if (viewDataType.IsGenericType)
{
// ensure it is the proper generic type
var def = viewDataType.GetGenericTypeDefinition();
if (def != typeof(ViewDataDictionary<>))
throw new Exception("Could not map viewData of type \"" + viewDataType.FullName + "\".");
// get the viewData model type and compare with the actual view model type:
// viewData is ViewDataDictionary<viewDataModelType> and we will want to assign an
// object of type modelType to the Model property of type viewDataModelType, we
// need to check whether that is possible
var viewDataModelType = viewDataType.GenericTypeArguments[0];
if (viewDataModelType.IsAssignableFrom(modelType))
return viewData;
}
// if not possible or it is not generic then we need to create a new ViewDataDictionary
var nViewDataType = typeof(ViewDataDictionary<>).MakeGenericType(modelType);
var tViewData = new ViewDataDictionary(viewData) { Model = null }; // temp view data to copy values
var nViewData = (ViewDataDictionary)Activator.CreateInstance(nViewDataType, tViewData);
return nViewData;
}
}
}