2016-08-17 1 views
1

Mon module crée un élément de contenu personnalisé via le contrôleur:index des champs pour les requêtes non mise à jour lorsque mis en valeur par programmation

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; 
    } 

Le résultat final de c'est un nouvel élément TestType avec un champ qui est défini sur true. L'affichage de l'élément de contenu dans le tableau de bord ainsi que l'examen de ContentItemVersionRecord dans la base de données confirme que la valeur a été définie correctement. Toutefois, les requêtes ne semblent pas fonctionner correctement sur les champs définis de cette manière. J'ai trouvé l'enregistrement IntegerFieldIndexRecord, qui est ce que je suppose que les projections utilisent pour remplir les pages de résultats de requête. Sur ce, la valeur de TestField reste à 0 (faux), au lieu de 1 (vrai). Si vous accédez à la page d'édition de l'élément de contenu et que vous cliquez simplement sur "enregistrer", IntegerFieldIndexRecord met à jour correctement IntegerFieldIndexRecord, ce qui signifie que la valeur est maintenant récupérée par la requête. Comment l'enregistrement peut-il être mis à jour pour les valeurs de champs définies par programme?

section pertinente de la migration:

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: Le correctif pour cela est de modifier manuellement l'index de projection enregistrement lors du changement d'une valeur de champ, en utilisant cet appel:

_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

Avez-vous essayé '_contentManager.Publish (TestItem)'? –

+0

Les réponses ci-dessous ont corrigé le problème. Il semble que le gestionnaire de FieldIndexPart ne modifie pas automatiquement l'enregistrement lorsque la valeur du champ change.La publication devrait le déclencher, mais ce n'est pas le cas. – ub3rman123

Répondre

0

Il y a 2 façons de résoudre ce problème:

1) Assurez-vous que l'élément nouvellement créé est publié en appelant ContentManager.Publish() comme Orchard.Projections.Handlers.FieldIndexPartHandler écoute le publier événement pour mettre à jour le FieldIndexPartRecord

2) utiliser IFieldIndexService pour mettre à jour FieldIndexPartRecord manuellement, voir la mise en œuvre de Orchard.Projections.Handlers.FieldIndexPartHandler entrer en idée comment faire

Hope this helps.

: modifier

En raison d'appeler l'Create(...Published)ContentManager.Published() ne feront rien que l'élément est déjà considéré comme publié.

Vous pouvez faire ce qui suit pour forcer la publication logique à exécuter:

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); 

ou tout simplement créer l'élément comme un projet et de le publier quand tout est correctement configuré.

+1

Je peux confirmer que publier n'était pas le problème, mais appeler manuellement IFieldIndexService.Set chaque fois que je modifie une valeur de champ résout le problème avec des requêtes. J'ai ajouté l'appel exact que je fais (qui ressemble beaucoup à ce que Xceno a posté) à l'article original. – ub3rman123

+0

@ ub3rman123 Je pense que l'appel de publication ne fait rien pour vous parce que vous créez déjà l'article en tant que version publiée. Il y a une vérification d'intégrité dans le gestionnaire de contenu qui fait que la méthode ne fait rien lorsque l'élément est déjà publié. Voir ma réponse éditée sur comment résoudre ce problème. – ViRuSTriNiTy

1

Dans certains cas, un simple contentManager.Publish() ne fera pas. J'ai eu un problème similaire il y a quelque temps et j'ai implémenté un simple service d'assistance pour résoudre ce problème; voici un extrait:

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)); 
} 

Je suis en fait construit ce pour une utilisation avec des champs MediaLibrary- et ContentPicker (ils encodent leur valeur en tant que chaîne interne), il pourrait ne pas convenir au champ booléen dans votre exemple. Mais cela ne peut pas être si difficile à mettre en œuvre, il suffit de regarder les pilotes et les gestionnaires existants pour ces champs.