1

Ok, so we've been converting an old project to .NET 4 and MVC 3, and it is mostly finished. I am now, however, receiving an error on a partial view when calling HtmlHelper.TextBoxFor(Expression<Func<MyModel,double?>>). HtmlHelper.TextBoxFor(Expression<Func<MyModel,string>>) works just fine, however.

Here are the relevant code snippets:

A model class:

public class MyClass
{
    public string SomeString { get; set; }

    public double? SomeNullableDouble { get; set; }
}

In the main view ViewModel:

public class MyMainViewModel
{
    public MyClass A { get; set; }

    public MyClass B { get; set; }
}

In the Partial View ViewModel:

public class MyPartialViewModel
{
    public Expression<Func<MyMainViewModel, string>> SomeStringProperty { get; set; }

    public Expression<Func<MyMainViewModel, double?>> SomeNullableDoubleProperty { get; set; }

    public MyPartialViewModel(Expression<Func<AnalyzeCostViewModel, string>> someStringProperty, Expression<Func<AnalyzeCostViewModel, double?>> someNullableDoubleProperty)
    {
        SomeStringProperty = someStringProperty;
        SomeNullableDoubleProperty = someNullableDoubleProperty;
    }
}

In the Main View (We haven't bothered converting to Razor views just yet...):

<div>
    <% Html.RenderPartial("MyPartialView", new MyPartialViewModel(m => m.A.SomeString, m => m.A.SomeNullableDouble)) %>
</div>
<div>
    <% Html.RenderPartial("MyPartialView", new MyPartialViewModel(m => m.B.SomeString, m => m.B.SomeNullableDouble)) %>
</div>

In the Partial View (MyPartialView.ascx):

<p>
    <%=Model.Helper.LabelFor(Model.SomeStringProperty, "SomeLabel:") %>
    <%=Model.Helper.TextBoxFor(Model.SomeStringProperty)%> 
    <%=Model.Helper.TextBoxFor(Model.SomeNullableDoubleProperty , new { @class = "some-class" })%>
</p>

When trying to access the main view, I'm getting a compiler error:

Server Error in '\' Application.

Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.

[InvalidOperationException: Templates can be used only with field access, property access, single-dimension array index, or single-parameter custom indexer expressions.] System.Web.Mvc.ModelMetadata.FromLambdaExpression(Expression1 expression, ViewDataDictionary1 viewData) +522 System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper1 htmlHelper, Expression1 expression, IDictionary2 htmlAttributes) +59 System.Web.Mvc.Html.InputExtensions.TextBoxFor(HtmlHelper1 htmlHelper, Expression`1 expression) +50 ASP.views_(proprietary)._Render_control1(HtmlTextWriter __w, Control parameterContainer) in d:(proprietary)MyPartialView.ascx:37 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +109 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8 System.Web.UI.Control.Render(HtmlTextWriter writer) +10 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer, ICollection children) +208 System.Web.UI.Control.RenderChildren(HtmlTextWriter writer) +8 System.Web.UI.Page.Render(HtmlTextWriter writer) +29 System.Web.Mvc.ViewPage.Render(HtmlTextWriter writer) +43 System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer, ControlAdapter adapter) +27 System.Web.UI.Control.RenderControl(HtmlTextWriter writer, ControlAdapter adapter) +100 System.Web.UI.Control.RenderControl(HtmlTextWriter writer) +25 System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint) +3060

The error occurs in the partial view for the nullable double property expression, but not the string one.

Is there an easy fix for this? Or is this something that will take some time to redesign?

Anj
  • 974
  • 2
  • 10
  • 22
  • 1
    Maybe I'm missing something here, but why are you exposing those `Expression` references in `MyPartialViewModel`? Do you really think there is a real need to do it this way? Don't you think it would be easier passing a simple, regular object reference to the partial view? – rsenna Feb 16 '11 at 20:43
  • I won't go into too much detail about why, but it is done that way for a reason (I stripped down the source code to remove all proprietary information). It worked prior to upgrading to MVC 3 (or maybe 2? I'm going straight from 1 => 3.) – Anj Feb 17 '11 at 17:06

2 Answers2

1

As from this question, it may be necessary to set up an editor template for double?...

New file - Views/Shared/EditorTemplates/NullableDouble.aspx

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<System.Double?>" %>
<%=Html.TextBox("", (Model.HasValue ? Model.Value : string.Empty), ViewData) %>

And then access this template from the view by using EditorFor:

<%=Html.EditorFor(model => model.SomeNullableDoubleProperty, new { @class = "some-class" }) %>
Community
  • 1
  • 1
James Kolpack
  • 9,331
  • 2
  • 44
  • 59
0

You have to use the Value property of your nullable type, as in:

Model.SomeNullableDoubleProperty.Value

See this answer for a detailed explanation.

Community
  • 1
  • 1
fretje
  • 8,322
  • 2
  • 49
  • 61