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.