Question

My model inherits from an interface:

public interface IGrid
{
    ISearchExpression Search { get; set; }
    .
    .
}

public interface ISearchExpression 
{
    IRelationPredicateBucket Get();
}

The model:

public class Project : IGrid
{
      public ISearchExpression Search { get; set; }

      public Project()
      {
            this.Search = new ProjectSearch();
      }  
}

The ProjectSearch:

public class ProjectSearch: ISearchExpression 
{
    public string Name { get; set; }
    public string Number { get; set; }

    public IRelationPredicateBucket Get()
    {...}
}

And the strong typed partialview in the main view:

       <%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ProjectSearch>" %>

       <%= Html.TextBoxFor(x=>x.Name)%>

       <%= Html.TextBoxFor(x => x.Number)%>

       ....

When I submit the form, the Search property don't get bound properly. Everything is empty.The action takes an argument of ProjectSearch type.

Why the Search don't get bound as supposed ?

EDIT

The action

public virtual ActionResult List(Project gridModel)
{..}
Was it helpful?

Solution

You need to specify the correct prefix in order to bind sub types. For example if you want to bind to Name property of the Search property of the Model your textbox must be named: Search.Name. When you use Html.TextBoxFor(x=>x.Name) your textbox is named Name and the model binder doesn't work. One workaround is to explicitly specify the name:

<%= Html.TextBox("Search.Name") %>

or use editor templates which is a new feature in ASP.NET MVC 2.0


UPDATE:

Based on the additional details provided in the comments section here's a sample that should work:

Model:

public interface IRelationPredicateBucket
{ }

public interface ISearchExpression
{
    IRelationPredicateBucket Get();
}

public interface IGrid
{
    ISearchExpression Search { get; set; }
}

public class ProjectSearch : ISearchExpression
{
    public string Name { get; set; }
    public string Number { get; set; }

    public IRelationPredicateBucket Get()
    {
        throw new NotImplementedException();
    }
}

public class Project : IGrid
{
    public Project()
    {
        this.Search = new ProjectSearch();
    }

    public ISearchExpression Search { get; set; }
}

Controller:

public class HomeController : Controller
{
    public ActionResult Index()
    {
        return View(new Project());
    }

    [HttpPost]
    public ActionResult Index(ProjectSearch gridModel)
    {
        // gridModel.Search should be correctly bound here
        return RedirectToAction("Index");
    }
}

View - ~/Views/Home/Index.aspx:

<%@ Page Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage<Models.Project>" %>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">
    <% using (Html.BeginForm()) { %>
        <% Html.RenderPartial("~/Views/Home/SearchTemplate.ascx", Model.Search); %>
        <input type="submit" value="Create" />
    <% } %>
</asp:Content>

View - ~/Views/Home/SearchTemplate.ascx:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<Models.ProjectSearch>" %>

<%= Html.TextBoxFor(x => x.Name) %>
<%= Html.TextBoxFor(x => x.Number) %>
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top