tags:

views:

209

answers:

3

I'm working with a SelectList, and populating it with the data from a table. I'm trying to bind it to the ID of another object.

EDIT Updated the Schema to Reflect something I neglected. I have updated it to show the exact names of each item. I think the problem comes in the fact that each Unit has a sheet, and each sheet has a product. (The sheet will hold more information for the product, but a Unit will have a great deal of other information, so I wanted to separate them in order to keep it clear what was what.)

I think something is happening and the "Sheet" isn't being initialized as an object, and when the binding occurs, it doesn't have an object to bind to, since it is one-level deep. Tell me if this makes sense, or if I am just completely off base.

**Unit**
UnitID (PK)

**ProductSheet**
UnitId (FK)(PK)
ItemId (FK)

**Items**
ItemId (PK)
ItemTitle

It just ...isn't working though. I have this code.

DatabaseDataContext db = new DatabaseDataContext();
Unit unit = new Unit();
ViewData["Items"] = new SelectList( db.Items, "Id", "ItemTitle", unit.ProductSheet.ItemId);

But in the postback, the selectList is always null and empty! This is the View code. I'm really getting lost here, I've followed a lot of examples and it still comes up with bunk.

<%= Html.DropDownList("Items") %>
+3  A: 

Your view code should read:

<% var selectItems = ViewData["Items"] as SelectList; %>
<%= Html.DropDownList("ProductSheet.ItemId", selectItems) %>
David Andres
Sorry, that doesn't even compile.
Stacey
DropDownList will only accept a string as it's first parameter.
Stacey
With your edit, it compiles and runs but the result is the same. It still comes out null on the model after posting.
Stacey
Stacey: just so I'm clear, what do you mean by "comes out null on the model after posting?"
David Andres
I run it, type in the values, pick the item from the dropdown. I hit "submit". Break into the debugger. The model.Sheet.ItemId is simply null. But, if I do Request.Form["Items"], I'll get the ID of the item that was selected in the dropdown.
Stacey
Can you please post the action method the is fired when the submit button is clicked? Also, I recommend naming your DropDownList Sheet.ItemId to match the model property.
David Andres
isn't the entity in your model named ProductSheet?
mhenrixon
<%= Html.DropDownList("ProductSheet.ItemId", selectItems) %> is what you should use with that approach.
mhenrixon
Yes, I will post more. Please give me a few moments to get all of that for you.
Stacey
I've included a sample of the whole project at www.developer-network.net/downloads/DropDownListErrors.zip. I'll post the ViewCode in a separate answer below. You can use the setup controller to install/initialize the database.
Stacey
Sorry, none of these have worked, either.
Stacey
Is there any way to do this and not have the property be the name of the HTML control on the output?
Stacey
There is, but I believe you're trying to have this property automatically populate a ProductSheet parameter when posted. For this to work, the names you choose must be enough for the MVC engine to figure out where all the form elements go on a newly instantiated ProductSheet. Otherwise, you can name it what you want and add a parameter to your action method to take the data in.
David Andres
I'm not entirely sure I understand. I can just add a parameter? How will MVC know to pass that(what) through to the ActionResult?
Stacey
Stacey, MVC will try to match form input element names to the parameter names passed to an action method.
David Andres
So I have to match the ids of the form elements to the model names? Isn't this really insecure, because it exposes information about my model to the view source?
Stacey
I don't think it's any more or less secure than knowing what form posts with a submit button click and where it goes. That's HTML/HTTP for you.
David Andres
A: 

An entire sample of the project is available at this url

These are the action methods.

public ActionResult Create()
{
  DatabaseDataContext database = new DatabaseDataContext();
  Unit u = new Unit();
  u.Sheet = new Sheet();
  ViewData["ProductListing"] = new SelectList(database.Products, "ProductId", "ProductName", u.Sheet.ProductId);
    return View();
} 

//
// POST: /Home/Create

[AcceptVerbs(HttpVerbs.Post)]
public ActionResult Create(Unit u)
{
    try
  {
   DatabaseDataContext database = new DatabaseDataContext();
   database.Units.InsertOnSubmit(u);
   database.SubmitChanges();
        // TODO: Add insert logic here

        return RedirectToAction("Index");
    }
    catch
    {
        return View();
    }
}

Here is the Create View.

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

<asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server">
    Create
</asp:Content>

<asp:Content ID="Content2" ContentPlaceHolderID="MainContent" runat="server">

    <h2>Create</h2>

    <%= Html.ValidationSummary("Create was unsuccessful. Please correct the errors and try again.") %>

    <% using (Html.BeginForm()) {%>

        <fieldset>
            <legend>Fields</legend>
            <%= Html.DropDownList("ProductListing") %>
            <p>
                <input type="submit" value="Create" />
            </p>
        </fieldset>

    <% } %>

    <div>
        <%=Html.ActionLink("Back to List", "Index") %>
    </div>

</asp:Content>

<asp:Content ID="Content3" ContentPlaceHolderID="ScriptContent" runat="server">
</asp:Content>
Stacey
A: 

I've marked the answer that seems to have made some progress now, I think I'm starting to understand it better.

When I passed the 'path' of the object to assign as a string in the name field of DropDownList, it seems to work. But this doesn't really make a lot of sense to me. Can you explain what is going on any better?

Stacey
By path, do you mean ProductSheet.ItemId? I think it helps to understand what happens when you post a form item whose name is ProductSheet.ItemId. Let's say you have an action method that takes a productsheet parameter. MVC will automatically equate the ProductSheet.ItemId form field with the productSheet action method parameter, and which this form data will try to fill the parameter's ItemId property (if it exists). This will work even if ProductSheet is a property of the paraemter itself, as in myParam.ProductSheet.ItemId. It's confusing, I know.
David Andres
I think the biggest problem is that field name and object name are sharing the same parameter, and it's a simple string. It isn't very clear to the programmer that that parameter needs to match the property you want to associate with in your model, and that you can reference the object itself (i.e. "Sheet.ProductId" instead of just being limited to "Sheet" or "ProductId").
Stacey
Is there any way to do this and control the id field of the html output?
Stacey