Ok, so this is an alternative to this question.
I'm trying to produce an MVC application using LinqToSql that allows for bulk editing of data on a single page.
Imagine a simple table Item with ItemId, ItemName, ItemPrice as fields.
There are many examples out there of extrmely simple MVC applications that show you a list of these items with an edit button next to each and an add button at the bottom.
From a UI perspective I find this very time consuming when a lot of data needs entering / updating.
I'm after a single page containing the items names and prices in textboxes that can all be edited in one go and then a single "Save" button pressed to update the data.
I've seen a number of examples that perform various stages of this but have yet to find one that implements the full solution. In particular the interaction with Linq.
I have a number of methods I've tried which all work, however, my gut feeling tells me my methods "smell" and therefore I'd like to see some examples of how other people have attempted this.
So, put simply, my question is can anyone provide some links to some examples please?
I have written about how to do this with MvcContrib's FluentHtml. Steve Sanderson has written about how to do it without FluentHtml. Both of our articles have a sample solution you can download and look at.
As far as LinqToSql, I would consider any interaction between bulk editing mechanism (controller and view) and LinqToSql to be a smell. That is to say, as far as possible your UI should be ignorant of your persistence mechanism.
What I would probably do to get around this is use jQuery to call a jsonResult when you switch rows. This jsonResult would call the code in the model to save the ItemId, ItemName, ItemPrice for only the row you are switching off of. More on general jsonResult w/ jQuery usage here : http://www.dev102.com/2008/08/19/jquery-and-the-aspnet-mvc-framework/
The other thing you could do is do model binding to a list of Items, iterating thru the list saving each item -- Phil Haack has an example of list binding here: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx With either method you'll want to do something to signify the row has changed so you're not updating every field if you're just changing a handful of rows.
What is your goal exactly, are you trying to commit a series of information all at once? Or do you simply not want your page to postback every time you change something. In either case jQuery is your best bet. If you want to do everything in one pass it is going to get complex unless you use a jQuery control that will do this for you. There are some great ones out there such as the Flexigrid.
Related
I am beginning with MVC ASP.NET and stumbled upon a problem. There is a paragraph (some 5 sentences) I would like to use on several of my child pages. This text changes quite often so I would like to have it defined on 1 place so I dont have to update like 10 pages when it changes again.
Problem is, that I dont know how to do it. I was thinking about using CSS (which should be used for styling, not text) or sections (doesnt work, as each child page needs its own sections defined).
Could someone advise me the most optimal and "correct" way to achieve this? I would like to define this paragraph at one place and then "call it" from the child page without need to use the database. Which approach should I choose?
Thank you
Create one partial view and call in your main view:
#Html.Partial("YourPartialViewName", Model) //if you have some dynamic data pass in model
First, I apologize if this is a dumb question, but I'm new to MVC and am trying to get up to speed as quickly as possible. I have spent hours searching for answers and even went and bought a book on MVC 4, but it still didn't answer my question.
I have a form I'd like a user to fill out to add a new product to the catalog. They choose the category, enter the name, a description, etc.. On the same page I'd like them to be able to add sizes or product options such as Small, Medium, Large, etc.. The problem is I'm not sure how to go about this.
I need to temporarily store the size options for example in some sort of collection until the user actually 'saves' the product, then I need to be able to read the collection. What I'm trying to avoid is to have the user add the basic product info, then save it, then select it, then choose to add options to it. I'm trying to just do it all on one form. Any help would be greatly appreciated!
There is nothing preventing you creating a view model with its own collections for the detail items and have those mapped to some sort of javascript control for selecting multiple items such as one that writes to an mvc hidden form control.
The controller handling the postback will simply create the master model from the postback data (the updated view model) and then create the child records. The whole thing could be achieved with ajax calling a controller action that returns a partial view of the updated ui.
Similar to this but have the list as a property of the master model
http://www.stevefenton.co.uk/Content/Blog/Date/201002/Blog/How-To-Handle-Multiple-Select-Lists-In-ASP-NET-MVC/
A little more advanced on how to manage your own bindings http://www.dotnetcurry.com/ShowArticle.aspx?ID=584
Sounds like u need to roll your sleeves up and get a control written in javascript that allows child items to be added client side whist serializing e.g. Into json when they save and saving it to an mvc hidden control ready for postback. Use json.net to hydrate these values into your pocos. http://erraticdev.blogspot.co.uk/2010/12/sending-complex-json-objects-to-aspnet.html
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.
This might be similar to ASP.NET MVC - Populate Commonly Used Dropdownlists.
I want to populate DropDownLists. Some of it is static data. Some of it comes from the Database. A couple of times I found myself forgetting to call the code that populates my lists and sets the ViewBag accordingly. It is almost worth adding a unit test for this. The only way I think that this suits a unit test is if you place it in model/service. Is there a best practice for this kind of thing?
I'd suggest that the data is contained within the model but is perhaps constructed by a html.helper method. this way, you keep the plumbing markup out of the view and leave the controller free to invoke the neccesary view and model.
You could also of course hand it off to a partialview with an <IList<SelectList>> model.
cats and their skin :)
If you follow the spirit of the pattern then the Model should supply the View with everything it needs to present to the user that's not static. If you have static dropdown lists then you could say that these could be constructed within the mark-up. If you are passing a SelectList to the View from your Action then I'd stick it in the Model to make things simpler and more coherent.
My rule of thumb is that the data must somehow be in the model, either as a ready to use SelectList or at worst in some container that can easily be turned into a SelectList using a LINQ-to-object call.
The bottom line is that the view should never contain any non trivial code.
EDIT (answer to your comment):
I try not to put too much code in models. Models are more like a simple bunch of data gathered by the controller and used by the view.
Regarding simple and/or common things such as the days of week, I believe an HTML helper is the most elegant solution. See WayneC's answer in this question.
I have an application that has two dependent dropdown lists, where if the user selects a value in list box A, it updates the available set of inputs in list box B. Such as make/model of a car. when the user selects the manufacturer, the list of models would update accordingly.
In winforms, this would just be handled in the autopost back event. What technique/approach should I take in asp.net MVC? is done through AJAX ? just trying to get up to speed on MVC and looking to build strategies to handle common tasks I am asked to handle at work.
I wanted to thank everyone who contributed to answering this post.
I'd do this through ajax. If you have these controls:
<select id="makes" /> and <select id="models" />
then you can do this with jquery:
$().ready(function() {
$("select#makes").change(function() {
var make = this.value;
$.getJSON('models/list?make=' + make, function(data) {
//load 2nd dropdown with result
})
});
});
Then you'd just need an action on the ModelsController called List() that returns a JSON data structure.
That you are using ASP.NET MVC is somewhat irrelevant. You basically have three options for this type of UI mechanic on a web page.
If the data in your lists is relatively small and infrequently changing, it can be easiest just to pre-load all possible data on the page in the initial request either in something like a javascript array or hidden elements in the page markup. When the value of Box A changes, javascript just replaces the contents of Box B with the appropriate data. This all happens without any requests back to the server which makes it very fast. But this method breaks down when the size of your data impacts the response time of the initial page load.
If the data in your lists is large or frequently changing (within the time frame a user would be on the page making a decision), the legacy method is to just have the page get reloaded with the new query arguments when the value of Box A changes. Code on the back-end adjusts the output based on the new arguments. Depending on how complex the rest of the rendering code in your page is, this can be expensive.
This is a variation on option 2 and is basically the answer Ben Scheirman gave regarding ajax. You're still loading the contents of Box B on demand when Box A changes. The difference is that you're only reloading the piece of the page that has changed rather than the entire page.
Personally, if your data is small enough to use option 1, that's probably what I would go with due to its performance. Otherwise go with option 3, particularly if you've already got other ajax related things implemented already. Option 2 is seems to be considered a legacy mechanic by many people these days.
Functionally it would work to place those two drop lists in their own partial view and then return just that when the value in ListA is selected. If that isn't feasible for layout purposes, then Ben's method above looks good.