Multiple dropdowns from one selectlist asp.net mvc - asp.net-mvc

I just ran into an issue that I have never noticed before and I want to know if this is something isolated to my current project for some reason or if this is an issue that I need to panic about and check every one of my applications and correct right away.
I have two drop downs on the same page using the same select list.
ex. HomeCity and CurrentCity
both populated from the same list of cities. Therefore in code both populated from the same IEnumerable<selectListItem>
It turns out that if the second value on the page is null (in the view model) then instead of defaulting to the optionLabel it defaults to whatever the first value is.
This issue is much exasperated when (as I often do) you try to cache the SelectList. Not only is the next item on the same page set to the wrong value, but the selected item gets changed in the cache (which is so strange because you would imagine that the cache serializes the values and give you a copy.
So my question is twofold.
is this the usual functionality or did I trigger this weird behavior somehow?
What is the recommended way to avoid this? Would I need to do a deep clone of my select list between dropdowns?

Related

MVC4 - getting list of fields in View

Is it possible to safely programmatically get a list of fields that are in the View that has just posted back to a Controller?
I noticed a problem with the default implementation of the scaffolding, in
DB.Entry(model).State = EntityState.Modified
DB.SaveChanges()
The problem is that if I haven't included a field to be edited in the view, it is being overwritten by the default value of the field that .NET assigns when creating the object. eg. If I have a User class with ID, Email and PasswordHash and I want to allow the user to update their Email address only, if I don't include anything for the PasswordHash field, it is reset to NULL as it is passed into the controller as NULL. At the moment, I am working around it by retrieving the current object from the database and updating only the fields which I know are in the View from the model passed in. That isn't such a problem for a small table, but I would like to have a general solution that I can apply across the board, especially for large tables which may during development and I don't want to have to update the code every time.
I know that I could loop through the POST variables and examine them to see what has been posted, but that creates a security issue as the user could inject additional fields that I don't want them to edit. I suppose I could explicitly exclude ones that I don't want them to edit, but then again, I would rather not have to list those if I can avoid it as it is an extra thing to maintain.
I think that there are 2 problems here and I'm not sure either are solvable...
Getting the View that posted back
Establishing which fields are included in that View (I might need to construct it again temporarily to do that?)
I suppose that I can probably get away with ignoring the first one as I could just only ever use that method on the Controller for a single View. That is still a little less neat than I'd like, but it does reduce the issue to just establishing which fields are in the View.
If a view needs only certain properties, create an interface with only those properties. Use this interface in the HttpGet and HttpPost methods.
And then you can use something like AutoMapper to map the viewmodel to your entity.

groovy: save gsp state

I have 2 gsp's say, "a.gsp" and "b.gsp".
"a.gsp" have combobox, from which user can select options.
My question is that, if the user shift to "b.gsp" and then come back to "a.gsp", the combobox selected option should be still there.
How to achieve this ?
You can do multiple things to achieve this. Depending on your requirements you may:
Use javascript and cookies.
Pass the value selected in the combobox into the controller when you naviate to b.gsp and into a hidden field in b.gsp, but then you have to pass it back to the controller once more when you want to see a.gsp.
Pass the selected value inside session/flash scope
From your question it sounds like you are not fully embracing Grails' MVC architecture and using controllers correctly to prepare data and pass structured data through to your view.
To begin with, rename your controller actions and views to something meaningful rather than a,b. Even if just for testing a small sample, as taking shortcuts can lead to long term bad habits...
Secondly, if you are using a tag then you would use the value attribute to indicate what should be selected.
Read about the tag and its attributes here : http://grails.org/doc/2.1.0/ref/Tags/select.html
Give us more details and perhaps we can help.
Thanks for the clarification, so I'm assuming that there could be any number of ways a user might leave the current a.gsp page and come back, but whatever happens you want the browser to remember the selected option. In this case I would use the jQuery cookie library, its very small, won't impact performance as you're doing very litte work and should be very quick for you to setup.. See: https://github.com/carhartl/jquery-cookie
Set a cookie in an onChange handler based on your selects val() value.
When your page loads (document ready), if you get a value when reading the cookie, then try and set the select value.

Telerik Grid MVC and check all checkbox on all pages

On Telerik demo site we can see an example of how to implement kind of functionality: "check all checkbox in a grid's column". But in my case it has 2 disadvantages:
It didn't check all checkbox on all pages.
It didn't save a state of checkboxes on different pages.
Is anybody know how to resolve these issues? Thanks in advance.
As long as I know there's no built-in functionality to do so. The same problem happens when you select records on page one and change to page two, you loose whatever you selected before.
To achieve that functionality you have 2 options (I've used both on previous projects)
1) On each check make an Ajax call to one of your controllers and store whatever you selected on a Session Variable (This can be inefficient if you have a lot of records)
2) Create a javascript variable and store your selections there, and send back to the controller using a json variable or a comma separated values string
As I said, I've used both approachs so it depends on if this works for you or not
Hope it helps
I can't test this, so I'm not 100% sure, but looking at Telerik's example, one reason it's not persisted is because every "page" of the grid requires a postback, and in the controller action result method, they aren't passing in the model (or view model) for the items that are bound to the grid, they're only returning that list of items back to the view, so it will never "save" which items are checked/selected and which ones aren't. You should be able to get around this by making your view model a parameter into the HttpPost action result method and then passing that list back to the view after the post so that it retains which items are selected instead of creating a new one. This won't solve the issue with not selecting all the items, but it should at least retain which ones are selected throughout the pages. I think the reason for it not working with all items is it can only select the ones that are actually being displayed at the time. You may want to do a post (or ajax) to select "all" items.
One of the major reasons for using paging in grids is so that you don't have to retrieve all of the data from the data store and generate a lot of HTML to push to the client.
It's been my experience that most users understand that a "select all" check box only checks the items on the current page. I've not seen a site where checking such a check box would actually check all records, even those I can't see.
If you have an action which will affect more than the current page of records, I would suggest that you add a button which clearly indicates that the action will affect all records, then send a command to your data layer which will perform that action. This will perform better (you don't have to send a potentially long list of ids across the wire) and allow users to understand the repercussions of their action.

Strongly typed view model and re-rendering select list if Model is not valid

Ok, I looked a bit and couldn't find a good answer to this question.
Using ASP MVC3 I have a strongly typed ViewModel that has a list of custom objects retrieved from a repository. I render out using DropDownListFor as a dropdown selection. A value is selected and during the post I have a custom binder that rebinds my selected value to the custom object....Life is good...
I check my Model.IsValid and it is not valid for some reason. Uh, oh...I need to display the view again but I dont have the complete list of all options. Is there a way to repopulate all of the select option values in the custom model binder or some other method or do I have to hit my repository again?
Thanks.
You hit your repository again. Implement caching in your repository using a MemoryCache to save on DB hits and cache by key. This is the advantage of the repository pattern and the caller is unaware. Since by definition a repository is essentially an in memory representation this works out great.
Check out the implementation here it's similar to what I use and it works great.
http://stevescodingblog.co.uk/net4-caching-with-mvc/
Your currently selected item should remain selected since the HTML helpers read it from the posted data and reuse it.
I typically rebuild the list again and send back to the View. Often I'll use a factory method to inflate the viewmodel(s) with the necessary list(s). Hopefully, an invalid model will be a rare occurrence due to client-side validation in addition to the server side you're working with now.

Multiple Dynamically Populated Drop Down Lists

I've got a page which will have about ten drop down lists which are generated from my SQL database. What's the best way to populate them? I was going to use a stored procedure with LINQ to return multiple result sets, but it seems a bit overkill. Is there another way of doing it? Using HtmlHelpers or something like that?
Seeing as though everyone seems to be confused by this, I will elaborate.
This isn't to do with caching, that's not what the problem states
This isn't to do with ASP.NET controls such as DropDownList, I tagged it asp.net-mvc
This isn't to do with code-behind models, I thought that was implicitly obvious by how I tagged this question originally as ASP.NET MVC
The problem is that multiple results sets are required on the page for drop down lists (think HTML!). So I have a drop down list for your favourite breed of badger, a drop down list for how many birthdays you've had, a drop down list for how many clouds are in the sky today. All of these are dynamically populated (please note, I am joking, this is a finance system I work on). I need all of them to be on my view page, but I'd rather NOT use the IMultipleResult return type in a LINQ stored procedure to bring back multiple result sets. It just gets messy.
So in basic, I want about 10 drop down lists on my view page, all of which are populated with data from a database (which constantly change). What is the best way to get them on the view?
I would just pass the required data to the view, either in multiple ViewData dictionaries or as a special view model if you want strongly typed access. Then use HtmlHelper.DropDownList() to display the actual drop downs.
Weakly typed solution
Controller
ViewData["Data1"] = SomeRepository.GetList();
ViewData["Data2"] = SomeRepositoty.GetList();
return View();
View
<%= Html.DropDownList("Data1") %>
<%= Html.DropDownList("Data2") %>
Strongly typed solution
View model
public class DataViewModel
{
public IEnumerable<string> Data1 { get; set; }
public IEnumerable<string> Data2 { get; set;}
}
Controller
var model = SomeRepository.GetModel(); // returns an instance of DataViewModel
return View(model);
View
<%= Html.DropDownList("Data1", new SelectList(Model.Data1)) %>
<%= Html.DropDownList("Data2", new SelectList(Model.Data2)) %>
It depends on the data, if the data in the database is not updated that often, then you could have a process that creates XML files once a day. Then use the XML files as the source to the dropdowns, this would speed up the application and limit the calls to the database server.
This is really a question of data management, not anything to do with HtmlHelpers until you get to the very pointy end of things. Anyhow, the first thing I would ask myself is "how is this data updated and what kind of filtering do I need?"
If this list is pretty much constant, then you could go for a bit of caching.
If this list is pretty fluid, then just pull it out of the database as needed and be done with it. Worry about caching if your DB box starts melting.
Either way you probably want to wrap things up in some sort of LookupService class, but there isn't enough to go on to make any more specific recommendations.
I second Wyatt's recommendation about grabbing from the DB each time if the list is fluid.
However, I'm doing a similar thing (with 10+ dropdowns on each page, all very static... the values will rarely change).
The first version of the application had a helper method for each dropdown list (about 20 total by the end of the project) that grabbed from the respective tables and cached via another helper. Before I started caching, there was no db context available for the view (i created it in the controller and didn't pass it), each dropdown had to create a new connection. This got noticeably slow. Plus, I had some problems with my caching routines, and saving them with 20 magic strings in the cache, etc. Also, I had a separate querying object where I had to manually build the relationships, and having to create the 20 relationships for inner joins was a pain.
So... my new version:
I'm using a single "selectables" table. There's a PK, and a "selectable type" (which I have to admit is a string). There's a selectables enumerable, which makes things a bit cleaner. There's a main getAllSelectables() method that looks for the entire result set in the cach (and gets all rows from the db if its not in the cache) and returns it. Then there's a getSelectables(enum) that grabs out only the relevant values, and a third function getSelectListItems(enum) that calls getSelectables(enum) and returns a ienumerable for the mvc helper function.
Hope that helps,
James

Resources