2016-08-17 5 views
1

Моего модуль создает пользовательский элемент контента через контроллер:индекса поля для запросов не обновляется, когда заданное значение программно

private ContentItem createContentItem() 
    { 
     // Add the field 
     _contentDefinitionManager.AlterPartDefinition(
      "TestType", 
      cfg => cfg 
      .WithField(
       "NewField", 
       f => f 
        .OfType(typeof(BooleanField).Name) 
        .WithDisplayName("New Field")) 
      ); 

     // Not sure if this is needed 
     _contentDefinitionManager.AlterTypeDefinition(
      "TestType", 
      cfg => cfg 
       .WithPart("TestType") 
      ); 

     // Create new TestType item 
     var newItem = _contentManager.New("TestType"); 
     _contentManager.Create(TestItem, VersionOptions.Published); 

     // Set the added boolean field to true 
     BooleanField newField = ((dynamic)newItem).TestType.NewField as BooleanField; 
     newField.Value = true; 

     // Set title (as date created, for convenience) 
     var time = DateTime.Now.ToString("MM-dd-yyyy h:mm:ss tt", CultureInfo.InvariantCulture).Replace(':', '.'); 
     newItem.As<TitlePart>().Title = time; 

     return newItem; 
    } 

Конечный результат этого является новым TestType элемент с полем, который установлен в действительность. Просмотр элемента контента на панели управления, а также проверка ContentItemVersionRecord в базе данных подтверждают правильность установки значения.

Однако запросы, похоже, не работают должным образом в полях, заданных таким образом. Я нашел запись IntegerFieldIndexRecord, которая, как я полагаю, использует прогнозы для заполнения страниц результатов запроса. При этом значение TestField остается равным 0 (false) вместо 1 (true).

Переход на страницу редактирования содержимого контента и просто щелчок «Сохранить» обновления IntegerFieldIndexRecord правильно, что означает, что значение теперь подхвачено запросом. Как можно обновить запись для значений полей, установленных программно?

Соответствующий раздел миграции:

SchemaBuilder.CreateTable(typeof(TestTypePartRecord).Name, table => table 
      .ContentPartRecord() 
     ); 

     ContentDefinitionManager.AlterTypeDefinition(
      "TestType", 
      cfg => cfg 
       .DisplayedAs("Test Type") 
       .WithPart(typeof(TitlePart).Name) 
       .WithPart(typeof(ContainablePart).Name) 
       .WithPart(typeof(CommonPart).Name) 
       .WithPart(typeof(IdentityPart).Name) 
      ); 

Edit: исправить это вручную изменить индекс проекции запись всякий раз, когда меняется значение поля, используя этот вызов:

_fieldIndexService.Set(testResultItem.As<FieldIndexPart>(), 
    "TestType", // Resolves as TestTypePart, which holds the field 
    "newField", 
    "", // Not sure why value name should be empty, but whatever 
    true, // The value to be set goes here 
    typeof(bool)); 
+1

Вы пытались '_contentManager.Publish (TestItem)'? –

+0

Ниже приведены ответы на неполадку. Похоже, обработчик FieldIndexPart не меняет запись автоматически при изменении значения поля.Публикация должна запускать его, но это не так. – ub3rman123

ответ

0

Есть 2 можно исправить это:

1) Убедитесь, что вновь созданный элемент публикуется по телефону ContentManager.Publish(), так как Orchard.Projections.Handlers.FieldIndexPartHandler прослушивает опубликовать событие, чтобы обновить FieldIndexPartRecord

2) использовать IFieldIndexService обновить FieldIndexPartRecord вручную, см реализации Orchard.Projections.Handlers.FieldIndexPartHandler, чтобы получить в идее, как сделать это

Надеются, что это помогает.

: редактировать

Благодаря вызову Create(...Published)ContentManager.Published() не будет ничего делать, как элемент уже считается опубликован.

Вы можете сделать следующее, чтобы заставить логику публикации бежать:

bool itemPublished = newItem.VersionRecord.Published; 

// unpublish item first when it is already published as ContentManager.Publish() internally first checks for published flag and when set it aborts silently 
// -> this behaviour prevents calling publish listeners 
if (itemPublished) 
    _contentManager.Unpublish(newItem); 

// the following call will result in calls to IContentHandler.Publishing()/IContentHandler.Published() 
_contentManager.Publish(newItem); 

или просто создать элемент в виде черновика и опубликовать его, когда все настроено правильно.

+1

Я могу подтвердить, что публикация не была проблемой, но вручную вызывать IFieldIndexService.Set каждый раз, когда я изменяю значение поля, исправляет проблему с запросами. Я добавил точный вызов, который я делаю (который выглядит очень похоже на то, что Xceno отправил) на исходный пост. – ub3rman123

+0

@ ub3rman123 Я думаю, что вызов публикации ничего не делает для вас, потому что вы создаете элемент как опубликованную версию уже. В менеджере контента есть проверка работоспособности, которая заставляет метод ничего не делать, когда элемент уже опубликован. См. Мой отредактированный ответ о том, как решить эту проблему. – ViRuSTriNiTy

1

В некоторых случаях простой contentManager.Publish() не будет работать. У меня была аналогичная проблема некоторое время назад и на самом деле реализована простая вспомогательная служба для решения этой проблемы; вот отрывок:

public T GetStringFieldValues<T>(ContentPart contentPart, string fieldName) 
{ 
    var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>(); 
    var partName = contentPart.PartDefinition.Name; 

    return this.fieldIndexService.Get<T>(fieldIndexPart, partName, fieldName, string.Empty); 
} 

private void SetStringFieldValue(ContentPart contentPart, string fieldName, IEnumerable<int> ids) 
{ 
    var fieldIndexPart = contentPart.ContentItem.As<FieldIndexPart>(); 
    var partName = contentPart.PartDefinition.Name; 
    var encodedValues = "{" + string.Join("},{", ids) + "}"; 
    this.fieldIndexService.Set(fieldIndexPart, partName, fieldName, string.Empty, encodedValues, typeof(string)); 
} 

Я на самом деле построил это для использования с MediaLibrary- и ContentPicker полей (они кодируют их значение в виде строки внутри), поэтому он не может быть пригодным для логического поля в вашем примере. Но это не может быть так сложно реализовать, просто посмотрите на существующие драйверы и обработчики для этих полей.