-
Notifications
You must be signed in to change notification settings - Fork 2.5k
Description
Greetings!
As suggested, I split this issue from the original #18177
ISSUE: there is no way to tell if I am uploading directly to the Media Library or in a Media Field attached to a content item.
Related to the same handler, I found no way to tell if I am uploading a new file to the library itself or to attach it to an existing content item. This is an issue, because the implementation of IMediaCreatingEventHandler.MediaCreatingAsync ends up creating a new content item with the new media attached to its MediaField, which would be redundant.
For reference, here's my code:
From class ContentCreationMediaCreatingEventHandler : IMediaCreatingHandler
public async Task<Stream> MediaCreatingAsync(MediaCreatingContext context, Stream creatingStream) {
// Use a scope to get scoped services from the Service Provider.
// This is needed because this handler is loaded as a singleton at startup,
// but content manager is scoped.
// Get the scope from the shell settings.
var shellScope = _shellHost.GetScopeAsync(_shellSettings).GetAwaiter().GetResult();
var contentCreated = true;
await shellScope.UsingAsync(async scope => {
var mediaManagementService = scope.ServiceProvider.GetRequiredService<IMediaManagementService>();
var ci = mediaManagementService.CreateMediaContent(context);
contentCreated = ci != null;
});
if (!contentCreated) {
return null;
}
var outStream = MemoryStreamFactory.GetStream();
await creatingStream.CopyToAsync(outStream);
outStream.Seek(0, SeekOrigin.Begin);
return outStream;
}
From MediaManagementService : IMediaManagementService (custom service)
public async Task<IContent> CreateMediaContent(MediaCreatingContext context) {
var mediaContent = await _contentManager.NewAsync("MediaContent");
//var mediaFileField = ((MediaField)mediaContent.Content.MediaData.MediaFile);
var mediaDataPart = mediaContent.Get<ContentPart>("MediaData");
var mediaFileField = mediaDataPart?.Get<MediaField>("MediaFile");
if (mediaFileField != null) {
mediaFileField.Paths = [context.Path];
mediaFileField.MediaTexts = [""];
}
// Apply the updated field to the part.
mediaDataPart.Apply("MediaFile", mediaFileField);
mediaDataPart.Apply();
var titlePart = mediaContent.Get<TitlePart>("TitlePart");
// Title is the file name of the media.
titlePart.Title = Path.GetFileNameWithoutExtension(context.Path);
titlePart.Apply();
// MediaContent is saved as draft to let the user add additional info before publishing it.
var result = await _contentManager.UpdateValidateAndCreateAsync(mediaContent, VersionOptions.Draft);
if (result.Succeeded) {
await _contentManager.SaveDraftAsync(mediaContent);
}
return mediaContent;
}
Possible solutions
Here is where I fall short: I checked how the MediaField views work and the javascript scripts involving the file upload and the display of the media library interface and the things coming to my mind are basically two:
- Call a different controller (a custom one, for instance) to avoid calling the handlers that involve the content creation. This also means creating alternates for the MediaField views to force this hidden field:
OrchardCore/src/OrchardCore.Modules/OrchardCore.Media/Views/Admin/MediaApplication.cshtml
Line 128 in cd83239
<input type="hidden" id="uploadFiles" value="@Url.Action("Upload", "Admin", new { area = "OrchardCore.Media" })" />
to have the value of the new controller. - Upgrade the controller to tell it the media library popup has been opened by a Media Field. This would give me the information I need to also upgrade the MediaCreatingContext object (which inherits from MediaContextBase and currently only has a Path property) and add it the information I need via one or more additional properties.
I would rather pursue solution 2, as it looks more clean.
What are your thoughts about this?
Thanks,
Andrea