Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • myname 3 posts 73 karma points
    Mar 03, 2021 @ 12:34
    myname
    0

    Umbraco forms - commercial version - how to make custom export type for forms (documentation is wrong/outdated)

    Greetings, I got forms commercial version couple of days ago and I have a requirement for a custom export type at forms so I followed this https://our.umbraco.com/documentation/Add-ons/UmbracoForms/Developer/Extending/Adding-a-Exporttype (the advanced example) but the FormRecordSearcher is giving me (inaccessible due to its protection level) , I also tried this here https://gist.github.com/ceee/3a4053b16f61850baa987a8888e456e6 based on a forum post from 2017 here , found here , https://our.umbraco.com/forum/umbraco-forms/86774-custom-umbraco-forms-export-to-file and it doesn't work too giving me loads of errors and missing references, can someone help me with this, I need to add pdf export type for entries as the example at documentation,

    thank you.

  • myname 3 posts 73 karma points
    Mar 03, 2021 @ 15:56
    myname
    0

    update :

    I implemented this :

    using System;
    

    using System.Collections.Generic; using System.IO; using System.IO.Compression; using System.Linq; using System.Text; using System.Threading.Tasks; using Umbraco.Core; using Umbraco.Core.IO; using Umbraco.Core.Logging; using Umbraco.Core.Services; using Umbraco.Forms; using Umbraco.Forms.Core; using Umbraco.Forms.Core.Models; using Umbraco.Forms.Core.Enums; using Umbraco.Forms.Data.Storage; using Umbraco.Core.Persistence; using System.Globalization; using Umbraco.Forms.Core.Searchers; using Umbraco.Forms.Core.Persistence.Dtos; using Umbraco.Forms.Core.Interfaces; using Umbraco.Core.Scoping; using System.Data; using Newtonsoft.Json; using Umbraco.Core.Models; using NPoco; using Umbraco.Forms.Core.Services; using Umbraco.Web; using Umbraco.Forms.Core.Data.Storage;

    namespace UmbracoPDFexport { public class _formRecordSearcher : IFormRecordSearcher { private readonly IFieldTypeStorage _fieldTypeStorage; private readonly IFormStorage _formStorage; private readonly ILocalizedTextService _localizedTextService; private readonly IMemberService _memberService; private readonly IScopeProvider _scopeProvider; private readonly IUmbracoContextAccessor _umbracoContextAccessor;

        public global::NPoco.Sql BuildSqlQuery(IScope scope, RecordFilter model, string select = "")
        {
            throw new NotImplementedException();
        }
    
        //public EntrySearchResultCollection QueryDataBase(RecordFilter model)
        //{
        //    throw new NotImplementedException();
        //}
        public EntrySearchResultCollection QueryDataBase(RecordFilter model) => this.QueryDataBaseForSubmissions(model, true);
    
        private EntrySearchResultCollection QueryDataBaseForSubmissions(RecordFilter model, bool enforceSensitiveData = true)
        {
            bool? scopeFileSystems = null;
            using (IScope scope = this._scopeProvider.CreateScope(IsolationLevel.Unspecified, RepositoryCacheMode.Unspecified, null, scopeFileSystems, false, false))
            {
                bool flag = this._umbracoContextAccessor.UmbracoContext.Security.CurrentUser.HasAccessToSensitiveData();
                Form form = this._formStorage.GetForm(model.Form);
                Sql sql = this.BuildSqlQuery(scope, model, "");
                Page<Record> page = scope.Database.Page<Record>((long)model.StartIndex, (long)model.Length, sql);
                EntrySearchResultCollection collection1 = new EntrySearchResultCollection();
                collection1.TotalNumberOfResults = page.TotalItems;
                collection1.TotalNumberOfPages = page.TotalPages;
                EntrySearchResultCollection results = collection1;
                //bool flag2 = Configuration.IsTrial && !Licensing.IsLocalBrowserRequest();
                List<EntrySearchResult> list = new List<EntrySearchResult>();
                if (form != null)
                {
                    List<EntrySearchResultSchema> list2 = new List<EntrySearchResultSchema>();
                    foreach (Field field in form.AllFields)
                    {
                        FieldType fieldTypeByField = this._fieldTypeStorage.GetFieldTypeByField(field);
                        if (fieldTypeByField.StoresData)
                        {
                            EntrySearchResultSchema schema1 = new EntrySearchResultSchema();
                            schema1.Name = field.Caption;
                            schema1.Id = field.Id.ToString();
                            schema1.View = fieldTypeByField.RenderView;
                            EntrySearchResultSchema schema = schema1;
                            if (field.ContainsSensitiveData)
                            {
                                schema.ContainsSensitiveData = true;
                            }
                            list2.Add(schema);
                        }
                    }
                    EntrySearchResultSchema item = new EntrySearchResultSchema();
                    item.Id = "member";
                    item.View = "member";
                    item.Name = "Member";
                    item.ContainsSensitiveData = true;
                    list2.Add(item);
                    EntrySearchResultSchema schema4 = new EntrySearchResultSchema();
                    schema4.Id = "state";
                    schema4.View = "text";
                    schema4.Name = "State";
                    list2.Add(schema4);
                    EntrySearchResultSchema schema5 = new EntrySearchResultSchema();
                    schema5.Id = "created";
                    schema5.View = "date";
                    schema5.Name = "Created";
                    list2.Add(schema5);
                    EntrySearchResultSchema schema6 = new EntrySearchResultSchema();
                    schema6.Id = "updated";
                    schema6.View = "date";
                    schema6.Name = "Updated";
                    list2.Add(schema6);
                    results.schema = list2;
                }
                foreach (Record record in page.Items)
                {
                    EntrySearchResult result1 = new EntrySearchResult();
                    result1.Id = record.Id;
                    result1.Form = record.Form.ToString();
                    result1.State = record.StateAsString;
                    EntrySearchResult item = result1;
                    int num = -model.LocalTimeOffset;
                    DateTimeOffset now = DateTimeOffset.Now;
                    TimeSpan offset = now.Offset;
                    int num2 = Convert.ToInt32(offset.TotalMinutes);
                    int num3 = num - num2;
                    item.Created = record.Created.AddMinutes((double)num3);
                    item.Updated = record.Updated.AddMinutes((double)num3);
                    item.UniqueId = record.UniqueId;
                    try
                    {
                        if (!string.IsNullOrEmpty(record.MemberKey))
                        {
                            IMember byId = this._memberService.GetById(Convert.ToInt32(record.MemberKey));
                            if (byId != null)
                            {
                                item.Member = byId;
                            }
                        }
                    }
                    catch (Exception ex)
                    {
    
                        //do nothing
                    }
                    if ((form != null) && !string.IsNullOrEmpty(record.RecordData))
                    {
                        Dictionary<string, string> dictionary = JsonConvert.DeserializeObject<Dictionary<string, string>>(record.RecordData);
                        List<object> list3 = new List<object>();
                        string str = _localizedTextService.Localize("content/isSensitiveValue", CultureInfo.CurrentCulture, null);
                        foreach (EntrySearchResultSchema schema2 in results.schema.Take<EntrySearchResultSchema>(results.schema.Count<EntrySearchResultSchema>() - 4))
                        {
                            if (!dictionary.ContainsKey(schema2.Id))
                            {
                                list3.Add(string.Empty);
                                continue;
                            }
                            //if (flag2)
                            //{
                            //    list3.Add(Configuration.TrialSaveMessage);
                            //    continue;
                            //}
                            if ((flag || !schema2.ContainsSensitiveData) ? (enforceSensitiveData && schema2.ContainsSensitiveData) : true)
                            {
                                list3.Add(str);
                                continue;
                            }
                            list3.Add(dictionary[schema2.Id]);
                        }
                        try
                        {
                            list3.Add(item.Member);
                        }
                        catch (Exception ex)
                        {
    
                           //do nothing
                        }
                        list3.Add(item.State);
                        list3.Add(item.Created);
                        list3.Add(item.Updated);
                        item.Fields = list3;
                    }
                    list.Add(item);
                }
                results.Results = list;
                scope.Complete();
                return results;
            }
        }
    }
    public class ExportToTextFile : ExportType
    {
        public ExportToTextFile()
        {
            this.Name = "Export as pdf files";
            this.Description = "Export entries as pdf files inside a zip file";
            this.Id = new Guid("171CABC9-2207-4575-83D5-2A77E824D5DB");
            this.FileExtension = "zip";
            this.Icon = "icon-zip";
        }
    
        /// <summary>
        /// We do not implement this method from the interface
        /// As this method is called from ExportToFile that we also override here & is expecting the file contents as a string to be written as a stream to a file
        /// Which would be OK if we were creating a CSV or a single based file that can have a simple string written as a string such as one large HTML report or XML file perhaps
        /// </summary>
    
        public override string ExportRecords(RecordExportFilter filter)
        {
            throw new NotImplementedException();
        }
    
        /// <summary>
        /// This gives us greater control of the export process
        /// </summary>
        /// <param name="filter">
        /// This filter contains the date range & other search parameters to limit the entries we are exporting
        /// </param>
        /// <param name="filepath">
        /// The filepath that the export file is expecting to be served from
        /// So ensure that the zip of text files is saved at this location
        /// </param>
        /// <returns>The final file path to serve up as the export - this is unlikely to change through the export logic</returns>
        public override string ExportToFile(RecordExportFilter filter, string filepath)
        {
            // Before Save - Check Path, Directory & Previous File export does not exist
            string pathToSaveZipFile = filepath;
    
            // Check our path does not contain \\
            // If not, use the filePath
            if (filepath.Contains('\\') == false)
            {
                pathToSaveZipFile = IOHelper.MapPath(filepath);
            }
    
            // Get the directory (strip out \\ if it exists)
            var dir = filepath.Substring(0, filepath.LastIndexOf('\\'));
            var tempFileDir = Path.Combine(dir, "text-files");
    
    
            // If the path does not end with our file extension, ensure it's added
            if (pathToSaveZipFile.EndsWith("." + FileExtension) == false)
            {
                pathToSaveZipFile += "." + FileExtension;
            }
    
            // Check that the directory where we will save the ZIP file temporarily exists
            // If not just create it
            if (Directory.Exists(tempFileDir) == false)
            {
                Directory.CreateDirectory(tempFileDir);
            }
    
            // Check if the zip file exists already - if so delete it, as we have a new update
            if (System.IO.File.Exists(pathToSaveZipFile))
            {
                System.IO.File.Delete(pathToSaveZipFile);
            }
    
    
            // Query the DB for submissions to export based on the filter
    
            _formRecordSearcher recordSearcher = new _formRecordSearcher();
            EntrySearchResultCollection submissions = recordSearcher.QueryDataBase(filter);
    
            // Get the schema objects to a list so we can get items using position index
            var schemaItems = submissions.schema.ToList();
    
            // We will use this to store our contents of our file to save as a text file
            var fileContents = string.Empty;
    
            // For each submission we have build up a string to save to a text file
            foreach (var submission in submissions.Results)
            {
                // The submitted data for the form submission
                var submissionData = submission.Fields.ToList();
    
                // For loop to match the schema position to the submission data
                for (int i = 0; i < schemaItems.Count; i++)
                {
                    // Concat a string of the name of the field & its stored data
                    fileContents += schemaItems[i].Name + ": " + submissionData[i] + Environment.NewLine;
                }
    
                // Now save the contents to a text file
                // Base it on the format of the record submission unique id
                var textFileName = Path.Combine(tempFileDir, submission.UniqueId + ".pdf");
                System.IO.File.WriteAllText(textFileName, fileContents);
    
                // Reset fileContents to be empty again
                fileContents = string.Empty;
            }
    
            // Now we have a temp folder full of text files
            // Generate a zip file containing them & save that
            ZipFile.CreateFromDirectory(tempFileDir, pathToSaveZipFile);
    
            // Tidy up after ourselves & delete the temp folder of text files
            if (Directory.Exists(tempFileDir))
            {
                Directory.Delete(tempFileDir, true);
            }
    
            // Return the path where we saved the zip file containing the text files
            return pathToSaveZipFile;
        }
    
    }
    

    and it is giving me a weird error :

    Possibly unhandled rejection: {"data":{"Message":"An error has occurred.","ExceptionMessage":"Object reference not set to an instance of an object.","ExceptionType":"System.NullReferenceException","StackTrace":"   at UmbracoPDFexport._formRecordSearcher.QueryDataBaseForSubmissions(RecordFilter model, Boolean enforceSensitiveData)\r\n   at UmbracoPDFexport._formRecordSearcher.QueryDataBase(RecordFilter model)\r\n   at UmbracoPDFexport.ExportToTextFile.ExportToFile(RecordExportFilter filter, String filepath)\r\n   at Umbraco.Forms.Web.Editors.ExportController.PostGenerateExport(RecordExportFilter model)\r\n   at lambda_method(Closure , Object , Object[] )\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass6_2.<GetExecutor>b__2(Object instance, Object[] methodParameters)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.Execute(Object instance, Object[] arguments)\r\n   at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__1.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<CallOnActionExecutedAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.ActionFilterAttribute.<ExecuteActionFilterAsyncCore>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__5.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Filters.AuthorizationFilterAttribute.<ExecuteAuthorizationFilterAsyncCore>d__3.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Web.Http.Controllers.ExceptionFilterResult.<ExecuteAsync>d__6.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n   at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n   at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n   at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__15.MoveNext()"},"status":500,"config":{"method":"POST","transformRequest":[null],"transformResponse":[null],"jsonpCallbackParam":"callback","url":"backoffice/UmbracoForms/Export/PostGenerateExport","data":{"startIndex":1,"length":20,"form":"b2413bd7-54f0-46eb-a7ad-0fde030638f1","sortBy":"created","sortOrder":"descending","states":["Approved","Submitted"],"localTimeOffset":-120,"exportType":"171cabc9-2207-4575-83d5-2a77e824d5db"},"headers":{"Accept":"application/json, text/plain, */*","Content-Type":"application/json;charset=utf-8","X-Requested-With":"XMLHttpRequest","X-UMB-XSRF-TOKEN":"BZoVuqZZ8PZ4WL-xVe57KWIHU1cQR8u33G9G0PPFD-P4zmp6jbK9N2k1I6dC4KfJ74kYl6mPIhXCO-bnvpWy5HlWSH2Pu0CbgmbkEp4XRd9bq1XW3jN4SsMSmBVMgf2yCZCihMUAFknk-HEXWgn20Q2"}},"statusText":"","xhrStatus":"complete"}
    

    does anyone have any idea what is this?

    thank you.

  • John C Scott 473 posts 1183 karma points
    Apr 19, 2022 @ 10:32
    John C Scott
    0

    Hi just wondering if you ever worked this out. And also what would need to be updated in the documentation.

Please Sign in or register to post replies

Write your reply to:

Draft