EPiServer 11:以编程方式转换媒体类型
EPiServer 11: Convert media type programatically
有没有人尝试过在 EPiServer 中以编程方式转换媒体文件类型?
我们有一个为图像建模的类型,ImageFile,以及一个通过插件添加的类型。我们不使用插件添加的类型,但发现上传的图像有时会被创建为错误的类型。我希望弄清楚如何进行转换,这样我就可以 运行 一个预定的作业来批量转换它们,然后删除插件。
到目前为止,我可以通过编程方式将 A 复制为类型 B,然后删除 A。
我真正想做的是将 A 转换为 B 以实现无缝过渡。
我尝试的第一件事是将图像克隆为正确的类型,但结果为空
var media = _contentRepository.Service.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot)
.Where(i => _contentRepository.Service.Get<IContent>(i) is MediaData);
var imageFileTypeId = new ImageFile().ContentTypeID;
foreach (var img in media)
{
if (img.Get<IContent>() is GcEpiImageFile)
{
count++ // for summary
var item = _contentLoader.Service.Get<GcEpiImageFile>(img.Get<IContent>().ContentLink);
var cloneItem = item.CreateWritableClone() as ImageFile;
if (cloneItem == null)
{
var msg = $"{item.Name}: {item.ContentLink.ID} came up null";
OnStatusChanged(msg);
summaryMessage.AppendLine(msg);
continue;
}
cloneItem.ContentTypeID = imageFileTypeId;
_contentRepository.Service.Save(cloneItem, SaveAction.Publish, AccessLevel.NoAccess);
}
接下来我尝试将其克隆为基础 class ImageData,它似乎创建了对象,但在保存时抛出了未设置为对象实例的对象引用异常。
var media = _contentRepository.Service.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot)
.Where(i => _contentRepository.Service.Get<IContent>(i) is MediaData);
var imageFileTypeId = new ImageFile().ContentTypeID;
foreach (var img in media)
{
if (img.Get<IContent>() is GcEpiImageFile)
{
count++ // for summary
var item = _contentLoader.Service.Get<GcEpiImageFile>(img.Get<IContent>().ContentLink);
var cloneItem = item.CreateWritableClone() as ImageData;
if (cloneItem == null)
{
var msg = $"{item.Name}: {item.ContentLink.ID} came up null";
OnStatusChanged(msg);
summaryMessage.AppendLine(msg);
continue;
}
try
{
cloneItem.ContentTypeID = imageFileTypeId;
}
catch (Exception ex)
{
summaryMessage.AppendLine($"exception triggered by id assignment {ex.Message}<br />{ex.InnerException}");
}
try
{
_contentRepository.Service.Save(cloneItem, SaveAction.Publish, AccessLevel.NoAccess);
}
catch (Exception ex)
{
summaryMessage.AppendLine(
$"exception triggered by save {ex.Message}<br />{ex.InnerException}");
}
}
这是我的堆栈跟踪:
Object reference not set to an instance of an object.
at EPiServer.Validation.Internal.RoutingSegmentValidator.Validate(IContent instance) at
EPiServer.Validation.Internal.ContextValidatorWrapper`2.Validate(Object instance, Object context)
at EPiServer.Validation.Internal.ValidationService.ValidateRecursively(Object instance, Object context, HashSet`1 visitedInstances)
at EPiServer.Validation.Internal.ValidationService.Validate[T](Object instance, T context)
at EPiServer.Core.ContentProvider.Validate(IContent content, ContentSaveValidationContext saveValidationContext)
at EPiServer.Core.Internal.DefaultContentRepository.Save(IContent content, SaveAction action, AccessLevel access) at Web.Business.ScheduledJobs.ImageConversion.Execute()
如有任何想法、帮助和指导,我们将不胜感激
向 EPiServer developer forum 上的 Johann Kronberg 致敬以寻求他的帮助。
BEGIN TRANSACTION [ConvertTransaction]
BEGIN TRY
DECLARE @FromPropertyID1 int
DECLARE @ToPropertyID1 int
DECLARE @FromPropertyID2 int
DECLARE @ToPropertyID2 int
DECLARE @FromPropertyID3 int
DECLARE @ToPropertyID3 int
DECLARE @RC int
DECLARE @PageID int
DECLARE @FromPageType int
DECLARE @ToPageType int
DECLARE @Recursive bit
DECLARE @IsTest bit
SELECT @PageID = 1
#get your type ids from content type guid
SELECT @FromPageType = pkID FROM tblContentType WHERE ContentTypeGUID = 'guid of the media type being changed'
SELECT @ToPageType = pkID FROM tblContentType WHERE ContentTypeGUID = 'guid of the media type it is being change to'
#mapping properties THIS IS IMPORTANT!!!
SELECT @FromPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Copyright'
SELECT @FromPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Description'
SELECT @FromPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Notes'
SELECT @ToPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Copyright'
SELECT @ToPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Alt Text'
SELECT @ToPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Notes'
SET @Recursive = 1
SET @IsTest = 0
print @PageID
print @FromPageType
print @ToPageType
DECLARE @MasterLanguageID int
SET @MasterLanguageID = 8
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID1
,@ToPropertyID1
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID2
,@ToPropertyID2
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID3
,@ToPropertyID3
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPageType]
@PageID
,@FromPageType
,@ToPageType
,@Recursive
,@IsTest
print @RC
COMMIT TRANSACTION [ConvertTransaction]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [ConvertTransaction]
END CATCH
-- Run separately
DECLARE @FromPageType int
SELECT @FromPageType = pkID FROM tblContentType WHERE ContentTypeGUID = '0a89e464-56d4-449f-aea8-2bf774ab8730'
EXECUTE netContentTypeDelete @ContentTypeID = @FromPageType
注意 如果源类型的属性多于目标类型,则可能需要向目标添加属性。在我的第一个 运行 中,我能够转换类型,但无法删除目标类型。
有没有人尝试过在 EPiServer 中以编程方式转换媒体文件类型?
我们有一个为图像建模的类型,ImageFile,以及一个通过插件添加的类型。我们不使用插件添加的类型,但发现上传的图像有时会被创建为错误的类型。我希望弄清楚如何进行转换,这样我就可以 运行 一个预定的作业来批量转换它们,然后删除插件。
到目前为止,我可以通过编程方式将 A 复制为类型 B,然后删除 A。 我真正想做的是将 A 转换为 B 以实现无缝过渡。
我尝试的第一件事是将图像克隆为正确的类型,但结果为空
var media = _contentRepository.Service.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot)
.Where(i => _contentRepository.Service.Get<IContent>(i) is MediaData);
var imageFileTypeId = new ImageFile().ContentTypeID;
foreach (var img in media)
{
if (img.Get<IContent>() is GcEpiImageFile)
{
count++ // for summary
var item = _contentLoader.Service.Get<GcEpiImageFile>(img.Get<IContent>().ContentLink);
var cloneItem = item.CreateWritableClone() as ImageFile;
if (cloneItem == null)
{
var msg = $"{item.Name}: {item.ContentLink.ID} came up null";
OnStatusChanged(msg);
summaryMessage.AppendLine(msg);
continue;
}
cloneItem.ContentTypeID = imageFileTypeId;
_contentRepository.Service.Save(cloneItem, SaveAction.Publish, AccessLevel.NoAccess);
}
接下来我尝试将其克隆为基础 class ImageData,它似乎创建了对象,但在保存时抛出了未设置为对象实例的对象引用异常。
var media = _contentRepository.Service.GetDescendents(SiteDefinition.Current.GlobalAssetsRoot)
.Where(i => _contentRepository.Service.Get<IContent>(i) is MediaData);
var imageFileTypeId = new ImageFile().ContentTypeID;
foreach (var img in media)
{
if (img.Get<IContent>() is GcEpiImageFile)
{
count++ // for summary
var item = _contentLoader.Service.Get<GcEpiImageFile>(img.Get<IContent>().ContentLink);
var cloneItem = item.CreateWritableClone() as ImageData;
if (cloneItem == null)
{
var msg = $"{item.Name}: {item.ContentLink.ID} came up null";
OnStatusChanged(msg);
summaryMessage.AppendLine(msg);
continue;
}
try
{
cloneItem.ContentTypeID = imageFileTypeId;
}
catch (Exception ex)
{
summaryMessage.AppendLine($"exception triggered by id assignment {ex.Message}<br />{ex.InnerException}");
}
try
{
_contentRepository.Service.Save(cloneItem, SaveAction.Publish, AccessLevel.NoAccess);
}
catch (Exception ex)
{
summaryMessage.AppendLine(
$"exception triggered by save {ex.Message}<br />{ex.InnerException}");
}
}
这是我的堆栈跟踪:
Object reference not set to an instance of an object.
at EPiServer.Validation.Internal.RoutingSegmentValidator.Validate(IContent instance) at
EPiServer.Validation.Internal.ContextValidatorWrapper`2.Validate(Object instance, Object context)
at EPiServer.Validation.Internal.ValidationService.ValidateRecursively(Object instance, Object context, HashSet`1 visitedInstances)
at EPiServer.Validation.Internal.ValidationService.Validate[T](Object instance, T context)
at EPiServer.Core.ContentProvider.Validate(IContent content, ContentSaveValidationContext saveValidationContext)
at EPiServer.Core.Internal.DefaultContentRepository.Save(IContent content, SaveAction action, AccessLevel access) at Web.Business.ScheduledJobs.ImageConversion.Execute()
如有任何想法、帮助和指导,我们将不胜感激
向 EPiServer developer forum 上的 Johann Kronberg 致敬以寻求他的帮助。
BEGIN TRANSACTION [ConvertTransaction]
BEGIN TRY
DECLARE @FromPropertyID1 int
DECLARE @ToPropertyID1 int
DECLARE @FromPropertyID2 int
DECLARE @ToPropertyID2 int
DECLARE @FromPropertyID3 int
DECLARE @ToPropertyID3 int
DECLARE @RC int
DECLARE @PageID int
DECLARE @FromPageType int
DECLARE @ToPageType int
DECLARE @Recursive bit
DECLARE @IsTest bit
SELECT @PageID = 1
#get your type ids from content type guid
SELECT @FromPageType = pkID FROM tblContentType WHERE ContentTypeGUID = 'guid of the media type being changed'
SELECT @ToPageType = pkID FROM tblContentType WHERE ContentTypeGUID = 'guid of the media type it is being change to'
#mapping properties THIS IS IMPORTANT!!!
SELECT @FromPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Copyright'
SELECT @FromPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Description'
SELECT @FromPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @FromPageType AND [Name] = 'Notes'
SELECT @ToPropertyID1 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Copyright'
SELECT @ToPropertyID2 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Alt Text'
SELECT @ToPropertyID3 = pkID FROM tblPropertyDefinition WHERE fkContentTypeID = @ToPageType AND [Name] = 'Notes'
SET @Recursive = 1
SET @IsTest = 0
print @PageID
print @FromPageType
print @ToPageType
DECLARE @MasterLanguageID int
SET @MasterLanguageID = 8
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID1
,@ToPropertyID1
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID2
,@ToPropertyID2
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPropertyForPageType]
@PageID
,@FromPageType
,@FromPropertyID3
,@ToPropertyID3
,@Recursive
,@MasterLanguageID
,@IsTest
print @RC
EXECUTE @RC = [dbo].[netConvertPageType]
@PageID
,@FromPageType
,@ToPageType
,@Recursive
,@IsTest
print @RC
COMMIT TRANSACTION [ConvertTransaction]
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION [ConvertTransaction]
END CATCH
-- Run separately
DECLARE @FromPageType int
SELECT @FromPageType = pkID FROM tblContentType WHERE ContentTypeGUID = '0a89e464-56d4-449f-aea8-2bf774ab8730'
EXECUTE netContentTypeDelete @ContentTypeID = @FromPageType
注意 如果源类型的属性多于目标类型,则可能需要向目标添加属性。在我的第一个 运行 中,我能够转换类型,但无法删除目标类型。