I'm running through some basic web page development and have came across something and I don't know how to proceed.
I have two Actions; one that returns a Customer object as JSON, used in a jQuery Ajax call, and an Action that should accept a Customer object to save it. Here is the Customer object (model).
public class Customer
{
public string Name { get; set; }
public Address Address { get; set; }
}
public class Address
{
public string Street { get; set; }
}
Basic stuff.
Here now are the Actions.
public JsonResult GetCustomer()
{
Customer customer = new Customer
{
Name = "Microsoft",
Address = new Address { Street = "Redmond" }
};
return Json(customer, JsonRequestBehavior.AllowGet);
}
public void SaveCustomer(Customer customer)
{
// intentionally left blank
}
In the HTML page I call the GetCustomer Action using jQuery.getJSON method, fired by a button click, and display the Customer in input fields.
And it all works nice. Now I want to edit the details and submit a jQuery.post call to update the record but the problem is the customer object no longer exists on the client side and it were, as it could be made to, it would be out of date as all edits
exist only in the input controls.
Question is how can I take the edits made in the input controls and use them to re-create a Customer object that can then be sent to the SaveCustomer event?
Is there data binding in ASP.MVC?
Any advice? I'm a bit new to this approach to web development and I'm a bit out of my comfort zone; which is awesome.
p.s I know that the customer object can be created using code similar to this
customer {
name = $('#textName').val;
}
and that's fine for this example but what if the Customer object was much more complex; I'd rather not take this approach as eventually I will be working with a very complex object.
An example is extracted from my task management application.... the point of interest here is JSON.stringify(object) method which converts a json object into string.
Call ajax from your button click and replace task with customer object.
// Build the JSON object to pass to the controller action
var task = {
Title: $("#Title").val(),
Description: $("#Description").val(),
Owner: $("#Owner").val()
};
$.ajax({
url: "/task/updatetask",
type: "POST",
data: JSON.stringify(task),
dataType: "json",
contentType: "application/json; charset=utf-8",
success: function (e) {
$("#message").html("Success");
},
error: function (xhr, status, error) {
// Show the error
$('#message').html(xhr.responseText);
}
});
I blog at http://rajeshpillai.net and have a community startup http://ownabook.org/
(Don't forget to click "Mark as Answer" on the post(s) that helped you.)
One approach would be to just build the same shaped object in JavaScript, populate it from your input fields, serialize it to JSON and then send it to the server with Ajax.
var name = $("#textName").val();
var street = $("#textStreet").val();
var object = {Name: name, Address : {Street: street }};
$.ajax({
url: 'YourController/SaveCustomer' // server endpoint
type : "POST", // POST HTTP verb since you're doing an update
data : JSON.stringify(object), // serialized JSON -- this should map onto your Customer object with model binding in MVC
contentType:'application/json', // tell the server that you're sedning JSON
dataType : "json", // this is the expected format of the response body
success : function(result) { // success callback -- result will be the deserailized JSON object from the response body
You replied as I updated the original post. I was aware of that approach but the reason I want an alternative is the Customer object could be much more complex.
In fact the idea was to use what I learned from this exercise and apply it to a very very complex object; and I don't really want to build the complex object on the client this way if I can help it.
A lot of code that needs to change if the objects design changes.
I'm kind of looking for a data binding approach where the Customer object would exist on the client and bound to the controls; edits on the controls would update the original object... and then that object could used with the ajax post code above really
easy.
Someone just posted the same advice. The example is small and doesn't really show the problem. Imagine that the customer was more complex then the need to rebuild the object on the client becomes a pain.
Is there any other approach? Something like data binding where the object can remain on the client and edits on the input controls automatically update the in memory object.
An another easier approach would be to write a simple function which binds the information from form automatically....
like...
(extracted from my sample app)
function bindFormData(formId, jData) {
debug("");
$.each(jData, function (fieldName, val) {
debug("Field : " + fieldName + "=>" + val);
var $formField = $("#" + fieldName);
if ($formField.is(":checkbox")) {
$formField.attr("checked", val);
$formField.attr("value", val);
}
if ($formField.is(":radio")) {
$formField.attr("checked", val);
}
if ($formField.is(":text") || $formField.is("select") || $formField.is(":hidden")) {
if ($formField.attr("data-type") === "date" || $formField.hasClass("date")) {
if (val !== null) {
$formField.val(val.parseDate() || "");
}
else {
$formField.val("");
}
}
else {
if (val === undefined || val === null) {
$formField.val("");
}
else {
$formField.val(val);
}
}
}
});
}
This is a reusable funtion which could be bound to any json data, given the form id.
You may modify this as required....
Similarly, you can write a getObject function which gets you the required object based on formId parameters.....
I know this is getting too complicated, and I will wait for responses from others on this as well...
I blog at http://rajeshpillai.net and have a community startup http://ownabook.org/
(Don't forget to click "Mark as Answer" on the post(s) that helped you.)
Someone just posted the same advice. The example is small and doesn't really show the problem. Imagine that the customer was more complex then the need to rebuild the object on the client becomes a pain.
Is there any other approach? Something like data binding where the object can remain on the client and edits on the input controls automatically update the in memory object.
On a side note, big shouts to DevelopMentor!
Ok, so if you're interested and willing to take on a more sophisticated approach the consider using
Knockout.js. It's basically a MVVM framework for JavaScript. It's quite cool and I think will be exactly what you're looking for.
1) mvc object binding to form elements. in the case the name of the field is path to bind to in the server object. use the html helpers ...For to produce the correct name. the use $('form').serialize() to produce a form post that bind to a complex view
model.
in your case name street <input name="Address.Street" ...>
2) use a client side MVC pattern. here you use an observable object client side that is a proxy to controler json actions. backbone.js is the one in moe current MVC templates but ther are other toolkits.
This is a form to json library, and may help avoid the tediousness of building json manually.... Do check whether this is useful to you...
I blog at http://rajeshpillai.net and have a community startup http://ownabook.org/
(Don't forget to click "Mark as Answer" on the post(s) that helped you.)
dsmyth
Member
31 Points
11 Posts
Ajax POST of Complex object to MVC Action
Mar 20, 2012 02:50 PM|LINK
Hi Everyone, really need your help.
I'm running through some basic web page development and have came across something and I don't know how to proceed.
I have two Actions; one that returns a Customer object as JSON, used in a jQuery Ajax call, and an Action that should accept a Customer object to save it. Here is the Customer object (model).
public class Customer { public string Name { get; set; } public Address Address { get; set; } } public class Address { public string Street { get; set; } }Basic stuff.
Here now are the Actions.
public JsonResult GetCustomer() { Customer customer = new Customer { Name = "Microsoft", Address = new Address { Street = "Redmond" } }; return Json(customer, JsonRequestBehavior.AllowGet); } public void SaveCustomer(Customer customer) { // intentionally left blank }In the HTML page I call the GetCustomer Action using jQuery.getJSON method, fired by a button click, and display the Customer in input fields.
<%@ Page Title="" Language="C#" MasterPageFile="~/Views/Shared/Site.Master" Inherits="System.Web.Mvc.ViewPage" %> <asp:Content ID="Content1" ContentPlaceHolderID="TitleContent" runat="server"> Customer Records </asp:Content> <asp:Content ID="Header" ContentPlaceHolderID="HeaderContent" runat="server"> <script type="text/javascript"> $(document).ready( function() { $('#buttonGet').click(click); }); function click() { $.getJSON("Customer/GetCustomer", null, display); } function display(customer) { $('#textName').val(customer.Name); $('#textStreet').val(customer.Address.Street); } </script> </asp:Content> <asp:Content ID="Main" ContentPlaceHolderID="MainContent" runat="server"> <input type="text" id="textName" /> <br /> <input type="text" id="textStreet" /> <br /> <input id="buttonGet" type="button" value="Get" /> </asp:Content>And it all works nice. Now I want to edit the details and submit a jQuery.post call to update the record but the problem is the customer object no longer exists on the client side and it were, as it could be made to, it would be out of date as all edits exist only in the input controls.
Question is how can I take the edits made in the input controls and use them to re-create a Customer object that can then be sent to the SaveCustomer event?
Is there data binding in ASP.MVC?
Any advice? I'm a bit new to this approach to web development and I'm a bit out of my comfort zone; which is awesome.
p.s I know that the customer object can be created using code similar to this
customer {
name = $('#textName').val;
}
and that's fine for this example but what if the Customer object was much more complex; I'd rather not take this approach as eventually I will be working with a very complex object.
thinkrajesh
Participant
1356 Points
232 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 02:56 PM|LINK
// Build the JSON object to pass to the controller action var task = { Title: $("#Title").val(), Description: $("#Description").val(), Owner: $("#Owner").val() }; $.ajax({ url: "/task/updatetask", type: "POST", data: JSON.stringify(task), dataType: "json", contentType: "application/json; charset=utf-8", success: function (e) { $("#message").html("Success"); }, error: function (xhr, status, error) { // Show the error $('#message').html(xhr.responseText); } });(Don't forget to click "Mark as Answer" on the post(s) that helped you.)
BrockAllen
All-Star
27544 Points
4907 Posts
MVP
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 02:59 PM|LINK
One approach would be to just build the same shaped object in JavaScript, populate it from your input fields, serialize it to JSON and then send it to the server with Ajax.
var name = $("#textName").val();
var street = $("#textStreet").val();
var object = {Name: name, Address : {Street: street }};
$.ajax({
url: 'YourController/SaveCustomer' // server endpoint
type : "POST", // POST HTTP verb since you're doing an update
data : JSON.stringify(object), // serialized JSON -- this should map onto your Customer object with model binding in MVC
contentType:'application/json', // tell the server that you're sedning JSON
dataType : "json", // this is the expected format of the response body
success : function(result) { // success callback -- result will be the deserailized JSON object from the response body
}
});
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
dsmyth
Member
31 Points
11 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:04 PM|LINK
Hi thinkrajesh,
Thanks for taking the time to reply.
You replied as I updated the original post. I was aware of that approach but the reason I want an alternative is the Customer object could be much more complex.
In fact the idea was to use what I learned from this exercise and apply it to a very very complex object; and I don't really want to build the complex object on the client this way if I can help it.
A lot of code that needs to change if the objects design changes.
I'm kind of looking for a data binding approach where the Customer object would exist on the client and bound to the controls; edits on the controls would update the original object... and then that object could used with the ajax post code above really easy.
Any ideas how that could be done?
BrockAllen
All-Star
27544 Points
4907 Posts
MVP
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:07 PM|LINK
You can simply accept a different object in your Save method -- the only requirement is that the submitted JSON match the shape (as in duck typing).
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
dsmyth
Member
31 Points
11 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:08 PM|LINK
Thanks BrockAllen,
Someone just posted the same advice. The example is small and doesn't really show the problem. Imagine that the customer was more complex then the need to rebuild the object on the client becomes a pain.
Is there any other approach? Something like data binding where the object can remain on the client and edits on the input controls automatically update the in memory object.
On a side note, big shouts to DevelopMentor!
thinkrajesh
Participant
1356 Points
232 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:12 PM|LINK
@dsmyth
-------------
Yes there are alternatives, but it may get too complex for this scenario..
NOTE: The below code is just for reference and you may ignore and wait for other better responses....
Checkout http://knockoutjs.com/ (this has two way binding between view and js model)...
An another easier approach would be to write a simple function which binds the information from form automatically....
like...
(extracted from my sample app)
function bindFormData(formId, jData) { debug(""); $.each(jData, function (fieldName, val) { debug("Field : " + fieldName + "=>" + val); var $formField = $("#" + fieldName); if ($formField.is(":checkbox")) { $formField.attr("checked", val); $formField.attr("value", val); } if ($formField.is(":radio")) { $formField.attr("checked", val); } if ($formField.is(":text") || $formField.is("select") || $formField.is(":hidden")) { if ($formField.attr("data-type") === "date" || $formField.hasClass("date")) { if (val !== null) { $formField.val(val.parseDate() || ""); } else { $formField.val(""); } } else { if (val === undefined || val === null) { $formField.val(""); } else { $formField.val(val); } } } }); }Similarly, you can write a getObject function which gets you the required object based on formId parameters.....
I know this is getting too complicated, and I will wait for responses from others on this as well...
(Don't forget to click "Mark as Answer" on the post(s) that helped you.)
BrockAllen
All-Star
27544 Points
4907 Posts
MVP
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:13 PM|LINK
Ok, so if you're interested and willing to take on a more sophisticated approach the consider using Knockout.js. It's basically a MVVM framework for JavaScript. It's quite cool and I think will be exactly what you're looking for.
And thx for the shout out :)
DevelopMentor | http://www.develop.com
thinktecture | http://www.thinktecture.com/
bruce (sqlwo...
All-Star
36852 Points
5446 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:18 PM|LINK
there are two approaches.
1) mvc object binding to form elements. in the case the name of the field is path to bind to in the server object. use the html helpers ...For to produce the correct name. the use $('form').serialize() to produce a form post that bind to a complex view model.
in your case name street <input name="Address.Street" ...>
2) use a client side MVC pattern. here you use an observable object client side that is a proxy to controler json actions. backbone.js is the one in moe current MVC templates but ther are other toolkits.
thinkrajesh
Participant
1356 Points
232 Posts
Re: Ajax POST of Complex object to MVC Action
Mar 20, 2012 03:19 PM|LINK
Try this
http://code.google.com/p/form2js/
This is a form to json library, and may help avoid the tediousness of building json manually.... Do check whether this is useful to you...
(Don't forget to click "Mark as Answer" on the post(s) that helped you.)