In Sitecore 7, it is now possible to create model definition items under /sitecore/layout/Models
and link them to my Layouts
and Renderings
(as opposed to hard-coding the type + assembly on each one). This makes it much easier to manage, especially if I ever need to update my namespaces or see which layouts are using a particular model.
That said, I have hit an issue whereby Glass.Mapper appears to parse the 'Model' field as though it is a text
field, when it is in fact an Internal Link
field. Here is the error I am getting:
Could not load type '/sitecore/layout/Models/HomeViewModel' from assembly 'Glass.Mapper.Sc, Version=3.0.2.8, Culture=neutral, PublicKeyToken=null'.
Does anyone now if Glass supports linking to Models in Sitecore 7, or am I correct to assume that it's just not resolving the Internal Link field to the Model?
UPDATE: This works properly now in the latest version, none of what I said below is needed anymore, keeping for posterity's sake.
I ran into this problem myself and unfortunately it does not appear as if this is supported. I looked on the Trello for Glass and it looks like Sitecore 7 testing/support is an upcoming task although it mostly works in its current form aside from one or two issues.
That being said since it's open source it's not too much of a hassle to get it working yourself. Below is the full code for the Glass.Mapper.Sc.Pipelines.Response.GetModel class which I've modified to resolve two issues I was having
Please note that I have not modified all methods in this class, just the ones that have broken for me so far. The modifications themselves are fairly straightforward (just make it look for the linked item instead of a text field). I hope this helps.
public class GetModel : GetModelProcessor
{
public GetModel()
{
ContextName = "Default";
}
public string ContextName { get; set; }
public override void Process(GetModelArgs args)
{
if (args.Result == null)
{
Rendering rendering = args.Rendering;
if (rendering.RenderingType == "Layout")
{
args.Result = GetFromItem(rendering, args);
if (args.Result == null)
{
args.Result = GetFromLayout(rendering, args);
}
}
if (args.Result == null)
{
args.Result = GetFromPropertyValue(rendering, args);
}
if (args.Result == null)
{
args.Result = GetFromField(rendering, args);
}
}
}
protected virtual object GetFromField(Rendering rendering, GetModelArgs args)
{
Item obj = ObjectExtensions.ValueOrDefault<RenderingItem, Item>(rendering.RenderingItem, (Func<RenderingItem, Item>)(i => i.InnerItem));
if (obj == null)
return (object)null;
Item model = MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(obj["Model"]);
if (model == null)
return (object)null;
else
return GetObject(model["Model Type"], rendering);
}
protected virtual object GetFromPropertyValue(Rendering rendering, GetModelArgs args)
{
string model = rendering.Properties["Model"];
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
protected virtual object GetFromLayout(Rendering rendering, GetModelArgs args)
{
string pathOrId = rendering.Properties["LayoutId"];
if (StringExtensions.IsWhiteSpaceOrNull(pathOrId))
return (object)null;
string modelItemPath = ObjectExtensions.ValueOrDefault<Item, string>(MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(pathOrId), (Func<Item, string>)(i => i["Model"]));
string model = ObjectExtensions.ValueOrDefault<Item, string>(MvcSettings.GetRegisteredObject<ItemLocator>().GetItem(modelItemPath), (Func<Item, string>)(i => i["Model Type"]));
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
protected virtual object GetFromItem(Rendering rendering, GetModelArgs args)
{
string model = ObjectExtensions.ValueOrDefault<Item, string>(rendering.Item, (Func<Item, string>)(i => i["MvcLayoutModel"]));
if (StringExtensions.IsWhiteSpaceOrNull(model))
return (object)null;
else
return GetObject(model, rendering);
}
public object GetObject(string model, Rendering rendering)
{
if (model.IsNullOrEmpty())
return null;
var type = Type.GetType(model, true);
if (type == null)
return null;
var context = Context.Contexts[ContextName];
if (context == null) throw new MapperException("Failed to find context {0}".Formatted(ContextName));
if (context.TypeConfigurations.ContainsKey(type))
{
ISitecoreContext scContext = new SitecoreContext(context);
//comment this if block out if you just need to solve the model link problem
if (rendering != null)
{
if (rendering.Item != null)
{
var dataSourceResult = scContext.GetCurrentItem(type, itemOverride: rendering.Item);
return dataSourceResult;
}
}
var result = scContext.GetCurrentItem(type);
return result;
}
return null;
}
}