Save Action on webforms for marketers throws exception - submit

I am using the latest version of Sitecore - 7.2 (rev. 140228) and the latest version of WFFM - 2.4 rev. 140923. So the problem is whenever I try to submit a form no matter what kind of save action I have, Sitecore throws exception:
Object reference not set to an instance of an object.
Description: An unhandled exception occurred.
Exception Details: System.NullReferenceException: Object reference not set to an instance of an object.
Stack Trace:
[NullReferenceException: Object reference not set to an instance of an object.]
Sitecore.Forms.Mvc.Controllers.ModelBinders.FormModelBinder.BindModel(ControllerContext controllerContext, ModelBindingContext bindingContext) +571
System.Web.Mvc.ControllerActionInvoker.GetParameterValue(ControllerContext controllerContext, ParameterDescriptor parameterDescriptor) +457
System.Web.Mvc.ControllerActionInvoker.GetParameterValues(ControllerContext controllerContext, ActionDescriptor actionDescriptor) +152
System.Web.Mvc.ControllerActionInvoker.InvokeAction(ControllerContext controllerContext, String actionName) +641
Some additional information. The latest version of WFFM supports MVC so in this scenario I use cshtml layout. This is the blog post where is described how to use MVC - THIS Despite it is for previous versions of SC it doesn't matter and the solution is applicable for the latest version.

Think I have a solution for this.
I reverse engineered and debugged using a version of the controller and model binder I created after reflecting on the Sitecore.Forms.MVC classes using ILSpy.
Apparently the null reference is occuring when it hits this:
if (controllerContext.HttpContext.Request.RequestType == "POST" && formId != item.ID)
item is null. item is set in the line before:
Sitecore.Data.Items.Item item = RenderingContext.CurrentOrNull.PageContext.Database.GetItem(RenderingContext.CurrentOrNull.Rendering.DataSource);
The data source property is empty on the rendering. If you check your presentation details, you'll see that's because there is another field that is used to specify your form ID. Apparently this looks like a Sitecore bug. But an easy workaround is to set the form data source in both the form ID and the Data source property of the rendering.

Related

NullReferenceException in custom IModelBinder

I'm trying to implement my own custom ModelBinder using MVC4 in .NET 4.5, but get the weirdest error. My code looks approx. like this
TableViewModelModel : IModelBinder
public object BindModel(ControllerContext ctx, BindingContext btx)
{
IEnumerable<String> sSearch = ctx.HttpContext.Request.Params.Keys.OfType<String().Where(key => key.StartsWith("sSearch_"));
...
}
A NullReferenceException is thrown allready at the first line, but none of the properties are actually null (they all appear in the intellisense debug). In a desperate I decided to rid of some of the properties to get a better look at where the exception is thrown and I found the culprit to be the Params property. What's really strange is that all the keys from the querystring is listed in the debug window, but an exception is thrown nevertheless. I really need some help on this one people!
Thanks.
Found the error using Reflector and analyzing the stack trace. Turns out that somewhere along the call stack HttpRequest.Params tried to read the Identity property of my Principal object (HttpContext.User). I have a custom implementation of IPrincipal that doesn't initialize the Identity object - and there you have it.
A big thank you to those of you who took the time to read my question.

ModelBindingContext ModelName

Can anyone explain where the ModelName gets populated from?
Looked in MSDN documentation and no explaination here.
I am creating a custom model binder and within it I get null for the following:
var result = bindingContext.ModelName);
The ModelBindingContext object is created and populated by whoever calls into the BindModel() method. If the model is coming in as an argument to your action method, this is done by ControllerActionInvoker.GetParameterValue(), and the ModelName property will be set to the name of the parameter (unless overridden by [Bind(Prefix = ... )]).
If the model is being updated via UpdateModel(), the ModelBindingContext object is created by the UpdateModel() method itself. The ModelName parameter will be the prefix argument passed to UpdateModel().

ASp.net MVC 2 changed how tryupdatemodel works, what is the easiest way to fix my code?

I initialize my strings to blank, not null. Which worked fine in MVC 1, using tryupdatemodel in that any text entries that had no text in them would be set to a blank string, in MVC 2 RC2 apparently (at least from my testing) it sets them to null / nothing. So now I'm getting errors from my validation layer which requires those to be blanks not null. Another problem with it that I have found is that now via reflection it calls every property on my objects including the ones I've not specified in a bind include statement and even readonly properties that could not be set.
Any one have an idea of the easiest way to get around these problems without totally changing all my code? Or should I just suck it up and
About properties that you haven't bound - asp.net mvc 2 rc has this change from input validation to model validation, here is how it works now
I suppose the issue you have with string is also because of changes made in RC2, check out the release notes.
To fix the string defaulting to null instead of "" I had to do this first:
Public Class NullToEmptyStringModelBinder
Inherits DefaultModelBinder
Protected Overrides Sub SetProperty(ByVal controllerContext As System.Web.Mvc.ControllerContext, ByVal bindingContext As System.Web.Mvc.ModelBindingContext, ByVal propertyDescriptor As System.ComponentModel.PropertyDescriptor, ByVal value As Object)
If value Is Nothing AndAlso propertyDescriptor.PropertyType Is GetType(String) Then
value = ""
End If
MyBase.SetProperty(controllerContext, bindingContext, propertyDescriptor, value)
End Sub
End Class
And then add to the application start this:
ModelBinders.Binders.DefaultBinder = New NullToEmptyStringModelBinder

ASP.NET MVC 2 Preview 2 under Mono in Linux

I am actually successfully running a production website with ASP.NET MVC under Mono in a Ubuntu LTS Linux. This server is located somewhere in the cloud and it rocks!
Today, I have tried to make it all work with ASP.NET MVC 2 Preview 2, which can be found here: ASP.NET MVC 2 Preview 2
I have downloaded the source code because I wanted to deploy the DLL by hand just like I am doing with v1. I find it simpler Linux not to rely on the GAC.
Everything seems to be working fine until I try to get JSON data in an AJAX call. Here is the information I get about the error...
[System.NotImplementedException]: The
requested feature is not implemented.
at
System.Web.Mvc.AssociatedMetadataProvider.GetTypeDescriptor
(System.Type type) [0x00000] at
System.Web.Mvc.AssociatedMetadataProvider.GetMetadataForType
(System.Func`1 modelAccessor,
System.Type modelType) [0x00000] at
System.Web.Mvc.ControllerActionInvoker.GetParameterValue
(System.Web.Mvc.ControllerContext
controllerContext,
System.Web.Mvc.ParameterDescriptor
parameterDescriptor) [0x00000] at
System.Web.Mvc.ControllerActionInvoker.GetParameterValues
(System.Web.Mvc.ControllerContext
controllerContext,
System.Web.Mvc.ActionDescriptor
actionDescriptor) [0x00000] at
System.Web.Mvc.ControllerActionInvoker.InvokeAction
(System.Web.Mvc.ControllerContext
controllerContext, System.String
actionName) [0x00000]
The feature your trying to use is not implemented. The fix would be to actually implement the feature your looking for.
Wait...
Are you using return type of JsonResult instead of ActionResult for your controller actions? Something is trying to populate the meta data about the model your passing to the view. I think if your returning JSON that piece of functionality, the metadata population, shouldn't happen.

Doing custom binding for a specific data-type in a ModelBinder

I'm in the process of creating my own custom ModelBinder that inherits from DefaultModelBinder, and manually binds XElement-typed properties.
Now it seems that I have to override the 'BindProperty' method, like so:
protected override void BindProperty(
ControllerContext controllerContext,
ModelBindingContext bindingContext,
System.ComponentModel.PropertyDescriptor propertyDescriptor)
{
if (propertyDescriptor.PropertyType == typeof(XElement))
{
// code here to take the POST-ed form value and put it in the property as an XElement instance
}
else
base.BindProperty(controllerContext, bindingContext, propertyDescriptor);
}
What code should I be using to:
A) get the value of the property from the posted Form values?
B) inject this value into the property?
I tried running Reflector on the DefaultModelBinder class to see how it does it, but the code was very confusing.
I need someone who's done this before to walk me through it.
The bindingContext parameter contains a ValueProvider property that is already populated with the values from the request. The idea is that you pull the values from that.
It is simply a dictionary of values, so you can index into it using the name of the field you would like to bind.
The easiest way to understand what's goint on is to apply your custom ModelBinder and then set a breakpoint in your code and inspect what data you got while in the debugger.

Resources