Why does a ViewBag Object Name need to be the same name as the Drop Down it is being bound to?

334 Views Asked by At

I've got a Razor cshtml setup where I am sending a SelectList through the ViewBag. My issue is the naming of the ViewBag object, I would like to send it like this (see below) but doesn't seem to be working for me.

Controller:

ViewBag.EmailAddresses = new[]
    {
        new SelectListItem { Text = "Select an Email Address", Value = "" }
    }
    .Concat(
        new SelectList( db.EmailAddresses, "Oid", "Name", null )
    );

Razor view:

@Html.DropDownList(
    "FromRecipientID", 
    ViewBag.EmailAddresses as SelectList, 
    null,
    htmlAttributes: new { @class = "form-control" }
)

However, it only works when I have it setup like this:

Controller (works):

ViewBag.FromRecipientID = new[]
    {
        new SelectListItem { Text = "Select an Email Address", Value = "" } 
    }
    .Concat(
        new SelectList( db.EmailAddresses, "Oid", "Name", null )
    );

Razor view (works):

@Html.DropDownList(
    "FromRecipientID", 
    //Binding SelectList isn't required, assumption of ViewBag Name and Property
    null, 
    htmlAttributes: new { @class = "form-control" }
)

Is there an alternative? I'm not sure what I am missing.

Edit #1:

I've been able to update my ViewModel, on Edit, populate IEnumerable<SelectListItem> EmailAddresses along with the EmailAddressID:

public ActionResult Edit(Guid? id)
{
    //...
    //Omitted information   

    //List of EmailMessages
    formView.EmailMessages = form.EmailMessages
        .Select(f =>
        {
            //Populate IEnumerable<SelectListItem>
            f.EmailAddresses = new SelectList(db.EmailAddresses, "Oid", "Name", f.FromRecipientID);
            return f;
        })
    ;

    //More omitted information
    //...

}

IEnumerable contained the following:

My Email    > id = 1
Your Email  > id = 2 (this should be the selected item)

//Note that the DropDownListFor examples below added "Select an Email Address" to the top of the list

The below Razor cshtml code was an attempt to show what I have tried and the result, I only had one DropDownListFor active at a time (I noticed that the first instance was the only one that "could" work properly).

In my PartialView, I have the FromRecipientID (Guid) or FromRecipient (EmailAddress object):

<div class="form-group">
    @Html.LabelFor(model => model.FromRecipientID, "FromRecipientID", htmlAttributes: new { @class = "control-label col-md-2" })
    <div class="col-md-10">

        @* Works, selected ID 2 (because of Model.EmailAddesses) *@
        @* On Save error though, noted below *@
        @Html.DropDownListFor(
            model => model.FromRecipient, 
            Model.EmailAddresses, 
            "Select an Email Address", 
            htmlAttributes: new { @class = "form-control" })

        @* Failed, no ViewBag.FromRecipient (makes sense) *@
        @Html.DropDownListFor(
            model => model.FromRecipient, 
            null, 
            "Select an Email Address", 
            htmlAttributes: new { @class = "form-control" })

        @* Does not work, selected "Select an Email Address" *@
        @Html.DropDownListFor(
            model => model.FromRecipientID, 
            Model.EmailAddresses, 
            "Select an Email Address", 
            htmlAttributes: new { @class = "form-control" })

        @* Works, selected ID 2 (but because of ViewBag.FromRecipientID) *@
        @Html.DropDownListFor(
            model => model.FromRecipientID, 
            null, 
            "Select an Email Address", 
            htmlAttributes: new { @class = "form-control" })

        @Html.ValidationMessageFor(model => model.FromRecipientID, "", new { @class = "text-danger" })
    </div>
</div>

For the first example, the one that populated properly (... model => model.FromRecipient, Model.EmailAddresses, "Select an Email Address" ...) didn't work on Save, I receive the following error:

System.InvalidOperationException: 
'There is no ViewData item of type 'IEnumerable<SelectListItem>' that has the key 'FromRecipient'.'

This seems to be coming from the ModelState being invalid, I get the following:

{"The parameter conversion from type 'System.String' to type 'ContentPub.Models.Mail.EmailAddress' failed because no type converter can convert between these types."}

I get it, I have a value of "2" but the DropDownListFor is trying to set model => model.FromRecipient.

Am I over-thinking this?

Edit #2

Wow, hate to report this as it was a simple fix/issue, but I need to...

I removed the old ViewBag setup that I had:

//ViewBag.FromRecipientID = new[] { new SelectListItem { Text = "Select an Email Address", Value = "" } }
//    .Concat(new SelectList(db.EmailAddresses, "Oid", "Name", null));

As I see it now, this was getting in the way of my testing.

This is the DropDownListFor that is working properly:

 @Html.DropDownListFor(
    model => model.FromRecipientID, 

    //When the ViewBag.FromRecipientID was active, Model.EmailAddesses wasn't being used
    // and was causing some type of conflict
    Model.EmailAddresses, 

    "Select an Email Address", 
    htmlAttributes: new { @class = "form-control" })

I will do more testing (and answer my own question when confirmed), but I think this is what I needed all along.

0

There are 0 best solutions below