find all Episerver form

Vote:
 

Hi 

Is there any way to retrieve the all Episerver forms that created in all sites ?

I've found this one but didn't work:

https://lockevn.medium.com/how-do-i-programmatically-get-a-list-of-all-episerver-forms-that-are-submitted-17476c7b8e58

#286897
Sep 09, 2022 5:31
Vote:
 

what didn't work? did you get any FormsInfo to start with

#286899
Sep 09, 2022 8:29
Vote:
 

Yes, I got the form info. but it is only returning 2 entries which I have plenty of forms.

I think it maybe doesn't search through the all pages

Index already updated 

#286900
Sep 09, 2022 8:31
Vote:
 

Hi Vahid, does it have to be programatically? or can you do it through the database?

#286907
Sep 09, 2022 10:05
Vote:
 

Hello, 

A bit late to the party, but I encountered a similar issue while attempting to retrieve all instances of FormContainerBlock. Initially, I used the following code to obtain form instances:

var formsInfoCollection = _formRepository.GetFormsInfo(null);

This approach effectively fetched forms located under the 'forms' root folder, aligning with expected behavior. However, it didn't return all form instances located under the 'blocks' root folder or those created 'for this page'— which is where a significant number of form instances were situated for me.

In search of an alternative that could access forms from the 'blocks' root and for this page, I explored various methods within formRepository to no avail. My exploration led me to experiment with ContentModelUsage, which ultimately seemed to return the results I expected. For those facing similar challenges, this approach might offer a solution.


var formContainerBlocks = GetAllFormContainerBlocks();

private IEnumerable<FormContainerBlock> GetAllFormContainerBlocks()
{
    var references = FindAllFormContainerBlocks();
    var formContainerBlocks = new List<FormContainerBlock>();

    foreach (var reference in references)
    {
        if (_contentRepository.TryGet(reference, out FormContainerBlock formContainerBlock))
        {
            formContainerBlocks.Add(formContainerBlock);
        }
    }

    return formContainerBlocks;
}

public IEnumerable<ContentReference> FindAllFormContainerBlocks()
{
	var contentType = _contentTypeRepository.Load<FormContainerBlock>();
	var usages = _contentModelUsage.ListContentOfContentType(contentType)
		.Select(x => x.ContentLink.ToReferenceWithoutVersion())
		.Distinct();
	return usages;
}

I decided to share my experience here, as I stumbled upon this thread while searching for solutions to my issue.

Thanks

#317242
Edited, Feb 16, 2024 14:29
Vote:
 

There is an extension method in EPiServer.Forms.UI for the IContentTypeRepository that does all of this for you:

var forms = _contentTypeRepository.GetExistingForms();

If you decompile the code it does basically the same things ... the following is the decompiled code.

    public static IEnumerable<FormInfo> GetExistingForms(this IContentTypeRepository contentTypeRepository)
    {
        IEnumerable<ContentType> enumerable = from item in contentTypeRepository.List()
                                              where typeof(FormContainerBlock).IsAssignableFrom(item.ModelType)
                                              select item;
        List<FormInfo> list = new List<FormInfo>();
        IContentModelUsage instance = ServiceProviderExtensions.GetInstance<IContentModelUsage>(ServiceLocator.Current);
        IPermanentLinkMapper permanentLinkMapper = ServiceProviderExtensions.GetInstance<IPermanentLinkMapper>(ServiceLocator.Current);
        foreach (ContentType item in enumerable)
        {
            IList<ContentUsage> list2 = instance.ListContentOfContentType(item);
            if (list2 != null && list2.Any())
            {
                list.AddRange(list2.Select((ContentUsage x) => new FormInfo
                {
                    FormGuid = permanentLinkMapper.Find(x.ContentLink).Guid,
                    Id = x.ContentLink.ID,
                    Name = x.Name
                }));
            }
        }

        return list;
    }
#317408
Feb 20, 2024 16:28
Vincent - Feb 21, 2024 2:35
Thanks Mark. Good to know there is an existing method does the job though it's a bit weird to have this under ContentTypeRepoistory.
Mark Stott - Feb 21, 2024 14:30
It would make sense to put this in a IFormsRepository rather than making it an extension method of IContentTypeRepository. I literally stumbled on this because I was following a similar route to find all Form Container Blocks and then find and cleanse all form submissions associated with each instance of a form container block.
Quan Mai - Feb 21, 2024 14:39
I do think putting a List all method into a repository class is a bad idea - it's very easily misused, if not abused.
Vote:
 

Hey Mark, 

Thank you for the information. I suspected there would be a mechanism to accomplish this, I just couldn't find it 🙃!

To elaborate further on my implementation, I have a custom form container that extends the default FormContainerBlock . For example,

public class MyCustomFormContainerBlock : FormContainerBlock
{
    // Custom implementation details
}

During the development, I observed that the code snippet below exclusively retrieves forms matching the exact type specified. I was expecting inheritance to play a part but it didn't. I also called Load() passing in the IFormContainerBlock interface but that caused a null exception.

var contentType = _contentTypeRepository.Load<FormContainerBlock>();

I later stumbled upon https://world.optimizely.com/blogs/Anders-Hattestad/Dates/2014/2/Query-content-of-inherit-type-or-those-that-implements-an-interface/ which mentions inheritance and offers solutions to this. However, I needed this for a one-off task so just created two lists for each type and merged them. Not ideal, especially if you have lots of extended forms but got the job done. Is there where you tell me there is something to help me here too :) ?

I'll take a look at the GetExistingForms() method you shared.

Thanks

#317409
Edited, Feb 20, 2024 16:47
Mark Stott - Feb 20, 2024 16:53
The decompiled method code suggests it will handle the fact you have a custom FormContainerBlock. The opening statement is to get ALL content types from the IContentTypeRepository and then filters them to those which have a model that is assignable to the default FormContainerBlock. Definitely worth a try in your solution :)
Paul Griffiths - Feb 20, 2024 16:56
Even better! This is really good to know! Based on the code you shared it should solve the issue I experienced! I'll give it a try.

Thank you for sharing the information :)
Mark Stott - Feb 20, 2024 17:12
You’re welcome. Let me know how it works out for you :)
Vote:
 

The database is your friend...

SELECT c.pkID, cl.Name
FROM tblContent c, tblContentLanguage cl
WHERE c.pkId = cl.fkContentID AND c.fkContentTypeId IN (SELECT pkId FROM tblContentType WHERE Name = 'FormContainerBlock')
#317466
Feb 21, 2024 17:30
* 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.