AllowedTypes attribute quirk

Vote:
 

The following attribute, when placed on a content area, will open up the "New Block: Form container" dialogue when you click "Create a New Block" within the content area:

[AllowedTypes(AllowedTypes = new Type[] { typeof(FormContainerBlock), typeof(AccordionBlock)})]

You then need to click out of that dialogue, and click "Create a New Block" again in order for the option to create an AccordionBlock. The bad behavior will go away for the entirety of your content entry. It will re-appear if you refresh or open the page in a new tab.

So, essentially, it is acting as if typeof(FormContainerBlock) is the only entry in the array. In addition, it does not matter if the FormContainerBlock element is first, last, or in the middle. It only matters that it is in the list. This is a small proof-of-concept from a larger implementation.

#272805
Feb 23, 2022 0:00
Vote:
 

Tricky issue to replicate and investigate. It could be related to content type permissions. Here is what I know about how the content types are displayed when creating new content. Hopefully it will help you 😄

The list of content types displayed when clicking on "Create new block" is filtered by the DefaultContentTypeAvailablilityService. It removes content types based on the user's access permissions. For example I believe it checks whether the user is allowed to create content in the 'For this page' folder. Then later the list is filtered again based on your AllowedTypes attribute.

To find out if the problem is related to the content type availability service (permissions issue probably) you can create a custom implementation and debug it to see if the AccordionBlock has been removed from the list at that point. Here is a snippet you can use:

public class CustomContentTypeAvailabilityService : DefaultContentTypeAvailablilityService
{
    public CustomContentTypeAvailabilityService(
        ServiceAccessor<IContentTypeRepository> contentTypeRepositoryAccessor,
        IAvailableModelSettingsRepository modelRepository,
        IAvailableSettingsRepository typeSettingsRepository,
        GroupDefinitionRepository groupDefinitionRepository,
        IContentLoader contentLoader,
        ISynchronizedObjectInstanceCache cache)
        : base(contentTypeRepositoryAccessor, modelRepository, typeSettingsRepository, groupDefinitionRepository,
            contentLoader, cache) { }

    /// <summary>
    /// Called every time a new page or block is being created
    /// and can be used to filter the displayed content types.
    /// </summary>
    public override IList<ContentType> ListAvailable(IContent content, bool contentFolder, IPrincipal user)
    {
        var contentTypes = base.ListAvailable(content, contentFolder, user);

        //Set a breakpoint here to see if the Accordion is not in the list
        return contentTypes;
    }
}

And to add it to the service context:

public void ConfigureContainer(ServiceConfigurationContext context)
{
    context.ConfigurationComplete += (_, _) =>
    {
        context.Services
            .AddSingleton<ContentTypeAvailabilityService, CustomContentTypeAvailabilityService>();
    };
}

Note: the content type will also not be listed when the AvailableInEditMode setting in the content type is set to false.

#272809
Edited, Feb 23, 2022 3:02
Zach Graceffa - Mar 10, 2022 14:59
While this answer didn't help me solve the exact question asked, I was able to implement a custom `DefaultContentTypeAvailablilityService` in order to achieve my ultimate goal. The issue at hand was to separate blocks and pages between 2 sites in a multi-site setup and this was a nice, singular, place to do so.
* You are NOT allowed to include any hyperlinks in the post because your account hasn't associated to your company. User profile should be updated.