65.9K
CodeProject 正在变化。 阅读更多。
Home

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

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (3投票s)

2011年12月8日

CPOL

2分钟阅读

viewsIcon

24560

使用 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)。

优点

  1. 将所有或选定的字段发送到服务器。 最好的事情是它绑定到任何级别的模型 - 我可以在我的模型类中设置类对象的属性。 例如:Address.Street
  2. 使用相同的模型类进行GET/POST
  3. 您可能不需要 - 表单控件、提交按钮、元素的名称属性。 一个按钮元素足以触发JavaScript。
  4. 由于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适用于所有输入元素。 我测试了texttextareacheckboxradioselect元素。

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日:最初发布
© . All rights reserved.