Is there a way to render a complete model as hidden fields?
Something like:
#Html.HiddenFor(m => m)
Or do I have to render every single property of my model with HiddenFor?
Edit:
It is a complex wizard (5-10 steps). In the last step I want to store the data in the DB. Perhaps I can serialize the model as JSON to a hidden field. Then I could also access it via JS.
Well you could serialize the object to a string of some format, such as XML or Base64, and put that into a hidden field, but that is basically just old-school ASP.NET ViewState.
If you are only editing a couple of fields in a large object, it is generally better to just have the ID on the page (in a hidden field or the URL) and reconstruct it again from the database/session/wherever when they submit the form.
Related
I have my form in my action:
$this->form = new SomeForm($this->data);
the form has a bunch of fields I don't need for one action but has stuff I need for another action. What is the best way to handle this? Create an individual form for each necessity or dynamically remove fields when I instantiate it as above?
Thanks
It sounds like you are doing a multi-part form.
I assume that you want to validate all the values submitted in your form, but just not save them.
Its sounds like you are doing an abstract form, so don't extend a base object form, rather extend BaseForm.
Don't unset the values, use the form to validate them, even if they're going to be used later.
They are saved to the form object, so you can use that to pass values to your next action, so this is helpful, plus they are validated.
Override doSave() in the form to save the objects of the form you want to save.
In my opinion for this case, extending the form to each need and applying, through the override of the setup, selectively the unset instruction, you get a code a little more readable and maintainable.
I have the same issue as about 500,000 other users of jqGrid. IE, no rows when I use the url property, which points to an ASP.Net MVC 3 Controller method (which returns JsonView). For some reason, one either needs to provide a JsonReader or use the cell format. My question is why can I load my records using ajax via the same controller method, then set the data property to this collection, and it works fine. I don't need JsonReader or the silly cell formatting Why in the world IS that??
I read somewhere that specifying repeatitems:false would get around the issues of JsonReader and the cell formatting. Is this true???
What I want to do is call ajax, populate grid, let user search in form fields, resubmit ajax, empty grid, set data with new ajax values. How in the world do u empty the grid?
This is sooooooooooooo frustrating.
Heeeeeeeeeeeeeeeeeeeelp
I figured out how to remove (clear) the elements of the jgGrid. Namely, I am using the following:
$("#list2").jqGrid('clearGridData'); //Clear all rows
$('#list2').setGridParam({ data: searchresults }); // Set to the new json result set
$("#list2").trigger("reloadGrid") // reload
This works killer, plus you don't have to deal with the black magic of the JsonReader... whatever is going on behind the scenes is a mystery. The above assumes that searchResults was populated by a return Json(list) from the MVC Controller. So, when a user searches by firstname, lastname, etc, simply do an ajax call to the controller, then reload the grid.
Granted this may not be the most robust solution, but for small result sets it rocks, plus you can trace every step.
In my app I have a criteria builder section that's built using jquery and is pitched back to the controller in a form post and picked up as IList by the model binder as suggested in Phil's post here: http://haacked.com/archive/2008/10/23/model-binding-to-a-list.aspx
A really simple way that I'm persisting the criteria across posts is re-delivering the IList object to the view. I'm using a DisplayFor() template for this object, but because it's a list I need to know the index # inside of the template.
I'm hoping there's a context value somewhere.
Well, I couldn't find any information on that kind of meta data, so I had to crud up my view model to contain that index and another property. So now it's a simple Model.IndexItem on the template that returns it's order in the entire collection.
asp.net mvc model object is being fetched by ajax call - $.ajax(....
form has fields with IDs exactly to matching properties on returned json object (created by Html.TextBox("NAME", Model.Order.NAME) )
How to automatically populate fields(inputs) with corresponding json object properties ?
Manually would be like $("#NAME).val(json.NAME) so how to make this dynamic?
Is there some kind of reflections (like System.Reflection in c#) for javascript/jquery ?
Maybe something like this:
$("#formId input").each(function(){
$(this).val(json[$(this).attr("id")]);
});
... which iterates over all the form inputs, and looks for a JSON entry with the inputs ID.
The thing to note here is that you can retrieve json.NAME via json["NAME"].
alt text http://img3.imageshack.us/img3/1488/advancedsearch.png
I'm building an "Advanced Search" interface in an ASP.NET application. I don't need SO to write this thing for me, but I'm stuck on a specific problem regarding dynamic controls and ViewState. I would like some direction for how to approach this. Here's my situation:
Ingredients:
A serviceable set of API objects representing entities, fields, and searches, which handles constructing a search, generating SQL, and returning the results. So that's all taken care of.
ASP.NET 3.5
Desired Interface Functionality:
(1) On initial page load, the interface gets a preconfigured Search object with a set of SearchCriterion objects. It binds them into a set of controls (see image above.)
Some search items are simpler, like:
Field (DropDownList) | Operator (DropDownList) | Value (TextBox)
Search Criterion controls for some field types have important information stored in viewstate, like:
Field (DropDownList) | Operator (DropDownList) | Value (DropDownList) where the "Value" dropdownlist is populated by a database query.
Some fields are lookups to other Entities, which causes a chain of field selectors, like:
Field (DropDownList) Field (DropDownList) | Operator (DropDownList) | Value
(2) The user modifies the search by:
Adding and Removing search criteria by clicking respective buttons
Configuring existing criteria by changing the Field, Operator, or Value. Changes to Field or Operator will require the control to reconfigure itself by changing the available operators, changing the "Value" input control to a different type, or adding/removing DropDownLists from the "Fields" section if Lookup-type fields are selected/unselected.
(3) Finally, the user hits "Search" to see their results.
The Problem:
As you probably already know if you're answering this question, controls added dynamically to the page disappear on postback. I've created a UserControl that manipulates the control collection and neatly accomplishes step (1) above as you can see in the attached image. (I'm not concerned about style at this point, obviously.)
However on Postback, the controls are all gone, and my Search API object is gone. If I could get the dynamically generated control collection to just play nice and stick in ViewState, I could examine the controls on postback, rebuild the Search object, then handle control events neatly.
Possible Solutions
I could make the Search object serializable and store it in viewstate. Then on page load I could grab it and reconstruct the control collection at page load time. However I'm not sure if this would play nicely with controls raising events, and what happens to the viewstate of Drop-down lists that contain data from the database - could I get it back? It's highly undesirable for me to have to re-query the database on every postback.
I could develop a custom server control (see this link) for this kind of thing... but that is a new topic for me and would involve some learning, plus I'm not totally sure if a custom server control would work any more nicely with non-fixed control collections. Anybody know about that?
I was thinking that I might be able to accomplish this using databound controls - for example I could bind my criterion collection to a repeater which has a fixed control collection (maybe hide the non-used "value" controls, use an inner repeater for the "Field" drop-down lists). Then all the information would stay in ViewState... right?
Any new ideas would be greatly appreciated.
thanks for your help.
b.Fandango
I've been coding for about a day and I got this working beautifully using the third option I suggested in my question - old-school databound controls. Actually I only thought of the idea when I was forced to write out the question in detail - doesn't that just happen to you all the time?
I put my SearchCriterionControl into an asp:Repeater and bound it to my object collection. For the Field Chooser I put an asp:DropDownList inside a nested asp:Repeater and bound the Field array to that. Everything works beautifully, keeps state, actually required very little code. So I never had to dynamically add controls to the page, thank goodness.
Thanks for your suggestions, Ender, Matt and andrewWinn.
Since no one else has taken a stab at this for 2 hours, I'll throw my hat in the ring with a solution that does not rely on viewstate at all (or the ASP.NET model of postbacks).
What if you grabbed all the input values with jQuery and instead of doing a post-back did a post against the page (or a new results.aspx page)? Or, you could make the entire thing asyncrhonous and do an Ajax request against a web method, get fed the results, and populate on the client side as needed?
The unfortunate thing here is you have to reconstruct which type of controls were used to figure construct your search query since that data wont be passed with the viewstate. But I imagine you were already going to have to do some kind of translation of your input data into a query form anyway.
Read here for more information about using jQuery to hit an ASP.NET page method. Remember - page methods must be static (it's an easy oversight).
I'm not sure what you're doing server side to construct your query - but I would highly recommend LINQ. I did a similar "advanced search" function previously, and after a few different attempts found that LINQ was a wonderful tool for this problem, regardless of whether I was hitting SQL with LINQtoSQL or just hitting an in-memory collection of objects.
This worked so well because 1) LINQ is deferred execution and 2) A LINQ query returns another queryable object. The implication here is that you can chain your LINQ queries together as you construct them from your input, instead of having to do a single massive clause translation to SQL or whatever backstore you are using (one of my attempts was constructing SQL clauses with strings, but still passing input data via SQLParameters for SQL injection protection - it was messy and complicated when hand crafted LINQ was orders of magnitude easier to understand and implement).
For example:
List<string> data; // or perhaps your a DB Context for LINQtoSQL?
var query = data.Where(item => item.contains("foo"));
if( {user supplies length search option} )
query = query.Where(item => item.Length < 5);
// etc, etc.
// LINQ doesn't do anything until the query is iterated, at which point
// it will construct the SQL statement without you worrying about details or parameter binding
foreach(string value in query)
; // do something with the results
Because of deferred execution and the queryable return type, you can concatenate LINQ queries to this expression all day long and let it worry about the implementation details (such as converting to a SQL query) at execution time.
I can't provide you with the exact steps that you will need to do, but I HIGHLY suggest looking into asp.net page life cycle. I created a user control as a DLL one time. I had to capture postback data at specific steps in the lifecycle and recreate and rebind the data at other steps. Additionally thinkgs like viewstate are only available at certain points also. I know that I had to override On_init, On_prerender and some other methods.
Sorry I couldn't be more help, but I don't have the code with me (its with an old employer). I hope this helps.
If you are adding controls to the controls tree dynamically, you need to add them on postpack as well. Just call the method that builds the control on Page_Load or Page_Init and the controls should stay on the page on postback.