-
Hi everyone, I already discussed a similar topic here. Last time, when I used the Now I have implemented a module with a Here is my handler implementation: public class CustomBagPartHandler : ContentPartHandler<BagPart>
{
private readonly IContentDefinitionManager _contentDefinitionManager;
private readonly IActionContextAccessor _actionContextAccessor;
public CustomBagPartHandler(IContentDefinitionManager contentDefinitionManager,
IActionContextAccessor actionContextAccessor)
{
_contentDefinitionManager = contentDefinitionManager;
_actionContextAccessor = actionContextAccessor;
}
public override async Task UpdatingAsync(UpdateContentContext context, BagPart part)
{
BagPartCustomSettingsList? settings = await GetSettingsAsync(part);
if (settings?.ContentTypeSettings != null)
{
foreach (BagPartCustomContentTypeSettings contentTypeSetting in settings.ContentTypeSettings)
{
// Filter content items by the current content type setting
IEnumerable<ContentItem> contentItemsOfType = part.ContentItems.Where(ci => ci.ContentType == contentTypeSetting.ContentType);
int count = contentItemsOfType.Count();
// Validate against the min and max settings for this content type
// Allow the possibility to have Min and Max = 0
if (count < contentTypeSetting.MinItems || (contentTypeSetting.MaxItems > 0 && count > contentTypeSetting.MaxItems))
{
_actionContextAccessor.ActionContext?.ModelState?.AddModelError(nameof(CustomBagPartHandler), $"The number of {contentTypeSetting.ContentType} items in the bag must be between {contentTypeSetting.MinItems} and {contentTypeSetting.MaxItems}. Current count: {contentItemsOfType.Count()}.");
}
}
}
await Task.CompletedTask;
}
private async Task<BagPartCustomSettingsList> GetSettingsAsync(BagPart part)
{
ContentTypeDefinition contentTypeDefinition = await _contentDefinitionManager.GetTypeDefinitionAsync(part.ContentItem.ContentType);
ContentTypePartDefinition? contentTypePartDefinition = contentTypeDefinition?.Parts?.FirstOrDefault(x => string.Equals(x.PartDefinition.Name, nameof(BagPart), StringComparison.Ordinal));
return contentTypePartDefinition?.GetSettings<BagPartCustomSettingsList>();
}
} The handler correctly retrieves the Here is what's inside And here is what's inside I suspected that during the This is how I implemented the public override async Task ValidatingAsync(ValidateContentContext context, BagPart part)
{
var settings = await GetSettingsAsync(part);
if (settings?.ContentTypeSettings != null)
{
foreach (var setting in settings.ContentTypeSettings)
{
var contentItemsOfType = part.ContentItems.Where(ci => ci.ContentType == setting.ContentType);
int count = contentItemsOfType.Count();
if (count < setting.MinItems || (setting.MaxItems > 0 && count > setting.MaxItems))
{
context.Fail(string.Format("The number of {0} items in the bag must be between {1} and {2}. Current count: {3}.",
setting.ContentType, setting.MinItems, setting.MaxItems, count));
}
}
}
} Unfortunately the What am I doing wrong? I have spent several hours trying to fix this, also searching for an example in the Orchard Core solution, without success. Thank you |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 8 replies
-
I don't have a solution from the top of my head, but here's a video with voice about how I'd approach figuring it out. 2024-05-03_01h14_33.mp4 |
Beta Was this translation helpful? Give feedback.
I believe when you say new/existing "Content Type", you mean "content item" instead.
ContentManager.ValidateAsync()
. This seems correct.UpdatingAsync
being called for a new content type also seems correct if you check out where it's called.UpdatingAsync
receivingnull
in itspart
parameter for new content items doesn't seem correct. However, that's not what I see in your screenshot. It being empty (but not `null) is expected, since this event is called before the content item is updated with new data from POST. Due to this, it's also expected that you'll see some value (the old one, before the update) for an existing content item.