sf.
sf.

Reputation: 25470

asp.net mvc and model binding objects with sub objects

I'm trying to get model bind a sub class in a form.

I have a Page class with a related PageContent class. There are many PageContent objects in a Page object. ie Page.PageContents

I return Page as the Model and I can see all the PageContent items.

However I'm a bit blurry on how to assign the PageContent items to the form so it'll keep it's model binding.

When I Post the Page model back into the controller, the PageContent list is empty.

Here is a snippet of the form:

<% using (Html.BeginForm("SavePage", "Admin")) {%>

    <fieldset>
        <legend>Fields</legend>
        <%=Html.Hidden("PageId", Model.PageId) %>
        <p>
            <label for="Title">Title:</label>
            <%= Html.TextBox("Title", Model.Title) %>
            <%= Html.ValidationMessage("Title", "*") %>
        </p>
        <p>
            <label for="SysName">SysName:</label>
            <%= Html.TextBox("SysName", Model.SysName) %>
            <%= Html.ValidationMessage("SysName", "*") %>
        </p>

        <% 
            int i = 0;
       foreach (var pageContent in Model.PageContents)

           { %>
            <div>
                <%=Html.Hidden("PageContents[" + i + "].PageContentId", pageContent.PageContentId) %>
                <%=Html.TextArea("PageContents[" + i + "].Content", pageContent.Content)%>                
            </div>
        <%
            i++;
       } %>

        <p>
            <input type="submit" value="Save" />
        </p>
    </fieldset>

<% } %>

I'm thinking I haven't made the PageContents aspect of the form correctly.

EDIT: Here is the basic controller method I POST to:

public ActionResult SavePage(Page page)
    {
        // do stuff with page.PageContents
        return View("PageEdit", page);
    }

I'm not using the Request.Form style

Please help :D

Upvotes: 0

Views: 1119

Answers (1)

BMBM
BMBM

Reputation: 16013

You said Page.PageContents is an EntitySet<PageContent> and that you are using auto-generated classes. So, I guess, you are using LINQ to SQL? If so, then you can use partial classes in order to add properties to the generated class

I remember that I had a similiar problem, I wasnt able to bind to EntitySet<T> properties. I think I fixed it by using a proxy / placeholder property which was an IList<T> what effectively set the actual property. So, in your case, that would look something like this:

// Your partial class, adding a property to the generated class
public partial class Page
{
    // Bind to this property
    public IList<PageContent> MyPageContents
    {
        set 
        { 
            var set = new EntitySet<PageContent>();
            set.AddRange(value);
            PageContents = set; 
        }
        get  { return PageContents; }
    }
}

// This and probably a lot more is created by LINQ to SQL
public partial class Page {
    // ...

    public EntitySet<PageContent> PageContents
    {
        get;
        set;
    }

    // ...
}

I think partial classes have to be in the same namespace as the auto generated class. More info here: Adding new methods to LINQ to SQL generated classes

And then, in your form, you bind to MyPageContents (you can use a better name of course) instead of PageContents.

Hopefully it works for you, it is quite some time ago since I last used LINQ to SQL.

Upvotes: 1

Related Questions