Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Commonly-accepted approach in MVC for form within jQuery dialog

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.

  1. 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.
  2. 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.
  3. [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.
  4. 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!

like image 312
mikemanne Avatar asked Oct 13 '11 19:10

mikemanne


2 Answers

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.

like image 119
Scott Rippey Avatar answered Oct 15 '22 13:10

Scott Rippey


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.

like image 21
Paul Tyng Avatar answered Oct 15 '22 12:10

Paul Tyng