我的模块通过控制器创建自定义内容项:
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项,其字段设置为true。查看仪表板中的内容项以及检查数据库中的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)
);
编辑:对此的修复是在使用此调用更改字段值时手动更改投影索引记录:
_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));
答案 0 :(得分: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字段(它们在内部将它们的值编码为字符串),因此它可能不适合您示例中的布尔字段。 但它实现起来并不困难,只需查看这些领域的现有驱动程序和处理程序。
答案 1 :(得分:0)
有两种方法可以解决这个问题:
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);
或者只是将项目创建为草稿,并在所有内容都正确设置后发布。