2016-08-17 3 views
1

Mein Modul erstellt ein benutzerdefiniertes Inhaltselement durch den Controller:Feldindex für Abfragen nicht aktualisiert, wenn Wert programmatisch

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

Das Endergebnis ist dies ein neues Testtype Element mit einem Feld, das auf true gesetzt wird. Das Anzeigen des Inhaltselements im Dashboard sowie das Überprüfen von ContentItemVersionRecord in der Datenbank bestätigen, dass der Wert korrekt festgelegt wurde.

Abfragen auf Feldern, die auf diese Weise festgelegt werden, scheinen jedoch nicht ordnungsgemäß zu funktionieren. Ich habe den Datensatz IntegerFieldIndexRecord gefunden, den ich für Prognosen verwende, um die Abfrageergebnisseiten zu füllen. Der Wert von TestField bleibt dabei auf 0 (falsch) anstelle von 1 (wahr).

Wenn Sie auf die Bearbeitungsseite des Inhaltselements gehen und einfach auf "Speichern" klicken, wird IntegerFieldIndexRecord korrekt aktualisiert, was bedeutet, dass der Wert jetzt von der Abfrage erfasst wird. Wie kann der Datensatz für programmatisch festgelegte Feldwerte aktualisiert werden?

Relevante Abschnitt der 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: Die Lösung für dieses ist, um manuell den Projektionsindexdatensatz zu ändern, wenn ein Feldwert zu ändern, mit diesem Aufruf:

_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

Haben Sie versucht, _contentManager.Publish (TestItem) '? –

+0

Die Antworten unten behebt das Problem. Es sieht so aus, als würde der Handler von FieldIndexPart den Datensatz nicht automatisch ändern, wenn sich der Wert des Feldes ändert.Publishing sollte es auslösen, tut es aber nicht. – ub3rman123

Antwort

0

Es gibt 2 Möglichkeiten, um dies zu beheben:

1) Stellen Sie sicher, dass das neu erstellte Element veröffentlicht wird, indem Sie ContentManager.Publish() als Orchard.Projections.Handlers.FieldIndexPartHandler hört die FieldIndexPartRecord

2) IFieldIndexService veröffentlichen Veranstaltung zu aktualisieren verwenden FieldIndexPartRecord manuell zu aktualisieren, siehe Umsetzung von Orchard.Projections.Handlers.FieldIndexPartHandler in Idee zu bekommen, wie diese das hilft

Hoffnung zu tun.

: bearbeiten

Aufgrund Create(...Published) der ContentManager.Published() Aufruf wird nichts tun, wenn der Gegenstand bereits veröffentlicht wird berücksichtigt.

Sie können die Logik veröffentlichen zu Zwingen folgendes auszuführen:

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

oder einfach nur das Element als Entwurf erstellen und veröffentlichen, wenn alles richtig eingerichtet ist.

+1

Ich kann bestätigen, dass die Veröffentlichung nicht das Problem war, aber das manuelle Aufrufen von IFieldIndexService.Set jedes Mal, wenn ich einen Feldwert ändere, behebt das Problem mit Abfragen. Ich habe den exakten Anruf, den ich mache (der Xceno sehr ähnlich sieht), zum ursprünglichen Beitrag hinzugefügt. – ub3rman123

+0

@ ub3rman123 Ich denke, der Veröffentlichungsaufruf tut nichts für Sie, weil Sie das Objekt bereits als veröffentlichte Version erstellen. Im Content-Manager gibt es eine Plausibilitätsprüfung, die dazu führt, dass die Methode nichts unternimmt, wenn das Element bereits veröffentlicht wurde. Sehen Sie meine bearbeitete Antwort zur Lösung dieses Problems. – ViRuSTriNiTy

1

In einigen Fällen wird eine einfache contentManager.Publish() nicht tun. Ich hatte vor einiger Zeit ein ähnliches Problem und implementierte tatsächlich einen einfachen Hilfsdienst, um dieses Problem anzugehen; Hier ein Auszug:

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

ich diese Nutzung für tatsächlich gebaut habe mit MediaLibrary- und ContentPicker Feldern (sie ihren Wert als String intern kodieren), so dass es möglicherweise nicht für das Boolesche Feld in Ihrem Beispiel geeignet sein. Aber es kann nicht so schwer zu implementieren sein, sehen Sie sich nur die vorhandenen Treiber und Handler für diese Felder an.

Verwandte Themen