使用 MVC3 和 AJAX 为现有 HTML 创建回发模型对象






4.33/5 (3投票s)
使用 MVC3 和 AJAX 为现有 HTML 创建回发模型对象
引言
将页面数据更改作为模型对象postback到MVC3环境中的控制器动作方法。同一个模型类可以用于GET
/POST
操作。
此示例使用Visual Studio 2010和MVC3 Razor, jquery-1.4.2。
我觉得VS2010中的MVC3不仅仅是架构上的改变,它在视图、控制器或模型编码方面给予了开发人员更大的自由度,同时也有其优势。
背景
任何MVC3视图(屏幕)的基本要求是填充“模型”,然后在postback时将更改作为模型(数据类)或表单字段发送到服务器。
如果开发人员从头开始,这并不痛苦,因为HtmlHelper
或脚手架总是可用来绑定模型和创建HTML元素。
尽管如此,这种技术也可以用于从头创建的新视图。
但是,当您有一个HTML文件并希望将其转换为使用模型进行get
/post
操作的MVC3视图时,这很困难且令人困惑。
在我的项目中,一组人将现有的经典ASP转换为纯HTML(实际上是.cshtml),并带有所有必需的样式。 我们必须在MVC3环境中使用它们来绑定我们在另一组人将ASP转换为HTML时已经创建的模型。
这是一个3步技术! - 创建一个JavaScript函数,在cshtml中绑定和设置类名,并创建模型动作方法(GET
/POST
)。
优点
- 将所有或选定的字段发送到服务器。 最好的事情是它绑定到任何级别的模型 - 我可以在我的模型类中设置类对象的属性。 例如:
Address.Street
。 - 使用相同的模型类进行
GET
/POST
。 - 您可能不需要 - 表单控件、提交按钮、元素的名称属性。 一个按钮元素足以触发JavaScript。
- 由于AJAX,没有页面闪烁(刷新)。
Using the Code
步骤 - 1
将一个class属性添加到您希望作为model
属性postback的cshtml元素。 Model
属性是您model
类中的一个public get
/set
方法。 类值为"prefixModelProperty
"。 例如:prefix = “ModPrfx-“ ; ModelProperty=”Address.Street”
。
<div id="divParent">
<input type="text" class="textcls ModPrfx-Address.Street"
value="@Model.Address.Street" id="txtSt"/>
<input type="checkbox" class="ModPrfx-IsManager" id="chk"/>Is Manager
<input type="text" class="textcls ModPrfx-Name" value="@Model.Name" id="txtNm"/>
@Html.DropDownList("ddlState", new SelectList(Model.States, "State", "State",
Model.Address.State), "", new { @class = "ModPrfx-Address.State" })
<input type="button" value="Save" id="btnSave"/>
</div>
<div id="divGen">
Male:<input type="radio" name="gender" class="ModPrfx-Gender" value="1"/>
Female:<input type="radio" name="gender" class="ModPrfx-Gender" value="2"/>
</div>
步骤 - 2
将JavaScript函数注册到保存按钮。 这将调用控制器中的“Employee
”方法。 SerializeForAjax()
接受三个参数。 第一个是父控件,接下来是前缀,最后一个是已填充的JSON对象(可选)。
$(document).ready(function () {
$("#btnSave").click(function (e) {
e.preventDefault();
$.ajax({
url: <a href="mailto:'@Url.Action(%22Employee%22)'">'
@Url.Action("Employee")'</a>,
type: 'post',
dataType: 'json',
data: SerializeForAjax('divParent','ModPrfx-',
SerializeForAjax('divGen','ModPrfx-')),
success: function (data) {
if (data && data.error) {
alert(data.error);
}
}});});});
步骤 - 3
在控制器类中定义Employee GET
/POST
方法。
//[HttpGet]
public ActionResult Employee()
{
Employee model = new Employee();
model.Load(Session);
return View(model);
}
[HttpPost]
public ActionResult Employee(Employee model)
{
//we do not want non-ajax access to this method
if(!Request.IsAjaxRequest())
return Json(""); //or send to error page
object results = model.Save(Session,User.Identity.Name);
return Json(results);
}
//The sample model class looks like this:
public class Employee
{
public EmpAddress Address { get; set; }
public bool IsManager { get; set; }
public string Name { get; set; }
public int Gender { get; set; }
public void Load(HttpSessionStateBase session) {..}
public object Save(HttpSessionStateBase session, string user) {..}
…….
}
public class EmpAddress
{
public string Street { get; set; }
public string State { get; set; }
}
SerializeForAjax()
是将HTML元素的数据序列化为JSON对象以发送到服务器的主要JavaScript方法。 SerializeForAjax
适用于所有输入元素。 我测试了text
、textarea
、checkbox
、radio
和select
元素。
function SerializeForAjax(prntCtrlId, modelFieldPrefix,jsonObj) {
var mdlFldWord = arguments.length == 1 ? "model-field-" : modelFieldPrefix;
var jsonData = !jsonObj ? {} : jsonObj;
var testData = "", modelFld = "";
$("#" + prntCtrlId + " [class*=" + mdlFldWord + "]").each(function (index, value) {
var classes = this.className.split(" "); //what if multiple classes exist
for (var i = 0; i < classes.length; i++) {
if (classes[i].indexOf(mdlFldWord) == 0) {
modelFld = classes[i].substring(mdlFldWord.length);
break;
}
}
var dataVal, dataOk = true;
if ($(this).is(':text')) {
//if you store the unformatted data) to be saved/sent to server
//can be stored into object. ex: i have text ctrl id="txtPhn" then
//you have to save rawdata as $("#txtPhn").data("txtPhn","1234567890")
//but you display as (123)-456-7890.
dataVal = !$(this).data(this.id) ? this.value : $(this).data(this.id);
}
//checkbox
else if ($(this).is(':checkbox')) {
dataVal = this.checked;
}
//radio button
else if ($(this).is(':radio')) {
dataVal = this.checked ? $(this).val() : "";
//store data only when rb is checked
dataOk = this.checked;
}
//for ddl or combo box handling
else if ($(this).is('select')) {
var tdata = $(this).val();
//if single select
if (tdata && typeof tdata == 'string') {
dataVal = tdata;
}
else { //multiselect
for (var i = 0; tdata && i < tdata.length; i++) {
dataVal = (dataVal) ? (dataVal + "," + tdata[i]) : tdata[i];
}
}
} //if its other than above objects. (ex:button,file,hidden,
//image,password,reset,sumit)
else {
dataVal = $(this).val();
}
if (dataOk) {
//if you want to separate object & method with - instead ' in class attribute value
if (modelFld.indexOf("-") > -1) {
modelFld = modelFld.replace("-", ".");
}
jsonData[modelFld] = dataVal;
//testData = testData + modelFld + "=" + dataVal + "\n"
}
});
//alert(testData);
return jsonData;
}
关注点
您可以扩展SerializeForAjax()
以实现用户的验证回调(开发人员)。
历史
- 2011年12月8日:最初发布