1

我的应用程序有几个搜索框的页面。当用户单击相应的搜索按钮时,预计会加载结果网格。该网格几乎没有可编辑的控件,用户可以在其中修改并在需要时点击保存按钮来保存数据。

我们已经使用 AjaxForm 和局部视图实现了该功能。

  1. 包含搜索框和搜索按钮的搜索区域是使用 Ajax.BeginForm 创建的,在提交时从控制器调用回发搜索方法。SearchModel 被传递给这个方法。
  2. 创建部分视图以显示结果,并且步骤 1 中的 Ajax 表单从控制器回发方法成功加载它。SearchModel.Results 属性作为其模型传递给视图。
  3. 这个显示结果的部分视图有一个保存按钮(同样是一个 Ajax 表单),它调用控制器中的另一个方法,但在控制器中获取模型 null。

尝试了很多技巧,但都没有成功。任何工作示例在任何地方展示或建议使其工作?网络上有很多示例,其中解释了使用 AjaxForm 加载数据,但没有找到多个(或嵌套?)

提前致谢。

编辑 - 2月24日

这是我使用 Visual Studio 默认 MVC 模板创建的示例,它与上面解释的实际条件相似,并且在提交部分页面时存在相同的问题。

意见:

索引.cshtml

    @using MvcApplication1.Models
    @model SearchModel

    @{
        ViewBag.Title = "Home Page";
    }

     <script src="@Url.Content("~/Scripts/jquery.unobtrusive-ajax.min.js")" ></script>
    <h2>@ViewBag.Message</h2>
    <p>
        To learn more about ASP.NET MVC visit <a href="http://asp.net/mvc" title="ASP.NET MVC Website">http://asp.net/mvc</a>.
    </p>



@Ajax.BeginForm("Search", "Home", new AjaxOptions { HttpMethod = "Post", 
InsertionMode = InsertionMode.Replace,UpdateTargetId = "SearchResults"})
{
     <table>
    <tr>
        <td>
            First Name:
        </td>
        <td>
            @Html.TextBoxFor(m => m.SearchString)
        </td>
    </tr>
    <tr>
        <td colspan="2">
            <input type="submit" value="Submit" />
        </td>
    </tr>
</table>

}
<div id="SearchResults" style="color: Green;"></div>

部分视图 - _SearchResult.cshtml

    @using MvcApplication1.Models
    @model MvcApplication1.Models.SearchModel
    @{
        ViewBag.Title = "Result Partial";
    }
    <h2>
        testPartial</h2>
    @Ajax.BeginForm("SearchResult", "Home", new AjaxOptions
    {
        HttpMethod = "Post"
    })
    {
    <table>
        @foreach (ResultModel item in Model.Result)
        {
            <tr>
                <td>
                    Name:
                </td>
                <td>
                    @Html.DisplayFor(m => item.Name)
                </td>
            </tr>
            <tr>
                <td>
                    Address:
                </td>
                <td>
                    @Html.TextAreaFor(m => item.Address)
                </td>
            </tr>

        }
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
    }

楷模:

搜索模型.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    namespace MvcApplication1.Models
    {
        public class SearchModel
        {
            public string SearchString  { get; set; }

            public List<ResultModel> Result { get; set; }
        }
    }

结果模型.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;

    namespace MvcApplication1.Models
    {
        public class ResultModel
        {
            public string Name { get; set; }
            public string Address { get; set; }
        }
    }

控制器:

家庭控制器.cs

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Web;
    using System.Web.Mvc;
    using MvcApplication1.Models;

    namespace MvcApplication1.Controllers
    {
        public class HomeController : Controller
        {
            public ActionResult Index()
            {
                ViewBag.Message = "Welcome to ASP.NET MVC!";

                return View();
            }

            public ActionResult About()
            {
                return View();
            }

            [HttpPost]
            public ActionResult Search(SearchModel model)
            {
                //dummy search for result
                List<ResultModel> result = new List<ResultModel>();

                ResultModel res1 = new ResultModel();
                res1.Name = model.SearchString + " 1";
                res1.Address = "Dummy address";

                result.Add(res1);

                ResultModel res2 = new ResultModel();
                res2.Name = model.SearchString + " 2";
                res2.Address = "Rummy address";

                result.Add(res2);

                //assign seach results to model
                model.Result = result;

                return PartialView("_SearchResult", model);
            }

            [HttpPost]
            public ActionResult SearchResult(SearchModel model)
            {
                //do something with results

                List<ResultModel> res = model.Result; // null here !!

                return RedirectToAction("Index");
            }
        }
    }

所以,上面的样本将

  1. 在主页上显示一个搜索框 - Index.cshtml
  2. 当您单击提交时,它将加载一个部分视图,在搜索下方显示结果
  3. 当您编辑搜索结果并在结果表单上点击提交时,请在那里设置一个断点,您将看到返回的模型为空。

希望,这可以解释我的问题。

4

1 回答 1

1

现在您已经用一个完整的示例展示了您的实际代码,您的问题可以得到回答。

您得到的原因null是因为您没有遵守默认模型绑定器期望的输入字段的标准命名约定。请阅读following articlePhil Haack 的文章以熟悉这些约定。

您的代码的问题在于您foreach在部分内部使用循环来呈现结果,而不是使用编辑器模板。因此,将您的代码替换_SearchResult.cshtml为以下内容:

@using MvcApplication1.Models
@model SearchModel
@{
    ViewBag.Title = "Result Partial";
}
<h2>testPartial</h2>

@using(Ajax.BeginForm("SearchResult", "Home", new AjaxOptions()))
{
    <table>
        @Html.EditorFor(x => x.Result)
        <tr>
            <td colspan="2">
                <input type="submit" value="Submit" />
            </td>
        </tr>
    </table>
}

然后为该ResultModel类型定义一个自定义编辑器模板(~/Views/Shared/EditorTemplates/ResultModel.cshtml- 警告,编辑器模板的名称和位置很重要,因为它按约定工作):

@using MvcApplication1.Models
@model ResultModel

<tr>
    <td>
        Name:
    </td>
    <td>
        @Html.DisplayFor(m => m.Name)
        @Html.HiddenFor(m => m.Name)
    </td>
</tr>
<tr>
    <td>
        Address:
    </td>
    <td>
        @Html.TextAreaFor(m => m.Address)
    </td>
</tr>

注意事项:

  • 我已经将Ajax.BeginForm助手包装在一个using声明中。你应该在你的Index.cshtml视图中做同样的事情
  • 我在自定义编辑器模板@Html.HiddenFor(m => m.Name)(到你的服务器。
于 2013-02-24T13:46:29.763 回答