2016-08-17 3 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; 
    } 

これの最終結果がtrueに設定されていますフィールドを持つ新しいをTestTypeアイテムです。ダッシュボードでコンテンツアイテムを表示し、データベース内のContentItemVersionRecordを調べると、値が正しく設定されていることが確認されます。

ただし、この方法で設定したフィールドではクエリが正しく機能していないようです。 IntegerFieldIndexRecordというレコードが見つかりました。これは、投影がクエリ結果ページを埋めるために使用すると仮定したものです。この場合、TestFieldの値は1(真​​)ではなく0(偽)のままです。

コンテンツアイテムの編集ページに移動し、単に「保存」をクリックすると、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) 
      ); 

編集:これに対する修正は、フィールド値を変更するたびに、手動でこのコールを使用して、投影インデックスレコードを変更することである。

_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に聞いて、新しく作成されたアイテムが公開されていることを確認します。このことができます。この

希望を行うにはどのような考え方で取得するOrchard.Projections.Handlers.FieldIndexPartHandlerの実装を参照して、手動でFieldIndexPartRecordを更新するためにIFieldIndexServiceを使用)FieldIndexPartRecord

2を更新するために、イベントを公開します。

:編集

により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

publishが問題ではないことを確認できますが、フィールド値を変更するたびに手動で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分野で使用するためにこれを構築しましたので、それはあなたの例では、ブールフィールドには適していない可能性があります。 しかし実装するのは難しいことではありません。既存のドライバとハンドラを見てください。