NullReferenceException on WFFM Submit - web-forms-for-marketers

I'm trying to get Webforms for Marketers to work in a Sitecore Mvc website.
The form renders normally, but upon submitting the form a NRE occurs.
[NullReferenceException: Object reference not set to an instance of an object.]
Sitecore.Forms.Mvc.Controllers.ModelBinders.FormModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +536
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +436
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +152
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +641
The error occurs with both newly created forms and with unmodified Sample Forms. I've tested using the default "Tell a Friend" and the "Send an Email" Actions. I've encountered no problems using these forms and actions outside the Mvc environment (Regular and Mvc Multi-site). I'm using Sitecore 7.5 and WFFM 2.5.
I've found Save Action on webforms for marketers throws exception as a duplicate. Important emphasis, the DataSource requires not the path shown at Form ID, but the actual Form ID you can view through Raw Values.

This exeptions means that some object is set to null and youre asignig value to its member.
if im right youre asigning viewmodel data to some domain model, and the reason you get exepton is youre domain model is null, firts you must create instance of that model and than give it some value
DomainModel yourModel = new DomainModel();
//and than you must give to yourModel objects properties some values
P.S Debugging is your best friend in such situations

Related

Django - Create new object in Form, update select box and save it

I think what I'm trying to achieve is not hard, but I have no clue how to do it hehehehe !
Basically what I need is the feature that we have in Django Admin, when you are creating a new object, if you have a Foreign Key, you can add new data (opening a pop-up), save it and then the select box updates automatically.
What I have is this form:
I know that would be easy to do it with some Javascript, but my point is, Django has some rules, and as far I know, I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
PS: "Local" is the select box where I want to add new data. The user should be able to create a new Local on this page, instead of going to another page to do it. Thanks :)
Here your question:
I can't add new data to a form already created, right? Otherwise Django won't validate this form. How could I achieve this?
Then the answer:
you are right, django will check values match form value rules. But:
realize that your main form is invoked for twice: on GET and on POST. Between both form executions you make changes on database values trhough your new form. That means that in second main form invocation the value added to database is available:
field1 = forms.ModelChoiceField(queryset= ***1*** )
***1***: on second invocation new value is already available on field1.
Then, you don't should to be afraid about this subject, the new value will be available on form on your main form POST request.
Nothing wrong with updating the value using javascript as long the key in your new combo box has the right key in the database then it should be ok.
Call this function after you saved the last entry.
function refreshLocal(){
$.get(window.location.href, '', function(html){
// change the id to the local combox's id
var serverLocalDropBox = $(html).find('#id_local');
if (serverLocalDropBox.length){
$('#id_local').replaceWith(serverLocalDropBox);
}
})
}
If you don't want to use javascript solution, you can post the form with refresh flag and on the server side if you see that flag just don't validate and return the form as is. Since you have a new entry in the foreignkey it will automatically update the queryset to include the new entry.
function serverRefreshLocal(){
var $form = $('#your_form_id');
$form.append('<input type="hidden" name="refresh" value="true" />');
// you can use ajax submit and ajax refresh here if you don't want to leave the page
$form.submit();
}
// Server Side
def your_form_post_view(request):
if request.POST.get('refresh', 'false') == 'true':
# initial is the trick to save user input
your_form = YourForm(initial=request.POST)
context = {
'form': your_form,
}
return render(request, 'your_template.html', context)
# your view code goes here

adding models to backbone collections

I have a rails app with 4 Model classes, with multiple instances in each table. I have created backbone Model and Collection classes in CoffeeScript to match. I can successfully load all of the collections and can render them in views. So far, so good. Here is one of my collections, with its associated model:
class window.CoffeeWater.Collections.Histories extends Backbone.Collection
url: '/api/histories'
model: History
class window.CoffeeWater.Models.History extends Backbone.Model
I need to be able to create a History model object, and then add it to the Histories collection. The documentation states that I have to set a 'collection' property when creating my new model, in order for it to get the 'url' property from the collection. My problem is that I can't seem to set the 'collection' property value correctly, because the url property does not get set on the model instance
attributes = {'start_time': new Date (1434740259016), 'stop_time': new Date (1434740259016 +(86400*1000)), 'valve_id': 2}
options = { collection: window.CoffeeWater.Collections.Histories }
history = new window.CoffeeWater.Models.History(attributes, options)
window.CoffeeWater.Objects.Collections.Histories.add(history)
Inspecting the resulting 'history' object does not show the same attributes that exist in models already in the collection, and the url property is missing.
I am currently at a loss. Does anyone have an example on how to do this? The backbone.js docs do not show any relevant examples.
The way the url in model is defined like this.
If there is a url property in model.
class window.CoffeeWater.Models.History extends Backbone.Model
url:'/api/history/1'
Then when model.fetch(), it will call that url. If this property is not found, it will see if the associated collection does have a 'url'. You try to set this collection variable.
What you are missing is this. This
class window.CoffeeWater.Collections.Histories extends Backbone.Collection
is actually a definition of a class. It is not an object yet. You need to initialize it, like you do in java. so
var historyCollection=new window.CoffeeWater.Collections.Histories()
Now you have a collection object. When you do
historyCollection.add(history);
The "collection" of model is automatically set to the "historyCollection" object, which contains a 'url'. So in fact, you do not need to manually put this in the option.
basically
attributes = {'start_time': new Date (1434740259016), 'stop_time': new Date (1434740259016 +(86400*1000)), 'valve_id': 2}
var historyCollection=new window.CoffeeWater.Collections.Histories()
var history = new window.CoffeeWater.Models.History(attributes)
historyCollection.add(history)

How to disable Sitecore WFFM custom fields caching

I have a custom field SomeCustomFieldType in Sitecore WFFM that shows on the left side of the Form Editor a property which is a dropdown with a list of choices.
[VisualProperty("Choose value", 99),
VisualCategory("Custom Properties"),
VisualFieldType(typeof(CountryBasedListChoiceField))]
public string ChosenValue { get; set; }
Instead of using the out-of-the-box ListChoiceField, I wrote my own CountryBasedListChoiceField, which, based on some condition, figures out which choice items need to be displayed in the property dropdown:
public CountryBasedListChoiceField()
: base(((object) HtmlTextWriterTag.Select).ToString())
{
string formID = Sitecore.Context.Request.GetQueryString("formid");
Language formLanguage = Language.Parse(Sitecore.Context.Request.GetQueryString("la"));
Item formItem = Sitecore.Context.ContentDatabase.GetItem(formID, formLanguage);
string countryName = SitecoreUtility.GetCurrentCountryISOCode(formItem, formLanguage);
string choicesRootPath = CountryConfigurationManager.GetCountrySite(countryName).Metadata.FormsStylesheetsItemPath;
Item choicesRootItem = Sitecore.Context.ContentDatabase.GetItem(choicesRootPath, formLanguage);
ChoicesRoot = choicesRootItem.ID.ToString();
}
It really doesn't matter how the above code works, since it works just fine.
The problem I am having is that the code above is executed only once, the very first time that the user opens a form in the form editor and clicks on a field that is of type SomeCustomFieldType.
After that, the list of choices to be displayed must be cached because this code is never being hit anymore. Even closing the browser and reopening it is not enough to clear that cache -- iisreset obviously clears that cache.
I would like to know if there is a way to stop this caching from happening.
Thanks in advance!
Firstly, you should check to ensure that it the rendering is not cached found here: '/sitecore/layout/Renderings/Modules/Web Forms for Marketers/Form' (the version of WFFM I have open right now it is NOT the default). Also check to ensure that any renderings it is contained within are also not cached.
Looking at the forms code, the form item and field containers are constructed every time. I also checked the .ascx that is called and it has no default output cache. You can start by looking deeper in Sitecore.Forms.Core.dll at the class 'Sitecore.Form.Web.UI.Controls.SitecoreSimpleFormAscx', but I would try the simple first.

How to get user info into a web forms for marketers form automatically

I try to get the login information present in the header of my Sitecore intranet automatically within a web form (from marketer) so that the logged person has not the reenter that user information already present on page.
Someone any feedback or experience therewith?
You can use rules for this. Look at each field property and one of these at the bottom are rules you can assign to the field.
One of the rules is populating the default value from the user profile field.
Hopefully this is what you are after.
I think you should create a custom field type.
Here is the documentation on page 55: web forms for marketers.
Here is the sample code snippet to get user e-mail:
public class UserDataEmailField : BaseControl
{
/// <summary>
/// Gets the result.
/// </summary>
public override ControlResult Result
{
get
{
var item = Sitecore.Context.Database.GetItem(this.FieldID);
return new ControlResult(item.Name, Sitecore.Context.User.Profile.Email, string.Empty);
}
}
}
You should overwrite also the Render method.
I hope I helped.

Web Forms for Marketers - Submit form data programmatically

I'm currently scoping whether or not to include Web Forms for Marketers on a project I'm currently working on. The web site will be a responsive design with a rich UI and so I would like to have full control over the rendering of the form, e.g. labels, input fields etc and would rather not have to modify the WFFM SitecoreSimpleFormAscx.ascx file or the associated css file.
Is there currently any way, using C# code, to submit some form data to a Web Forms for Marketers form that is already created in Sitecore (assuming I have knowledge of all the fields)? The WFFM reference guide has a code snippet for accessing already submitted web form data but nothing for just submitting some.
If you don't want to dig into custom controls for the forms you might try performing a POST to a page that contains the WFFM form via JavaScript from your responsive page. Alternatively you could embed and hide the wffm form on your page and stunt drive it with script again. I think the second approach would be better as it would allow you to more directly respond to validation failures.
You could submit form code to the WFFM DB using the following code, and it would show up seamlessly in the report page of that form:
Say you have your list of fields populated in a list of this class:
public class WffmField
{
public string FieldName { get; set; }
public string FieldGuid { get; set; }
public string FieldValue { get; set; }
}
the field guid would be the guid from sitecore:
You can then save to the WFFM database:
// This should be populated with the data you want to send to the WFFM database
var fields = new List<WffmField>();
var wffmDatabaseFields = fields.Select(GetWFFMDatabaseField).ToList();
Sitecore.Forms.Data.DataManager.InsertForm(
formId: new Sitecore.Data.ID("<Form guid here>"),
fields: new AdaptedResultList(wffmDatabaseFields),
sessionID: AnalyticsTracker.SessionId,
data: null);
Hope this helps!