Dynamic Types and the Forms API
Hello All!
private
void
EnsureForm()
FormDescription fd;
using
(FormsManager mgr = FormsManager.GetManager())
mgr.Provider.SuppressSecurityChecks =
true
;
if
(mgr.GetForms()
.Where(f => f.Id == ContactFormId)
.FirstOrDefault() ==
null
)
fd = mgr.CreateForm(
"ContactInfo"
, ContactFormId);
fd.Name =
"ContactInfo"
;
fd.Status = ContentLifecycleStatus.Live;
fd.SubmitAction = SubmitAction.TextMessage;
fd.SubmitRestriction = SubmitRestriction.None;
fd.SuccessMessage =
"Thank you for contacting us. We will get back with you soon."
;
fd.Description =
"Flexible contact form"
;
mgr.SaveChanges();
private
void
EnsureDynamicFields(FluentSitefinity fs,
ref
bool
restart)
if
(fs.DynamicData().Types().Where(t => t.Id == ContactTypeId)
.Get().FirstOrDefault() ==
null
)
bool
changeDb =
false
;
fs.DynamicData().Type().CreateNew(
"ContactInfo"
,
"Telerik.Sitefinity.DynamicTypes.Model"
, ContactTypeId)
.Field().TryCreateNew(
"FormName"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Prefix"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"FirstName"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"LastName"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Email"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Phone"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Address"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"City"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"State"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"ZipCode"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Country"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Title"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Experience"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"OrganizationName"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"OrganizationType"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"OtherType"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Materials"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"MoreInfo"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Notes"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"EducationLevel"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Expertise"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"OtherExpertise"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"Role"
,
typeof
(
string
),
ref
changeDb).Done()
.Field().TryCreateNew(
"GeoArea"
,
typeof
(
string
),
ref
changeDb).Done()
.SaveChanges(
true
);
if
(changeDb)
restart = changeDb;
protected
bool
SaveDataInternal(IDictionary<
string
,
object
> values)
bool
ret =
true
;
using
(FluentSitefinity sf = App.WorkWith())
bool
restart =
false
;
EnsureForm();
EnsureDynamicFields(sf,
ref
restart);
if
(restart)
SystemManager.RestartApplication(
false
);
// persist data to ContactInfo dynamic type...please help!!!
return
ret;
Hi Bryan,
You can see some examples that show how to perform these operations in this post.
Greetings,
Ivan Dimitrov
the Telerik team
Hey Ivan,
protected
bool
SaveDataInternal(IDictionary<
string
,
object
> values)
bool
ret =
true
;
using
(FluentSitefinity sf = App.WorkWith())
bool
restart =
false
;
EnsureForm();
EnsureDynamicFields(sf,
ref
restart);
if
(restart)
SystemManager.RestartApplication(
false
);
// persist data to ContactInfo dynamic type
var typ = sf.DynamicData().Types().Where(t => t.Id == ContactTypeId);
// try to add a new instance to my dynamic types
return
ret;
I think I have made some progress but now I am getting errors when attempting to create a new FormEntry.
|
Telerik.Sitefinity.Descriptors.LstringPropertyDescriptor.AddDescriptor(PropertyDescriptorCollection orgColl, List`1 list, String fieldName) +118 Telerik.Sitefinity.Descriptors.LstringPropertyDescriptor.SetLocalStrings(PropertyDescriptorCollection allProperties) +147 Telerik.Sitefinity.Descriptors.DynamicFieldsTypeDescriptor..ctor(ICustomTypeDescriptor parent, Type type) +373 Telerik.Sitefinity.Model.DynamicFieldsTypeDescriptionProvider.GetTypeDescriptor(Type objectType, Object instance) +354 System.ComponentModel.DefaultTypeDescriptor.System.ComponentModel.ICustomTypeDescriptor.GetProperties() +99 System.ComponentModel.TypeDescriptor.GetPropertiesImpl(Object component, Attribute[] attributes, Boolean noCustomTypeDesc, Boolean noAttributes) +270 Telerik.Sitefinity.Model.DataExtensions.DoesFieldExist(IDynamicFieldsContainer dataItem, String fieldName) +21
private
void
EnsureForm()
using
(FormsManager mgr = FormsManager.GetManager())
mgr.Provider.SuppressSecurityChecks =
true
;
FormDescription fd = mgr.GetForms().Where(f => f.Id == ContactFormId)
.FirstOrDefault();
if
(fd ==
null
)
fd = mgr.CreateForm(CONTACT_TYPE_NAME, ContactFormId);
fd.Name = CONTACT_TYPE_NAME;
fd.Status = ContentLifecycleStatus.Live;
fd.Title =
"Flexible Contact Form"
;
fd.Description =
"Provides common data store for Exergy Dynamic Contact Forms"
;
fd.SubmitAction = SubmitAction.TextMessage;
fd.SuccessMessage =
"Thank you for contacting us. We will get back with you soon."
;
mgr.SaveChanges();
private
void
EnsureDynamicFields(FluentSitefinity fs,
ref
bool
restart)
if
(fs.DynamicData().Types().Where(t => t.Id == ContactTypeId)
.Get().FirstOrDefault() !=
null
)
return
;
bool
changeDb =
false
;
fs.DynamicData().Type().CreateNew(CONTACT_TYPE_NAME, CONTACT_TYPE_NAMESPACE, ContactTypeId)
.Do(t =>
t.DatabaseInheritance = DatabaseInheritanceType.vertical;
t.BaseClassName =
"Telerik.Sitefinity.Forms.Model.FormEntry"
;
)
.Field().TryCreateNew(
"FormName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Subject"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Prefix"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"FirstName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"LastName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Email"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Phone"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Address"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"City"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"State"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"ZipCode"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Country"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Title"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Experience"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"OrganizationName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"OrganizationType"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"OtherType"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Materials"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"MoreInfo"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetLongTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Notes"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetLongTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"EducationLevel"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Expertise"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"OtherExpertise"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"Role"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.Field().TryCreateNew(
"GeoArea"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf);
).Done()
.SaveChanges(
true
);
if
(changeDb)
restart = changeDb;
protected
bool
SaveDataInternal(IDictionary<
string
,
object
> values)
bool
ret =
true
;
using
(FluentSitefinity sf = App.WorkWith())
bool
restart =
false
;
EnsureForm();
EnsureDynamicFields(sf,
ref
restart);
if
(restart)
SystemManager.RestartApplication(
false
);
sf.Forms().Form(ContactFormId).Entry()
.CreateNew().Do(e =>
foreach
(KeyValuePair<
string
,
object
> pair
in
values)
if
(e.DoesFieldExist(pair.Key))
e.SetValue(pair.Key, pair.Value.ToString());
).SaveChanges();
return
ret;
Hello Bryan,
1.You can use the built-in forms. When you create a form this is actually a new type. Each response is the item from your type.
2. In your code you are calling SystemManager.RestartApplication(
false
);
inside SaveDataInternal
and in this case you need to get the managers again, because you are working in a different scope.
Greetings,
Ivan Dimitrov
the Telerik team
Thanks Ivan! That helped.
My data is not showing up in the Sitefinity Forms UI now. I have successfully created my dynamic type by extending FormEntry using the following:
private
void
EnsureDynamicFields()
MetadataManager manager = MetadataManager.GetManager();
MetaType dynType = manager.GetMetaTypes()
.Where(t => t.Id == ContactTypeId)
.FirstOrDefault();
if
(dynType !=
null
)
return
;
LOG.InfoFormat(
"EnsureDynamicFields: Creating dynamic type ID: 0"
, ContactTypeId);
bool
changeDb =
false
;
using
(FluentSitefinity fs = App.WorkWith())
fs.DynamicData().Type().CreateNew(CONTACT_TYPE_NAME, CONTACT_TYPE_NAMESPACE, ContactTypeId)
.Do(t =>
t.DatabaseInheritance = DatabaseInheritanceType.vertical;
t.BaseClassName =
"Telerik.Sitefinity.Forms.Model.FormEntry"
;
t.IsDynamic =
true
;
)
.Field().TryCreateNew(
"FormName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Form name"
);
).Done()
.Field().TryCreateNew(
"Subject"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Subject"
);
).Done()
.Field().TryCreateNew(
"Prefix"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Prefix"
);
).Done()
.Field().TryCreateNew(
"FirstName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"First name"
);
).Done()
.Field().TryCreateNew(
"LastName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Last name"
);
).Done()
.Field().TryCreateNew(
"Email"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"E-mail"
);
).Done()
.Field().TryCreateNew(
"Phone"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Phone"
);
).Done()
.Field().TryCreateNew(
"Address"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Address"
);
).Done()
.Field().TryCreateNew(
"City"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"City"
);
).Done()
.Field().TryCreateNew(
"State"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"State or region"
);
).Done()
.Field().TryCreateNew(
"ZipCode"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Zip or postal code"
);
).Done()
.Field().TryCreateNew(
"Country"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Country"
);
).Done()
.Field().TryCreateNew(
"JobTitle"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Title"
);
).Done()
.Field().TryCreateNew(
"Experience"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Experience"
);
).Done()
.Field().TryCreateNew(
"OrganizationName"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Organization name"
);
).Done()
.Field().TryCreateNew(
"OrganizationType"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Organization type"
);
).Done()
.Field().TryCreateNew(
"OtherType"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetShortTextField(
ref
mf,
"Other type"
);
).Done()
.Field().TryCreateNew(
"Materials"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Materials"
);
).Done()
.Field().TryCreateNew(
"MoreInfo"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetLongTextField(
ref
mf,
"Additional info"
);
).Done()
.Field().TryCreateNew(
"Notes"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetLongTextField(
ref
mf,
"Notes"
);
).Done()
.Field().TryCreateNew(
"EducationLevel"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Education Level"
);
).Done()
.Field().TryCreateNew(
"Expertise"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Area of expertise"
);
).Done()
.Field().TryCreateNew(
"OtherExpertise"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Other expertise"
);
).Done()
.Field().TryCreateNew(
"Role"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Role or position"
);
).Done()
.Field().TryCreateNew(
"GeoArea"
,
typeof
(
string
),
ref
changeDb).Do(mf =>
SetDefaultTextField(
ref
mf,
"Geographical location"
);
).Done()
.SaveChanges(
true
);
LOG.InfoFormat(
"EnsureDynamicFields: dynamic type created with ID: 0"
, ContactTypeId);
if
(changeDb)
SystemManager.RestartApplication(
false
);
private
void
EnsureForm()
using
(FormsManager mgr = FormsManager.GetManager())
mgr.Provider.SuppressSecurityChecks =
true
;
FormDescription fd = mgr.GetForms().Where(f => f.Id == ContactFormId)
.FirstOrDefault();
if
(fd ==
null
)
LOG.InfoFormat(
"EnsureForm: FormDescription ID: 0 was not found. Creating it."
, ContactFormId);
fd = mgr.CreateForm(CONTACT_TYPE_NAME, ContactFormId);
fd.Name = CONTACT_TYPE_NAME;
fd.Status = ContentLifecycleStatus.Live;
fd.Title =
"Flexible Contact Form"
;
fd.Description =
"Provides common data store for Exergy Dynamic Contact Forms"
;
fd.SubmitAction = SubmitAction.TextMessage;
fd.SuccessMessage =
"Thank you for contacting us. We will get back with you soon."
;
fd.DateCreated = DateTime.UtcNow;
mgr.SaveChanges();
LOG.InfoFormat(
"EnsureForm: Created FormDescription \"0\" with ID: 1"
, fd.Title, ContactFormId);
protected
bool
SaveDataInternal(IDictionary<
string
,
object
> values)
bool
ret =
true
;
EnsureDynamicFields();
EnsureForm();
try
App.WorkWith().Forms().Form(ContactFormId).Entry()
.CreateNew().Do(e =>
object
output = String.Empty;
if
(values.TryGetValue(
"IpAddress"
,
out
output))
e.IpAddress = output.ToString();
foreach
(KeyValuePair<
string
,
object
> pair
in
values)
if
(e.DoesFieldExist(pair.Key))
e.SetValue(pair.Key, pair.Value.ToString());
).SaveChanges();
LOG.Info(
"SaveDataInternal: new ContactInfo created"
);
catch
(Exception ex)
ret =
false
;
LOG.Error(
"SaveDataInternal: failed to create ContactInfo"
, ex);
return
ret;
Hello Bryan,
This is not how you work with the forms module.
1) Forms are much like pages in Sitefinity. They consist of controls (instead of PageControl-s, they have FormControl-s). In fact, they share a lot of functionality
2) The first thing you do is create a FormDescription
4) Create a form (manager.CreateForm), edit it (manager.EditForm), add controls (manager.CreateControl<FormDraftControl>) to the draft, and finally publish the draft.
5) The forms manager automatically builds the dynamic type from the form description (manager.BuildDynamicType)
I followd your example to the letter and the service never returned any error. It runs as expected. Your form has no controls, and that is why you can't create entries on the frondend. Once you actually create the controls via the UI, the form entries are properly displayed.
Anyway, I really see no point in going through all this hassle. Why not create your forms via the UI, create a backend page and drop a forms controls on it?
All the best,
Dido
the Telerik team
The primary reason for this is we need to show and hide controls based on user inputs. For example, if a user selects yes or no on a radio button we need to show/hide other controls. I don't see where the canned forms support conditional processing based on user input. It would be cool if there were some sort of hook that would allow us, as developers, to hook into events other than the submit button.
I will dig around and see if this functionality is possible. Otherwise, I will start working on plugging in a module to display these form submissions.
Thanks,
Bryan
Hi Bryan,
Out of the box we do not have this implementation. If we are talking for public controls and form widget you can create a custom control that inherits from FieldControl and implements IFormFieldControl . In the template of the FieldControl you can add the controls that you want to show/hide. Depending on a property you have set you can show/hide the controls from a page by using two or more div elements and setting style= display:none or using Visible=false. If you want to use two separate controls dropped on a different places of your page it will be harder, because you have to know the position of the control which will allow you to use jQuery methods to hide /show this control.
Kind regards,
Ivan Dimitrov
the Telerik team
Hi Ivan ,
Can you tell me whether it is possible to access the sitefinity forms in the code file. I have a scanerio wherein the forms will be created in the Sitefinity CMS but will be displayed dynamically as per accessed data.
Bottomline : I need to access the forms which i can add in my custom widget for the users to enter data and dynamically set the forms name as and when required.