I have five pages in asp.net web application. I entered information in first page and click next. it goes to next page and enter information in this page. I continue this process for five pages. Before click Submit button in fifth page, I need to review once all information entered by me in all previous pages under review button click. How do this? pls Advice.
You can store your data in the database, as you move along the steps, and retrieve it in the final step. You can also store it in Session, as an alternative.
Surely there are other ways to implement this scenario, but the idea is to somehow persist the data and retrieve it in the final step.
I personally think that you are going the wrong way about this. Passing data from page to page is going to cause you all sorts of trouble.
There are a number of methods to achieve this on a single page. You could create 5 seperate controls and place them all on the single page (if they aren't all too big and slow down the page load), then make the appropriate control visible depending on which the user is to see. For example, when you click next make the current control visible property false and then display the next one. Then at the end of the process when you click complete you can access the entered data from each of the controls, you could create a fancy function in the controls that return you a populated class or even pass by reference (we won't go in to that here).
You could also look in to using Views. Which is another method that you could implement on a singular page.
If you're adamant with using multiple pages then you could temporarily store the data in a database and then on the final page get the IDs from a Session and store it all finally as one. But I wouldn't advise this, although it depends on the situation. If you want them to be able to fill half the form and then continue at a later date then the database method would be advisable, but if you only want data being stored upon completion then you will end up with a lot of half completed redundant data using this method.
The solution totally depends on the framework and methods you are using. I'll try and help you with an ASP.Net MVC3 solution, as I think MVC3 is really the way to go for when using ASP.Net.
When the user clicks on the 'next' button, just load a partial view (containing the next step html) with the JavaScript / jQuery Ajax method, OR just present the next step by using using the jQuery show / hide functions.
Keep your form data within one html form-tag (or at least one holder-div).
When you need to submit the information at the last step, simply collect the information with a single jQuery serialize call and send it to your ASP.Net receiver.
Some code snippets:
Display a partial view from the Razor view-engine:
#Html.Partial("/Views/Instance/_General.cshtml", Model)
Load a partial view through jQuery - for more details, please see http://api.jquery.com/category/ajax/
#Html.Partial("/Views/Instance/_General.cshtml", Model)
Post your data to the server though jQuery:
$("#submit-button-id").click(function () {
var data = $("#form-id").serialize();
$.ajax({
url: "/Example/Save",
type: "POST",
data: data,
cache: false,
success: function (success) {
if (success) {
// things worked out just fine..
}
else {
// present some kind of error..
}
}
});
});
There seem to be several ways to integrate jQuery dialogs with ASP.NET MVC. Has a specific approach emerged as the commonly-accepted best-practice way to do so?
As an example: I have a list page where clicking "edit" for any of the listed items opens a form in a jQuery dialog, populated with the item's details. User edits details and clicks "save". If the save succeeds on the server-side, the dialog is closed and the list is re-built with fresh data. If the save fails on the server-side, the dialog remains open and displays the error message(s) to the user.
No-JSON approach: each "edit" link is an HREF to an "edit" controller action. That controller action builds a view that is identical to the "list" view, plus it includes a partial action to build the edit form, populate it, and define the javascript to pop it open as a jquery dialog. The "save" is a form-post; if it succeeds, it returns a redirect action back to the list page. If it fails, it rebuilds the entire page (including the form that pops up in a dialog) displaying the error messages as well.
All-JSON approach: the list page renders an empty edit form (hidden), ready to be popped open into a dialog. The "edit" link calls local javascript which does an ajax request to get the full object (I define a controller which returns the full object as a JsonResult). On success, it fills the edit form with the object's data and opens the dialog. The "save" link calls local javascript which bundles the form data into a json object, and calls a post operation with that json object as payload (I define a controller which expects that object, attempts the save, and returns a JsonResult indicating success/failure+errorMessages). Success callback from the ajax request evaluates the returned object, and either shows the error messages in the still-open jquery dialog, or closes the dialog and reloads the "list" page to get fresh data in the list.
[Edit] Ajax-HTML approach: just saw this SO discussion which describes another approach. The "edit" calls local javascript which does an ajax post to get the FULL HTML of the dialog (I would write a controller which returns a partial view: the fully-populated form). It renders the returned HTML into a jquery dialog, and also "re-wires" the form submission to do an ajax-post of the form's contents (I would write an httpPost controller, same as in #2 above). The success callback evaluates the response and populates error messages or closes the dialog.
Some other cool approach I haven't thought of?
Option 1 seems to be more in keeping with "pure" ASP.NET MVC. However, it seems to feature big HTTP payloads (since we're shipping the full page back to the browser on every request), and slower server-side performance (since we're re-building the list on every request).
Option 2 seems to be more consistent with more modern Ajax-based web applications (smaller HTTP payloads, more granular operations). However, it seems like many of the controllers will be JSON controllers, and I'll be writing a lot of client-side code to marshal data from JSON objects to/from form fields, display error messages, etc. It also seems like I'd be missing out on a lot of cool MVC features like EditorFor() and ValidationMessageFor(). It just "feels" like I'm working around the MVC system instead of with it.
[Edit: added option 3] Option 3 seems to be a bit of a hybrid between 1 and 2. I use the "pure" MVC approach to build and populate the form, and return a fully-formed HTML FORM tag. Returning HTML to an ajax request feels weird since it's so verbose, but I can get over it. The post operation is nice, compact JSON which "feels" better over ajax. However, it's unfortunate that the payload object is a FormCollection rather than a real viewmodel object. It seems like I can make use of some of the MVC conveniences (EditorFor()) but not others (ValidationMessageFor()).
I'm looking for the "right" way to do this, not just the fastest way to hack it together. Yeah, yeah, I know there's no universally "right" way. But I'm sure there's some notably wrong ways to do it, and I want to avoid them.
I'm pretty experienced in ASP.NET/C#, but I'm pretty new to MVC. Thanks in advance for your help!
[Edit] - outstanding responses - I wish I could award multiple answers/bounties, as I found several responses extremely useful. But since I can't, I'm marking the top-voted response as the answer. Thanks again to all respondents!
My team and I have a lot of experience writing AJAX enabled MVC apps, and we have used all 3 approaches.
However, my favorite is definitely the AJAX-HTML approach -- Use a PartialView to render the contents of the dialog, which could include server-side validation messages and any other logic.
The biggest benefit of this approach is the separation of concerns - your Views are always responsible for rendering your HTML, and your JavaScript doesn't have to contain any text, markup, or "templates" needed to render the JSON.
Another big advantage is that all the great MVC features are available for rendering the HTML: strongly-typed views, HtmlHelper, DisplayFor and EditorFor templates, DataAnnotations, etc. This makes it easier to be consistent and lends well to refactoring.
Just remember, there's no requirement to stick to a single approach. When your AJAX call only needs something simple, such as a status update like "Success", it's fine to just use a string or JSON to convey those messages. Use PartialViews when HTML is needed, and use simpler methods when communication is needed.
Your 2nd method, the All-JSON approach, seems to be increasingly prevalent with MVC and MVVM client side libraries like Knockout
In this you could actually have all of the data in JSON (including the list) and edit list items (similar to their list item editor demo, just with a dialog rendering isntead of inline, and bind the data to readonly spans in your cells) and then serialize the entirety of the set back to the server on save. Or you could do it with piece-meal saves after each popup edit.
JSFiddle: http://jsfiddle.net/paultyng/weLtH/17/
The JS could be cleaned up a bit, I didn't include a save button, but you should get the idea. The edit dialog could be a single template bound to one edit as well, instead of doing per row, this was just the simplest way to do it with Knockout.
I think the best way would be to render the list normally. Hook up the edit links to go to a separate page (follow me here) like you would normally do.
With JS handle clicking of the link, and do a get to it's href. In the edit action do a check for Request.IsAjaxRequest() and if it is, return a partial view if it isn't, return the full view. Or render the normal edit view without the master page (pass in null to the master page parameter in the View() call or call return Partial()). Take the contents of the result and put it into a dialog.
Also use JS to handle submitting the form and getting the result from the request. If it wasn't successful insert the contents of the view into the dialog to show that there were errors. Otherwise close it and move on.
The benefit to this approach is it's very unobtrusive and still allows functionality for those who don't have JS.
Ok, so your options are pretty much torching the concept of progressive enhancement here. 2 & 3 aren't going to work if your client doesn't support java script. Obviously thats ok if you don't care, but I think I'd try to engineer things so that they degrade gracefully and you are asking for best practise here.
So the way I would construct it, starts with your option 1. You have edit buttons that trigger another action which loads an edit page, and this page is designed with all the validators etc as per normal mvc. That's your base functionality so works with no js.
So then the next question is how do we progressively enhance this to have a nice popup instead of a new page?
Well first step is to create a handler to open your dialog attached to the edit links on click (make sure to e.PreventDefault). Now to save too much coding effort I would be looking to reuse the edit page. This is going to require a bit of refactoring though as you don't want to include the layout for the ajax requests. You can do this a few ways, but I think the cleanest is to have the edit area of the edit view as a partial view which the main edit view uses to render its model.
Then, in your edit action, you can check if you have an ajax request, if so then return a PartialView(mypartialeditview) or a View(editview) if not.
In terms of then submitting the results back to the server if you want an easy life just treat it like a form. You can use the micorsoft unobstrive ajax here and it will be very simple. You use Ajax.BeginForm in your partial view. n.b.This will degrade to a normal form if ajax not available. Have the AjaxOptions for this beginform set to update the div in the dialogue so if it responds with its html you don't have to do anything more, it implies a validation error.
[small aside as you asked above about this: In terms of the HttpPost handler, the default model model binder is amazingly smart, it can bind form fields to properties on a complex class object parameter. This also work with json so you don't have to end up with lots of action methods to support different scenarios.]
So if your update is unsucessful the post handler will return the partial view again, bound to the model so you'll get all your validators. If however the update is successful I would suggest that rather than return anything, the action does a redirect back to your main page which you want to reload anyway as you've changed the underlying.
If you don't like doing a full reload of the main page, then it gets more complex as with the approach above you are returning html. You will either have to jquery over that to find a hidden field or class to indicate success/failure or migrate to a pure json approach which returns a jsonresult. This is getting heavier on the maintenance/coding front though. I'd probably do the jquery check and have it wired to the completion handler of the ajax.Beginform.
If you really want to get your head around this stuff, I have found the Steve Sanderson Pro Asp.net MVC book invaluable. The one I initially read was for MVC2, but just in process of reading the MVC3 update. I have mixed feelings on the update, as its been simplified in a few places - easier to follow now but I feel like a few things are missing, also it was rushed as some errors etc as it gets near the end. I guess maybe they panicked now that MVC4 is being talked about and book wasn't out! Still a good book though and it covers all this stuff beautifully.
Hope this helps. Appreciate it covers some of the same ground as an answer above but hope I've drilled in more for you.
Using jQuery.tmpl() plugin1
I use a similar scenario but do it in a different way.
I have a master list where each item is wrapped in a container (be it table TR or DIV). Some general information about the item is displayed in the master list when there's too much data to contain in a simple list. Hence a master list and not details (of course).
Each item container is usually written this way:
<div class="item" data='<%= item.ToJson() %>'> <!-- single quotes! -->
item visible list data
</div>
The main part here is my custom extension method ToJson() that serializes my item data which can easily be used on the client.
Then I have a jQuery template at the end of a list contained inside a script tag. This template is the actual content of the edit dialog with all item variables set as needed.
Whenever user clicks edit on the item, I simply parse item JSON by:
// in edit link click handler
var itemData = $.parseJSON($(this).closest("[data]").attr("data"));
// display dialog
displayDialog($("#editDialog").tmpl(itemData));
My dialog than takes care of the rest via Ajax calls and closing the dialog when calls are successful or user cancels editing.
This keeps my HTML code to minimum (having only one template) and JSON also contains only those properties that are actually needed.
What to do when your model class has other entity references?
This is quite common that entities are related between each other. Suppose you have a Post and Comment entities:
public class Post
{
public int Id { get; set; }
public string Body { get; set; }
public IList<Comment> Comments { get; set; }
}
Of course you're not interested in related entities when converting your items to JSON on the server. That's why you can put an attribute to related properties so they don't get included in the JSON:
public class Post
{
public int Id { get; set; }
public string Body { get; set; }
[ScriptIgnore]
public IList<Comment> Comments { get; set; }
}
This will make JSON serializer ignore the related property we won't edit in our details editor.
ToJson() extension code
The last thing to put here is extension method code so here it goes:
public static class ObjectExtensions
{
/// <summary>
/// Serializes this object instance to JSON string.
/// </summary>
/// <param name="instance">Object instance being extended.</param>
/// <returns>Returns a JSON string that represents current object instance.</returns>
public static string ToJson(this object instance)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
// register custom class converters
serializer.RegisterConverters(...);
return serializer.Serialize(instance);
}
/// <summary>
/// Serializes this object instance to JSON string.
/// </summary>
/// <param name="instance">Object instance being extended.</param>
/// <param name="recursionDepth">Serialization recursion limit depth.</param>
/// <returns>Returns a JSON string that represents current object instance.</returns>
public static string ToJson(this object instance, int recursionDepth)
{
JavaScriptSerializer serializer = new JavaScriptSerializer();
// register custom class converters
serializer.RegisterConverters(...);
serializer.RecursionLimit = recursionDepth;
return serializer.Serialize(instance);
}
}
What to do when entities are too complex?
Upper approach is useful when your entities aren't too complex. In cases when:
your entities are complex or have long data (long in terms of serialized string)
determining JSON objects for all items would be too time consuming
unknown JSON object at time of master list display
then you can always send a remote Ajax call to server for a single entity and return either
JSON object to use with dialog template
return partial view with editor
Second approach is better, since converting object instance to either HTML or JSON is practically similar task. but in the second case there's no need for client-side template processing.
But don't use remote requests just because you can. Use an approach that's easier and better for the problem at hand.
1: jQuery template API reference
I've seen it time and time again the typical answer being something like this:
public string RenderControlToHtml(Control ControlToRender)
{
System.Text.StringBuilder sb = new System.Text.StringBuilder();
System.IO.StringWriter stWriter = new System.IO.StringWriter(sb);
System.Web.UI.HtmlTextWriter htmlWriter = new System.Web.UI.HtmlTextWriter(stWriter);
ControlToRender.RenderControl(htmlWriter);
return sb.ToString();
}
... This is fine if you have simple html tags but when I have a textbox or some other asp control in my control it throws a wobbly about the control not being on a form (which in fact it is because im trying to render a portion of the page to a string that i can then send as an email)
So ...
I'm pretty sure this has been asked and answered before but i'm at a loss for finding a real answer that actually works ...
How do i render the html output of both server and client side controls to a html string in .Net 4.0 because seemingly the above is not good enough?
Note:
I have found examples that talk about doing this at page level ...
public override void VerifyRenderingInServerForm(Control control)
{
//Do nothing (we dont care if theres a form or not)
}
... and disabling event validation but apparently that's not working for me either.
Is there a way to do this without a "hack" thats clean?
Also:
I even tried creating a new page, adding a form to it, added my control to that then calling renderControl on that page to which i got more errors.
EDIT:
I've been digging around and I think the problem might be related to postbacks or something because i found this:
http://forums.asp.net/t/1325559.aspx
Another thing that might be putting a bit of a spanner in the works is my use of the ajax toolkit, I essentially need only the visible portion of the control which seems to give a bit of a headache for updatepanels for some reason.
I'm guessing the above sample works only on basic .net controls that are not ajax toolkit related.
What further complicates the issue is that I would like to get the control in its current state when a button is clicked at the bottom of it ...
Essentially the control represents a form for booking an MOT and I would like to render the form filled in to an email that is then sent to the garage if that makes sense.
I'm thinking i may have to admit defeat here and simply get the markup from the client and manually build an email pulling out the control values as this seems to be a compatability issue between ajax controls and the renderControl method from what i can tell (maybe you cant render a partial postback compatible control in this fashion).
Unless someone smarter than me can prove it can be done ???
Create an ajax control extender and get the html markup on the client side then post that back to the server for processing, it's a bit of hack but it seems that anything involving ajax controls will cause the default recommended mechanism to break.
I have some user controls that I want to add some client side functionality to.
Let say 1 control has a hidden field and a bunch of checkboxes. When a checkbox is checked, it sets the hidden field to 'YES'. How could I $get that control in the hosting control or page, and call some function on it that would return the value of that hidden field?
If I have a couple of these on the page, I'd like to be able to do this:
var choices1 = $get('choices1_id')
if(choices1.dirty() = 'YES')
//do whatever
var choices2 = $get('choices2_is')
if(choices2.dirty() = 'YES')
//do whatever
I might be looking for something like this: http://jimblackler.net/blog/?p=23 but I'm not sure how to access the object(s) from the parent.
thanks,
Mark
I take it the problem you are running into is that ASP.Net can mangle the id of the control?
In that case What I normally do is either note how the id is mangled for simple pages, and write the javascript accordingly, or for more complex scenarios I'll check the .ClientID property of each control and put it into variables in a custom script that's easily accessible to the rest of the javascript on the page.
This should be easier than it is, and not having simple access to every control element from javascript is one of my complaints with the ASP.Net framework. They're doing a little to address this in the next version, though not as much as they could. In the mean time, you can find various components on the web that will help automate generating the script I described above.
What's the best way to implement user controls that require AJAX callbacks?
I want to accomplish a few things:
Have events done in the browser (eg, drag and drop) trigger an AJAX notification that can raise a control event, which causes code on the page using the control to do whatever it needs to do (eg, change a value in a database).
Have partial updates (NOT using an updatepanel) that can do things like populate an auto-complete dropdown underneath a textbox.
Implement a single user control that is generic enough to be reused on several pages
Avoid having to implement logic on the page itself that passes events back to the control, because that is repetitive and hard to maintain
I'm using jQuery for most of the client side stuff, but for the actual AJAX calls I don't really care if it's jQuery or the ASP AJAX libraries.
Effectively what would be perfect is PageMethods on the user control, that would be easily callable from client-side script. Unfortunately, as far as I'm aware, pagemethods do not work on user controls.
I'll use an autocomplete control as an example:
I should be able to put the autocomplete control on the page, and then in the page code, have eg:
Public Sub HandleLookup(ByVal input As String, ByRef list As List(Of String) Handles MyControl.LookupEntries
list = New List(Of String)
' Query database for list of items..
For Each item as String in FullItemList
If item.StartsWith(input) then list.Add(item)
Next
Return list
End Sub
And do nothing else .. the rest of the code should be in the usercontrol.
Note, the controls I'm trying to make are much more specific than eg, autocomplete. They do not exist in any 3rd party libraries and I really need to be able to make them myself.
Look into implementing ICallbackEventHandler in your Page -- it's a simple way to make a call back to a page function from JavaScript.
Here's a good tutorial:
http://www.ajaxprojects.com/ajax/tutorialdetails.php?itemid=119
You might want to check out; Ra-Ajax UserControl Sample and combine that knowledge with Ra-Ajax Drag and Drop
Click the "Show code" C# icon to the left to see the usage of the code...