locked
Help using SelectList RRS feed

  • Question

  • User1420621089 posted

    Hey, I'm new to MVC and was hoping I could get some help. I'm currently trying to use a Create view to add UserProfiles to preexisting Users, which are stored in a database. However, when I try to load the Create page, it gives me a ArgumentNullException for the dropdownbox. The User table in the database is definitely populated, so I know that isn't the issue.

    So my question is, why is the DropdownList coming up as null?

    Here is the View code:

    <div class="editor-field">
                @Html.DropDownList("User", new SelectList((IEnumerable<WebApp.Models.User>)ViewBag.UserID, 
                                                            "UserID", "UserName"))
            </div>

    And here is the Controller code:

    public ActionResult Create()
            {
                ViewBag.UserID = new SelectList((from u in db.Users select u), "UserId", "UserName");
                return View();
            }
    
            [HttpPost]
            public ActionResult Create(UserProfile newProfile)
            {
               
                ViewBag.UserID = new SelectList((from u in db.Users select u), "UserId", "UserName");
    
                if (ViewBag.UserID == null)
                {
                    return View();
                }
                
                if (ModelState.IsValid)
                {
                    db.UserProfiles.AddObject(newProfile);
                    db.SaveChanges();
    
                    return RedirectToAction("Index");
                }
                else
                {
                    return View(newProfile);
                }
    
            }



    And here is the stack trace:

    [InvalidCastException: Unable to cast object of type 'System.Web.Mvc.SelectList' to type 'System.Collections.Generic.IEnumerable`1[WebApp.Models.User]'.]
       CallSite.Target(Closure , CallSite , Object ) +173
       System.Dynamic.UpdateDelegates.UpdateAndExecute1(CallSite site, T0 arg0) +432
       ASP._Page_Views_Profile_Create_cshtml.Execute() in c:\Users\****\Documents\Visual Studio 2012\Projects\WebApp\WebApp\Views\Profile\Create.cshtml:19
       System.Web.WebPages.WebPageBase.ExecutePageHierarchy() +197
       System.Web.Mvc.WebViewPage.ExecutePageHierarchy() +97
       System.Web.WebPages.StartPage.RunPage() +17
       System.Web.WebPages.StartPage.ExecutePageHierarchy() +62
       System.Web.WebPages.WebPageBase.ExecutePageHierarchy(WebPageContext pageContext, TextWriter writer, WebPageRenderingBase startPage) +76
       System.Web.Mvc.RazorView.RenderView(ViewContext viewContext, TextWriter writer, Object instance) +260
       System.Web.Mvc.BuildManagerCompiledView.Render(ViewContext viewContext, TextWriter writer) +115
       System.Web.Mvc.ViewResultBase.ExecuteResult(ControllerContext context) +295
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResult(ControllerContext controllerContext, ActionResult actionResult) +13
       System.Web.Mvc.<>c__DisplayClass1a.<InvokeActionResultWithFilters>b__17() +23
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultFilter(IResultFilter filter, ResultExecutingContext preContext, Func`1 continuation) +242
       System.Web.Mvc.<>c__DisplayClass1c.<InvokeActionResultWithFilters>b__19() +21
       System.Web.Mvc.ControllerActionInvoker.InvokeActionResultWithFilters(ControllerContext controllerContext, IList`1 filters, ActionResult actionResult) +177
       System.Web.Mvc.Async.<>c__DisplayClass2a.<BeginInvokeAction>b__20() +89
       System.Web.Mvc.Async.<>c__DisplayClass25.<BeginInvokeAction>b__22(IAsyncResult asyncResult) +102
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +57
       System.Web.Mvc.Async.AsyncControllerActionInvoker.EndInvokeAction(IAsyncResult asyncResult) +43
       System.Web.Mvc.<>c__DisplayClass1d.<BeginExecuteCore>b__18(IAsyncResult asyncResult) +14
       System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
       System.Web.Mvc.Controller.EndExecuteCore(IAsyncResult asyncResult) +57
       System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
       System.Web.Mvc.Controller.EndExecute(IAsyncResult asyncResult) +47
       System.Web.Mvc.Controller.System.Web.Mvc.Async.IAsyncController.EndExecute(IAsyncResult asyncResult) +10
       System.Web.Mvc.<>c__DisplayClassb.<BeginProcessRequest>b__4(IAsyncResult asyncResult) +25
       System.Web.Mvc.Async.<>c__DisplayClass4.<MakeVoidDelegate>b__3(IAsyncResult ar) +23
       System.Web.Mvc.Async.WrappedAsyncResult`1.End() +62
       System.Web.Mvc.<>c__DisplayClasse.<EndProcessRequest>b__d() +48
       System.Web.Mvc.SecurityUtil.<GetCallInAppTrustThunk>b__0(Action f) +7
       System.Web.Mvc.SecurityUtil.ProcessInApplicationTrust(Action action) +22
       System.Web.Mvc.MvcHandler.EndProcessRequest(IAsyncResult asyncResult) +60
       System.Web.Mvc.MvcHandler.System.Web.IHttpAsyncHandler.EndProcessRequest(IAsyncResult result) +9
       System.Web.CallHandlerExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +9615056
       System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +155


    Thanks for any help you can give me.

    Thursday, August 23, 2012 3:33 PM

Answers

  • User1904378495 posted

    It's coming out as null because in the controller ViewBag.UserID is a select list , yet in the view you are casting it into an IEnumerable<WebApp.Models.User>. When a cast fails, the object gets set to null.

    You don't need to create another select list in the view, just cast it to a selectlist like so:

    <div class="editor-field">
                @Html.DropDownList("User",(SelectList)ViewBag.UserID)
    </div>

    Also I would make the following change to your controller actions:

    public ActionResult Create()
            {
                var users = from u in db.Users select u;
                ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
                return View();
            }
    
            [HttpPost]
            public ActionResult Create(UserProfile newProfile)
            {
                var users = from u in db.Users select u;
                ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
    
                if (ViewBag.UserID == null)
                {
                    return View();
                }
                
                if (ModelState.IsValid)
                {
                    db.UserProfiles.AddObject(newProfile);
                    db.SaveChanges();
    
                    return RedirectToAction("Index");
                }
                else
                {
                    return View(newProfile);
                }
    
            }




    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 23, 2012 3:40 PM

All replies

  • User1904378495 posted

    It's coming out as null because in the controller ViewBag.UserID is a select list , yet in the view you are casting it into an IEnumerable<WebApp.Models.User>. When a cast fails, the object gets set to null.

    You don't need to create another select list in the view, just cast it to a selectlist like so:

    <div class="editor-field">
                @Html.DropDownList("User",(SelectList)ViewBag.UserID)
    </div>

    Also I would make the following change to your controller actions:

    public ActionResult Create()
            {
                var users = from u in db.Users select u;
                ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
                return View();
            }
    
            [HttpPost]
            public ActionResult Create(UserProfile newProfile)
            {
                var users = from u in db.Users select u;
                ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
    
                if (ViewBag.UserID == null)
                {
                    return View();
                }
                
                if (ModelState.IsValid)
                {
                    db.UserProfiles.AddObject(newProfile);
                    db.SaveChanges();
    
                    return RedirectToAction("Index");
                }
                else
                {
                    return View(newProfile);
                }
    
            }




    • Marked as answer by Anonymous Thursday, October 7, 2021 12:00 AM
    Thursday, August 23, 2012 3:40 PM
  • User1420621089 posted

    That worked perfectly, thanks!

    Thursday, August 23, 2012 4:15 PM
  • User1420621089 posted

    Ok now it isn't working because the data isn't being passed back to the controller - the View displays fine, but when it passes the UserProfile back to the controller, UserId is set to all 0's. My best guess is that UserId is a Guid object and can't be explicitly converted and it's defaulting to empty, but I don't know how to resolve it.

    Thanks for any help.

    Friday, August 24, 2012 12:12 AM
  • User1904378495 posted

    No problem. What does the User class or table look like?

    Friday, August 24, 2012 12:19 PM
  • User1420621089 posted

    User has 5 columns: ApplicationID(FK), UserID (pk), UserName, IsAnonymous, LastActivityDate

    There are 3 users in the database at the moment, the Admin user and a couple of test users. As I said, the dropdownbox populates the three users correctly, but modelstate.isValid is false when it posts, and I'm pretty certain the reason is that there isn't a valid value for the UserId key(I checked the value right before modelState.IsValid check).

    Edit: It occurs to me that you might mean UserProfiles, which is the table I'm trying to add to. That has a lot of columns, but the ones that can't be left null are UserProfileID, which is the primary key, and UserID which is a foreign key from the User table, and the one in the dropdownbox.

    Friday, August 24, 2012 12:26 PM
  • User-474980206 posted

    views do not pass the model to controller. on a http request to the controller action, they pass route values in the url, and form data (input, select and textarea's) as name/value pairs. the binder creates an empty instance of the model, and applies the postback values. if the model value is not included in a form field, its not sent back, and will not be in the new model instance.

      

    Friday, August 24, 2012 4:09 PM
  • User1420621089 posted

    Well that explains it. How can I get the View to pass the selected value back to the controller then?

    Saturday, August 25, 2012 12:48 AM
  • User1957004874 posted

    Look at here for example.

    Saturday, August 25, 2012 12:38 PM
  • User1420621089 posted

    I got it to work, although I'm not sure how. Here is the correct code:

    public ActionResult Create()
            {
                
                var users = from u in db.Users select u;
                ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
                return View();
            }
    
            [HttpPost]
            public ActionResult Create(UserProfile newProfile)
            {
                
    
                if (ModelState.IsValid)
                {
                    db.UserProfiles.AddObject(newProfile);
                    db.SaveChanges();
    
                    return RedirectToAction("Index");
                }
                else
                {
                    
                    var users = from u in db.Users select u;
                    ViewBag.UserID = new SelectList(users.ToList(), "UserId", "UserName");
                    return View(newProfile);
                }
    
            }

    And here is the line from the View:

     <div class="editor-label">
                @Html.LabelFor(model => model.UserId)
            </div>
            <div class="editor-field">
                @Html.DropDownList("UserID", (SelectList)ViewBag.UserID, "Select User")
            </div>




    Monday, August 27, 2012 1:00 AM
  • User-1236715451 posted

    Thank you ! I'm try it

    Monday, August 27, 2012 3:09 AM