Advertisement
If you have a new account but are having problems posting or verifying your account, please email us on hello@boards.ie for help. Thanks :)
Hello all! Please ensure that you are posting a new thread or question in the appropriate forum. The Feedback forum is overwhelmed with questions that are having to be moved elsewhere. If you need help to verify your account contact hello@boards.ie

MVC DropdownList not working...

Options
  • 26-06-2014 12:03pm
    #1
    Closed Accounts Posts: 1,143 ✭✭✭


    Hi folks, lol me again! Thanks to all in the forum for helping me get acquainted with MVC via the few threads on here lately, I can't be grateful enough for the folks who have helped me get over the small hurdles that we all run into when not coming at software development from a position of experience...

    My latest issue is that I'm starting to work with what would have been "Drop & Drag" toolkit controls under the Webforms regime. Using something like a DropdownList as a Control Parameter for another control such as a FormView, was really simple, you just drop it on the page and wire it up to an SqlDatasource.

    When I try to put some DropdownList functionality on my MVC view to try to fiddle around with how I can use it, I Googled a simple MVC DropdownList solution and I found these, the objective here was just to see a simple DropdownList on my page with something like
    <Option A>
    <Option B>
    <Option C>
    ...

    I've put this code into my View, when I view the page source, it is there, so it is being rendered in the page, the only issue is that I can't "see" it!

    [HTML]

    @if(ViewBag.Show == true)
    {
    <fieldset name="MyFieldset">
    ..............
    </fieldset>

    List<SelectListItem> listItems= new List<SelectListItem>();
    listItems.Add(new SelectListItem
    {
    Text = "Exemplo1",
    Value = "Exemplo1"
    });
    listItems.Add(new SelectListItem
    {
    Text = "Exemplo2",
    Value = "Exemplo2",
    Selected = true
    });
    listItems.Add(new SelectListItem
    {
    Text = "Exemplo3",
    Value = "Exemplo3"
    });


    @Html.DropDownListFor(model => model.ClientID, listItems, "-- Select Status --")


    }
    [/HTML]


    Btw, I know I have a conditional statement above, using the "@if(ViewBag.Show == true)" statement, but this condition is true as my Fieldview is displaying all the data I need, so this DropdownList code being within the same statement/scope, I would have thought it would display on the page?


Comments

  • Registered Users Posts: 586 ✭✭✭Aswerty


    I haven't worked with this HtmlHelper for a long while but I think the value of your expression (model => model.ClientID) has to resolve to the same value as the Value property in a SelectListItem. So if ClientID = 3 in this case then you'd want a SelectListItem with a Value = "3".


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    I haven't worked with this HtmlHelper for a long while but I think the value of your expression (model => model.ClientID) has to resolve to the same value as the Value property in a SelectListItem. So if ClientID = 3 in this case then you'd want a SelectListItem with a Value = "3".

    Ahhhh, I'll try that!


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    I haven't worked with this HtmlHelper for a long while but I think the value of your expression (model => model.ClientID) has to resolve to the same value as the Value property in a SelectListItem. So if ClientID = 3 in this case then you'd want a SelectListItem with a Value = "3".

    Should this DDL not display the list items though as it stands?!? It is inserting the selected item into my DB, I just can't see the control when my page renders?!?


  • Registered Users Posts: 586 ✭✭✭Aswerty


    Without seeing your code I'm just guessing here but the act of inserting something in a DB and rendering something within the browser are probably not related. I think you're just using the HtmlHelper wrong. I expect you're not getting any errors because the debugger doesn't seem to be as good a dealing with problems within a View as it is in classes.

    There is also a method called HtmlHelper.DropDownList(). This is not strictly tied to the Model of the View as the method you are using.

    Alternatively You can just write the HTML and not bother with the helper method but I think they allow for clean looking Views.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    My prob now is that I have a Fieldset in my View, so in my controller I've used:

    return View(StockVehicleDB);


    to display that data...

    But now I have this code in my Controller:

    [HTML]
    var dropdownItems = new List<DropdownItem>();

    dropdownItems.Add(new DropdownItem { ItemID = 1, ItemName = "Item 1" });
    dropdownItems.Add(new DropdownItem { ItemID = 2, ItemName = "Item 2" });
    dropdownItems.Add(new DropdownItem { ItemID = 3, ItemName = "Item 3" });

    ViewBag.Show = true;

    //return View(new DropdownModel { DropdownItems = dropdownItems });
    [/HTML]

    The commented out bit is return View for this DropDownList, but how do I return a view for both my Fieldset AND my DropdownList?!?

    This is where MVC is hard to get your head around!


  • Advertisement
  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    This is where MVC is really confusing me... I've just dropped the following code into my View:

    [HTML]
    <select name="year"> <option>2010</option> <option>2011</option> <option>2012</option> <option>2013</option> <option>2014</option> <option>2015</option> </select>
    [/HTML]

    Just to see if I can make the simplest sort of DropdownList appear on my page! I can't see it on the page, but when I go into my PageSource, lo and behold, there it is?!?

    [HTML]
    </fieldset> <select name="year"> <option>2010</option> <option>2011</option> <option>2012</option> <option>2013</option> <option>2014</option> <option>2015</option> </select>
    [/HTML]


  • Registered Users Posts: 586 ✭✭✭Aswerty


    With regards to your first post:

    So say you have your View which you want to return to the user. In this view you might want to conditionally render partial views. Or you might want to push a bunch of related HTML/Code into a partial view so things are cleaner. There are 2 approaches to doing this, either rendering a partial view directly or calling an action method and rendering the partial view it returns. The latter method is generally used if the partial view has a Model in it.

    So this view might look like:
    <div>
    @Html.Partial("FieldsetPartialView") <!-- Where the name of this view is FieldSetPartialView and it is in the same directory as the view rendering it (note you can pass a Model using this method but the model can only be passed to it if it exists in this view-->
    @{Html.RenderAction("CreateDropDown", "Product");} <!-- Here we call an action method call CreateDropDown in the ProductController and we then render the returned partial view, this action method can create a Model/hit the DB/anything else a normal action method does -->
    </div>
    

    With regards your last post:

    This sounds like a CSS issue (or your HTML has unclosed brackets), remember all styling in MVC is done via CSS. All modern browsers should allow you modify the CSS of an open page (via developer tools). You should look at seeing if you can modify the CSS so the dropdown is visible within the browser on a live page.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    With regards to your first post:

    So say you have your View which you want to return to the user. In this view you might want to conditionally render partial views. Or you might want to push a bunch of related HTML/Code into a partial view so things are cleaner. There are 2 approaches to doing this, either rendering a partial view directly or calling an action method and rendering the partial view it returns. The latter method is generally used if the partial view has a Model in it.

    So this view might look like:
    <div>
    @Html.Partial("FieldsetPartialView") <!-- Where the name of this view is FieldSetPartialView and it is in the same directory as the view rendering it (note you can pass a Model using this method but the model can only be passed to it if it exists in this view-->
    @{Html.RenderAction("CreateDropDown", "Product");} <!-- Here we call an action method call CreateDropDown in the ProductController and we then render the returned partial view, this action method can create a Model/hit the DB/anything else a normal action method does -->
    </div>
    
    With regards your last post:

    This sounds like a CSS issue (or your HTML has unclosed brackets), remember all styling in MVC is done via CSS. All modern browsers should allow you modify the CSS of an open page (via developer tools). You should look at seeing if you can modify the CSS so the dropdown is visible within the browser on a live page.

    Thanks for all the help Aswerty... This is gonna sound naive, but in my Controller, can't I only have one return View(); ...?!?



    I mean if I tried:


    return view(StockDB);
    return View(new DropdownModel { DropdownItems = dropdownItems });


    OR something like return view(StockDB, (new DropdownModel { DropdownItems = dropdownItems })

    In an attempt to return two types of data, this is a big no no surely?!? I know these questions sound riduculous but I am genuinley making good progress with this, just having adjustment issues with Webforms - MVC and the different ways of working with code...


  • Registered Users Posts: 586 ✭✭✭Aswerty


    You can have as many returns in a method as you want but once the program flow hits one it will exit the method and only return the value for that return statement. So in you example of having two return statements one after another; the program would hit the first one and return thus causing the second return to be unreachable.

    So as what I tried to state above, you can return a View and inside this View you can render more Views via the RenderAction() method.

    So for example the controller that gets hit by the clients request may be this:
    public ActionResult Initial()
    {
        return View("InitialView");
    }
    

    The InitialView would look like:
    <div>
    @{Html.RenderAction("Stock", "Product");} <!-- Here we call an action method call Stock in the ProductController -->
    @{Html.RenderAction("CreateDropDown", "Product");} <!-- Here we call an action method call CreateDropDown in the ProductController -->
    </div>
    

    The Stock and CreateDropDown action methods would look like:
    public ActionResult Stock()
    {
        // perform logic here
    
        return view("Stock", StockDB);
    }
    
    public ActionResult CreateDropDown()
    {
        // perform logic here
    
        return View("CreateDropDown", new DropdownModel { DropdownItems = dropdownItems });
    }
    

    The Stock partial view and the CreateDropDown partial views would then be as follows:
    @model Stock <!-- or whatever the type of stock is -->
    <div>
    <fieldset>
        <!-- add info from the model in this partial view here -->
    </fieldset>
    </div>
    
    @model DropDownModel
    <div>
        <!-- add the dropdown helper or whatever here -->
    </div>
    

    In this manner a view can have data returned from multiple action methods.


  • Closed Accounts Posts: 1,143 ✭✭✭LordNorbury


    Aswerty wrote: »
    You can have as many returns in a method as you want but once the program flow hits one it will exit the method and only return the value for that return statement. So in you example of having two return statements one after another; the program would hit the first one and return thus causing the second return to be unreachable.

    So as what I tried to state above, you can return a View and inside this View you can render more Views via the RenderAction() method.

    So for example the controller that gets hit by the clients request may be this:
    public ActionResult Initial()
    {
        return View("InitialView");
    }
    
    The InitialView would look like:
    <div>
    @{Html.RenderAction("Stock", "Product");} <!-- Here we call an action method call Stock in the ProductController -->
    @{Html.RenderAction("CreateDropDown", "Product");} <!-- Here we call an action method call CreateDropDown in the ProductController -->
    </div>
    
    The Stock and CreateDropDown action methods would look like:
    public ActionResult Stock()
    {
        // perform logic here
    
        return view("Stock", StockDB);
    }
    
    public ActionResult CreateDropDown()
    {
        // perform logic here
    
        return View("CreateDropDown", new DropdownModel { DropdownItems = dropdownItems });
    }
    
    The Stock partial view and the CreateDropDown partial views would then be as follows:
    @model Stock <!-- or whatever the type of stock is -->
    <div>
    <fieldset>
        <!-- add info from the model in this partial view here -->
    </fieldset>
    </div>
    
    @model DropDownModel
    <div>
        <!-- add the dropdown helper or whatever here -->
    </div>
    
    In this manner a view can have data returned from multiple action methods.

    I'm gonna have to take a step back and read up a bit on the fundamentals of:

    (1) Partial Views, what they do and how they work...

    and

    (2) HTML Helpers. same as above. I don't know what these things do so I'm kinda pissing into the wind trying to plough through it and make it work without understanding how it all hangs together and what is meant to do what! With Webforms, you could actually make shít work without really understanding how it worked!


  • Advertisement
  • Moderators, Science, Health & Environment Moderators Posts: 8,919 Mod ✭✭✭✭mewso


    I've said it before but going from forms to mvc should be taken as an opportunity to change your thinking. For starters models. Models in mvc terms are models that the view needs as opposed to being direct representation of your database tables for example.

    A lot of mvc is complemented by domain driven design (DDD) and test driven development (TDD). Neither are absolutely necessary approaches to use with mvc but fit in very nicely. One major aspect of DDD is the idea of modelling your domain (the business requirements of your system) using entities. Once we have it modeled we then use an ORM (Nhibernate being my preference, Entity Framework being the MS option) to map these entities to a database. The aim is to model the domain to serve the requirements not the way it will be stored so you map to the database at the end of this process not the beginning.

    On the other end of this is the interface or the views and the models in the mvc project. It's far better to refer to these as View Models though so you have a clear idea in your head of of it's purpose. So if for example we have a Person object:-
    public class Person {
        public int Id {get;set;}
        public PersonType {get;set;}
        public string FirstName {get;set;}
        public string SecondName {get;set;}
    }
    
    public class PersonType {
        public int Id {get;set;}
        public string TypeName {get;set;}
    }
    

    Thats not exactly how I would create my entities for the purposes of example it's fine. Now in a view to create a person we can see we are probably going to need a select/dropdownlist for the PersonType and a property to store the selected value so our View Model will be a different structure.
    public class PersonCreateView {
        public int SelectedPersonTypeId {get;set;}
        public List<OptionItem> PersonTypes {get;set;}
        public string FirstName {get;set;}
        public string SecondName {get;set;}
    }
    

    I have a general purpose OptionItem object that I use for selects as I find it quite handy:-
    public class OptionItem {
        public string OptionValue {get;set;}
        public string OptionTitle {get;set;}
    }
    

    So in my controller action method I might have something like this:-
    public ActionResult Create() {
        var createView = new PersonCreateView {
            PersonTypes = _personTypeRepo.All().ToOptionItemList()
        };
        return View(createView );
    }
    

    Assuming here we have a PersonType Repository which will get all the types from the database and I have written an extension method to convert these to a list of option items. My controllers don't normally call a repository directly but this is for simplicity's sake.

    So now our view should have what it needs:-
    @model PersonCreateView
    
    @using (Html.BeginForm()) {
    <fieldset>
        <legend>Person Details</legend>
        @Html.LabelFor(m => m.SelectedPersonTypeId, "Type:")
        @Html.DropDownListFor(m => m.SelectedPersonTypeId, new SelectList(Model.PersonTypes, "OptionValue", "OptionTitle", Model.SelectedPersonTypeId), "--Select--")
    
        @Html.LabelFor(m => m.FirstName, "First Name:")
        @Html.TextBoxFor(m => m.FirstName)
    
        @Html.LabelFor(m => m.SecondName, "Second Name:")
        @Html.TextBoxFor(m => m.SecondName)
    
        <input type="submit" value="Save" />
    </fieldset>
    }
    

    Again I'm going as simple as possible here as I could spend hours detailing my project structure, utility classes and so on that I use for a standard mvc project but the main point here is to think of Models for your database and Models for your views as two separate things. Most of what you are trying to do doesn't need you to use RenderAction for example. I'm not saying don't use them but see if you can get your head around building view models that service what the view needs before looking RenderAction, PartialViews and view templates.

    If you want me to go into greater detail let me know.


  • Registered Users Posts: 403 ✭✭counterpointaud


    I take an approach very similar to the above, except I tend to prefer to build the SelectList in the controller. I think understanding the SelectList class may be what you are missing OP? I know it threw me the first time I cam across it.

    http://msdn.microsoft.com/en-us/library/dd492553(v=vs.118).aspx


Advertisement