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;
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"}
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.
update :
I implemented this :
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;
and it is giving me a weird error :
does anyone have any idea what is this?
thank you.
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.