Glass Mapper (4.1.2.67) не может сопоставить форматированное текстовое поле

У меня есть несколько классов, определенных для сопоставления элементов шаблона следующим образом:

public class ContentBase
{
    public virtual Guid Id { get; set; }
    public virtual string Name { get; set; }
    [SitecoreParent]
    public virtual ContentBase Parent { get; set; }
    [SitecoreItem]
    public virtual Item Self { get; set; }
}
[SitecoreType(TemplateId = "{7979766D-DB9C-4E75-9BE3-5B481C6AB6FF}", AutoMap = true)]
public class EventsListing : ContentBase
{
    [SitecoreField(FieldName = "EventsLocation")]
    public virtual SitecoreFolder<Event> Events { get; set; }
}
[SitecoreType(TemplateId = "{CED01C9B-6284-461A-848F-2CDD00CC6DEB}", AutoMap = true)]
public class Event : ContentBase
{
    public virtual string Title { get; set; }
    public virtual string Details { get; set; }
    public virtual string iCalSummary { get; set; }
    public virtual Image ImageLandscape { get; set; }
    public virtual Image ImagePortrait { get; set; }
    public virtual Image ImageSquare { get; set; }
    public virtual string Date { get; set; }
    public virtual DateTime DateStart { get; set; }
    public virtual DateTime DateEnd { get; set; }
    public virtual string Location { get; set; }
    public virtual string GoogleMapsAddress { get; set; }
    public virtual string MemberDiscount { get; set; }
    public virtual Link EventLinkUrl { get; set; }
    public virtual string EventLinkText { get; set; }
}

Шаблон для мероприятия

Шаблон для мероприятия

У меня есть подмакет для EventsListing, основанный на GlassUserControl, и он успешно получает все поля для EventsListing и дочерних событий. Затем у меня есть ссылка на дату для создания iCal для события через контроллер web.api.

    [RoutePrefix("hbf/api/ical")]
public class EventICalController : ApiController
{
    [Route("{id:guid}")]
    [HttpGet]
    public HttpResponseMessage Get(Guid id)
    {
        var scc = new SitecoreContext(); 
        var item = scc.GetItem<Item>(id);
        var myEvent = scc.GetItem<Models.Event>(id);

Элемент выглядит нормально, и я могу получить доступ к полям; но вызов scc.GetItem(id) вызывает исключение в поле «Подробности».

Вложение исключений (полная трассировка стека ниже): Glass.Mapper.MapperException "Не удалось создать тип Models.Event" Glass.Mapper.MapperException "Не удалось сопоставить свойства на /sitecore/content/..." Glass.Mapper.MapperException «Не удалось сопоставить сведения о свойстве Models.Event» System.NullReferenceException

Если я закомментирую свойство «Подробности», оно сработает.

Я пробовал разные способы получить SitecoreContext, даже без указания языка. Я также попытался установить атрибут SitecoreField с именем и/или идентификатором и типом поля.

Что я могу с точки зрения конфигурации (или чего-то еще), чтобы решить эту проблему?


{
  "Message": "An error has occurred.",
  "ExceptionMessage": "Failed to create type xxx.Web.Models.Event",
  "ExceptionType": "Glass.Mapper.MapperException",
  "StackTrace": "   at Glass.Mapper.Pipelines.ObjectConstruction.Tasks.CreateConcrete.CreateConcreteTask.CreateObject(ObjectConstructionArgs args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\ObjectConstruction\\Tasks\\CreateConcrete\\CreateConcreteTask.cs:line 115
       at Glass.Mapper.Pipelines.ObjectConstruction.Tasks.CreateConcrete.CreateConcreteTask.Execute(ObjectConstructionArgs args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\ObjectConstruction\\Tasks\\CreateConcrete\\CreateConcreteTask.cs:line 68
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 77
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 82
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 82
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 82
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 82
       at Glass.Mapper.Pipelines.AbstractPipelineRunner`2.<>c__DisplayClass3.<CreateTaskExpression>b__2(T args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\AbstractPipelineRunner.cs:line 82
       at Glass.Mapper.AbstractService.InstantiateObject(AbstractTypeCreationContext abstractTypeCreationContext) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\AbstractService.cs:line 138
       at Glass.Mapper.Sc.SitecoreService.CreateType(Type type, Item item, Boolean isLazy, Boolean inferType, Dictionary`2 parameters, Object[] constructorParameters) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper.Sc\\SitecoreService.cs:line 498
       at Glass.Mapper.Sc.SitecoreService.GetItem[T](Guid id, Boolean isLazy, Boolean inferType) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper.Sc\\SitecoreService.cs:line 899
       at xxx.Web.Services.xxx.EventICalController.Get(Guid id) in d:\\Dev\\LW\\xxx.Web\\Services\\xxx\\EventICalController.cs:line 57
       at lambda_method(Closure , Object , Object[] )
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)
       at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)
        --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()
        --- End of stack trace from previous location where exception was thrown ---
       at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
       at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
       at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()",
  "InnerException": {
    "Message": "An error has occurred.",
    "ExceptionMessage": "Failed to map properties on /sitecore/content/xxx/Home/Living well/Events/datasources/Health and fitness events/xxx Fitness.",
    "ExceptionType": "Glass.Mapper.MapperException",
    "StackTrace": "   at Glass.Mapper.Configuration.AbstractTypeConfiguration.MapPropertiesToObject(Object obj, IAbstractService service, AbstractTypeCreationContext context) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Configuration\\AbstractTypeConfiguration.cs:line 174
           at Glass.Mapper.Pipelines.ObjectConstruction.Tasks.CreateConcrete.CreateConcreteTask.CreateObject(ObjectConstructionArgs args) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Pipelines\\ObjectConstruction\\Tasks\\CreateConcrete\\CreateConcreteTask.cs:line 104",
    "InnerException": {
      "Message": "An error has occurred.",
      "ExceptionMessage": "Failed to map property Details on xxx.Web.Models.Event",
      "ExceptionType": "Glass.Mapper.MapperException",
      "StackTrace": "   at Glass.Mapper.Configuration.AbstractTypeConfiguration.<>c__DisplayClassb.<CreatePropertyExpression>b__a(Object obj, AbstractDataMappingContext context) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Configuration\\AbstractTypeConfiguration.cs:line 123
           at Glass.Mapper.Configuration.AbstractTypeConfiguration.MapPropertiesToObject(Object obj, IAbstractService service, AbstractTypeCreationContext context) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Configuration\\AbstractTypeConfiguration.cs:line 144",
      "InnerException": {
        "Message": "An error has occurred.",
        "ExceptionMessage": "Failed to map to property 'Details' on type 'xxx.Web.Models.Event'",
        "ExceptionType": "Glass.Mapper.MapperException",
        "StackTrace": "   at Glass.Mapper.AbstractDataMapper.MapCmsToProperty(AbstractDataMappingContext mappingContext) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\AbstractDataMapper.cs:line 64
               at Glass.Mapper.Configuration.AbstractTypeConfiguration.<>c__DisplayClassb.<CreatePropertyExpression>b__a(Object obj, AbstractDataMappingContext context) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\Configuration\\AbstractTypeConfiguration.cs:line 119",
        "InnerException": {
          "Message": "An error has occurred.",
          "ExceptionMessage": "Object reference not set to an instance of an object.",
          "ExceptionType": "System.NullReferenceException",
          "StackTrace": "   at xxx.Core.Pipelines.RenderField.GetDevModeContent.Process(RenderFieldArgs args)
               at (Object , Object[] )
               at Sitecore.Pipelines.CorePipeline.Run(PipelineArgs args)
               at Glass.Mapper.Sc.DataMappers.SitecoreFieldStringMapper.RunPipeline(Field field) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper.Sc\\DataMappers\\SitecoreFieldStringMapper.cs:line 99
               at Glass.Mapper.AbstractDataMapper.MapCmsToProperty(AbstractDataMappingContext mappingContext) in c:\\TeamCity\\buildAgent\\work\\8567e2ba106d3992\\Source\\Glass.Mapper\\AbstractDataMapper.cs:line 60"
        }
      }
    }
  }
}

person baralong    schedule 18.08.2016    source источник
comment
Обычно я использую SitecoreService, а не SitecoreContext с ApiControllers. Вы уверены, что он использует правильную базу данных?   -  person Ben Golden    schedule 18.08.2016
comment
Хм... Не обращайте на это внимания. Я пропустил часть, где вы упоминаете, что можете получить обычный предмет и получить доступ к полям. Настроены ли у вас какие-либо настраиваемые преобразователи данных? Может помочь более полная трассировка стека.   -  person Ben Golden    schedule 18.08.2016
comment
@BenGolden Добавлено. Я также собираюсь попытаться получить исходный код GlassMapperSC и вступить в него.   -  person baralong    schedule 19.08.2016
comment
Судя по трассировке стека, похоже, что ошибка возникает в специальном процессоре для конвейера RenderField: xxx.Core.Pipelines.RenderField.GetDevModeContent.   -  person Ben Golden    schedule 19.08.2016


Ответы (2)


Я добавил исходный код проектов Glass.Mapper.Sc.* в свое решение (yay для открытого исходного кода) и обнаружил, что мне нужно добавить некоторые дополнительные настройки для расширенное текстовое поле, как показано ниже:

[SitecoreField(Setting = SitecoreFieldSettings.RichTextRaw)]
public virtual string Details { get; set; }

Таким образом, поле не проходит процесс рендеринга и просто возвращает необработанный HTML-код, чего я и хотел. Это был сбой процесса рендеринга, это своего рода половинчатый ответ, так как я не знаю, почему процесс рендеринга не удался, но мне это не нужно. К сожалению, в документации Glass.Mapper я не нашел того, что мне было нужно.

person baralong    schedule 19.08.2016
comment
Обратите внимание, что если вы используете необработанное значение поля форматированного текста, ваши ссылки не будут расширены до SEO/удобных для пользователя URL-адресов. - person Ben Golden; 19.08.2016
comment
Хм, это может быть проблемой. я буду копать - person baralong; 22.08.2016

Я считаю, что Glass не может разрешить Context.Site. Поскольку вызовы веб-API по умолчанию не имеют контекстного сайта. Вероятно, вы можете обернуть весь вызов внутри using (new SiteContextSwitcher(Factory.GetSite("yoursite"))) или найти другой способ установить Context.Site внутри вызова службы.

или, если у вас есть несколько сайтов, убедитесь, что они имеют свойство hostName, определенное в вашем узле <sites>, и что-то вроде этого в начале вызова:

var sites = Sitecore.Configuration.Factory.GetSiteInfoList();
string currentHost = HttpContext.Current.Request.Url.Host;
var currentSite = sites.FirstOrDefault(obj => obj.HostName.Equals(currentHost, StringComparison.InvariantCultureIgnoreCase));
if (currentSite != null)
   {
       var newSite = new Sitecore.Sites.SiteContext(currentSite);
       if (newSite != null)
       {                 
           using (new SiteContextSwitcher(newSite))
           {

                ///Code here
           }
       {
    {
person Amir Setoudeh    schedule 20.08.2016
comment
Спасибо за подробности, я попробовал эту строку, но у меня только один сайт, и он все еще не отображается. Я оставлю свое исправление ниже, но я буду продолжать изучать ваше предложение. - person baralong; 22.08.2016