当前位置: 首页 > 面试题库 >

通过Ajax加载和模型更新的ASP.Net MVC2自定义模板

计和顺
2023-03-14
问题内容

我有一个视图模型,其中包含其他对象的集合。

public ParentViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<ChildViewModel> Child { get; set; } 
}

public ChildViewModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

在我的一种视图中,我传入ParentViewModel作为模型,然后使用

<%: Html.EditorFor(x => x) %>

其中显示Id和Name属性的表单。

当用户单击一个按钮时,我通过Ajax调用一个操作以加载带有Child集合的局部视图:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<IEnumerable<Child>>" %>
<%: Html.EditorFor(x => x) %>

然后使用自定义模板Child来显示每个传入的Child的表单。

我遇到的问题是,Child自定义模板创建的表单未使用DefaultModelBinder使用的命名约定。

即字段名称是(当由Ajax加载时):

[0].FirstName

代替:

Child[0].FirstName

因此,在我的控制器中执行Edit操作:

[HttpPost]
public virtual ActionResult Edit(int id, FormCollection formValues)
{
    ParentViewModel parent = new ParentViewModel();
    UpdateModel(parent);

    return View(parent);
}

从提交的表单重新创建ParentViewModel无效。

我想知道通过Ajax完成在Custom Templates中加载然后能够使用UpdateModel的最佳方法是什么。


问题答案:

首先要注意的是,您需要记住默认的ModelBinder是递归的,它将尝试找出需要做的事情……非常聪明。要记住的另一件事是,您 不需要
使用html帮助器,实际的html也可以正常工作:-)

因此,首先使用模型,这里没有什么不同。

public class ParentViewModel
{
    public int Id { get; set; }
    public string Name { get; set; }
    public List<ChildViewModel> Child { get; set; }
}

public class ChildViewModel
{
    public int Id { get; set; }
    public string FirstName { get; set; }
}

父局部视图 -这需要ParentViewModel的一个实例

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ParentViewModel>" %>

<h2>Parent</h2>
<%: Html.TextBox("parent.Name", Model.Name) %>
<%: Html.Hidden("parent.Id", Model.Id) %>

<% foreach (ChildViewModel childViewModel in Model.Child)
{
    Html.RenderPartial("Child", childViewModel);         
}
%>

子局部视图 -这需要ChildViewModel 的 单个 实例

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl<ChildViewModel>" %>

<h3>Child</h3>
<%: Html.Hidden("parent.Child.index", Model.Id) %>
<%: Html.Hidden(string.Format("parent.Child[{0}].Id", Model.Id), Model.Id)%>
<%: Html.TextBox(string.Format("parent.Child[{0}].FirstName", Model.Id), Model.FirstName) %>

此时要注意的一点是,索引值是用于计算列表中唯一记录的值。这不必是增量值。

那么,你怎么称呼它呢?在Index操作中,它将显示需要传递的数据。我已经设置了一些演示数据,并将其在ViewData字典中返回给索引视图。

所以控制器动作…

public ActionResult Index()
{
    ViewData["Message"] = "Welcome to ASP.NET MVC!";

    ViewData["Parent"] = GetData();

    return View();
}

private ParentViewModel GetData()
{
    var result = new ParentViewModel
                     {
                         Id = 1,
                         Name = "Parent name",
                         Child = new List<ChildViewModel>
                                     {
                                         new ChildViewModel {Id = 2, FirstName = "first child"},
                                         new ChildViewModel {Id = 3, FirstName = "second child"}
                                     }
                     };
    return result;
}

在现实世界中,您会打电话给数据服务等。

最后是索引视图的内容:

<form action="<%: Url.Action("Edit") %>" method="post">
    <% if (ViewData["Parent"] != null)  { %>

        <%
            Html.RenderPartial("Parent", ViewData["Parent"]); %>

    <% } %>
    <input type="submit" />
</form>

保存

因此,现在我们已经显示了数据,我们如何将其恢复为动作?好的,这是默认模型联编程序将针对相对复杂形式的简单数据类型为您执行的操作。因此,您可以将要发布的操作的基本格式设置为:

[HttpPost]
public ActionResult Edit(ParentViewModel parent)
{

}

这将为您提供具有原始ID(来自隐藏字段)的更新的详细信息,以便您可以根据需要进行更新/编辑。

新孩子通过阿贾克斯

您在通过ajax加载自定义模板中的问题中提到过,您的意思是如何为用户提供添加另一个孩子而无需回发的选项?

如果是这样,您可以执行以下操作…

添加操作 -需要一个操作,该操作将返回一个新的ChildViewModel

[HttpPost]
public ActionResult Add()
    {
        var result = new ChildViewModel();
        result.Id = 4;
        result.FirstName = "** to update **";
        return View("Child", result);
    }

为了方便演示,我给了它一个id。

然后,您需要一种调用代码的方法,因此唯一需要更新的视图是主索引视图。这将包括用于获取操作结果的javascript,用于调用代码的链接以及要附加到html的目标HTML标记。另外,不要忘记在母版页或视图顶部添加对jQuery的引用。

索引视图-已更新!

<script type="text/javascript">

   function add() {

        $.ajax(
            {
                type: "POST",
                url: "<%: Url.Action("Add", "Home") %>",
                success: function(result) {
                    $('#newchild').after(result);
                },
                error: function(req, status, error) {

                }
        });
    }

</script>

<form action="<%: Url.Action("Edit") %>" method="post">
    <% if (ViewData["Parent"] != null)  { %>

        <%
            Html.RenderPartial("Parent", ViewData["Parent"]); %>

    <% } %>
    <div id="newchild"></div>

    <br /><br />
    <input type="submit" /> <a href="#" onclick="JavaScript:return add();">add child</a>
</form>

这将调用添加操作,并在返回到提交按钮上方的newChild div时追加响应。

我希望这篇长文章有用。

请享用 :-)



 类似资料:
  • 问题内容: 我已经创建了自己的NER模型与斯坦福大学“斯坦福大学NER”软件,并按照这些方向。 我知道CoreNLP按照以下顺序开箱即用地加载了三个NER模型: 我现在想将我的NER模型包括在上面的列表中,并先用NER模型标记文本。 我已经找到了关于该主题的两个以前问题,它们是“使用自定义NER模型的Stanford OpenIE[”和“为什么Stanford CoreNLP NER注释器默认加载

  • null 我发现了之前关于这个主题的两个StackOverflow问题,它们是“Stanford OpenIE使用定制的NER模型”和“为什么Stanford CoreNLP NER-annotator默认加载3个模型?” 这两个帖子都有很好的答案。答案的一般信息是,您必须在文件中编辑代码。 使用自定义NER模型的斯坦福OpenIE 是否需要修改或添加此代码到CoreNLP软件中的特定类文件中?

  • 问题内容: 在Keras中,如果您需要自定义损失以及其他参数,我们可以像https://datascience.stackexchange.com/questions/25029/custom- loss-function-with-additional-parameter-in- 凯拉斯 当我训练模型时,上述方法有效。但是,一旦训练了模型,我将很难加载模型。当我尝试在load_model中使用c

  • 如果您是一位经验丰富的ML开发人员,而且ML Kit的预训练的模型不能满足您的需求,您可以通过ML Kit使用定 的TensorFlow Lite模型。 使用Firebase托管您的TensorFlow Lite模型或将其与您的应用程序打包在一起。然后,使用ML Kit SDK来使用您的自定义模型的最佳版本构建应用。如果您使用Firebase托管您的模型,ML Kit会自动更新您的用户的所用版本。

  • 本文向大家介绍seaJs的模块定义和模块加载浅析,包括了seaJs的模块定义和模块加载浅析的使用技巧和注意事项,需要的朋友参考一下 SeaJS 是由玉伯开发的一个遵循 CommonJS 规范的模块加载框架,可用来轻松愉悦地加载任意 JavaScript 模块和css模块样式。SeaJS非常小巧,小巧在于压缩和gzip后体积只有4K,而且接口和方法也非常少,SeaJS 就两个核心:模块定义和 模块的

  • 问题内容: 我有一个带有开始和结束日期范围的Django模型。我想强制执行验证,以便没有两个记录具有重叠的日期范围。最简单的实现方式是什么,这样我就不必重复编写逻辑了? 例如,我不想在Form 和 a 以及 admin表单中重新实现此逻辑, 并且 模型被重写。 据我所知,Django在全球范围内强制执行这些类型的条件并不容易。 Googling并不是很有帮助,因为“模型验证”通常是指验证特定的模型