【问题标题】:ASP.NET MVC - Pass outer model to editor templateASP.NET MVC - 将外部模型传递给编辑器模板
【发布时间】:2013-04-16 16:11:10
【问题描述】:

我的大部分表单都使用自定义编辑器模板,但在尝试使用它们呈现自定义对象选择器时,我发现没有简单的方法将有关包含上下文的信息传递给编辑器模板。

具体来说,我的主表单呈现域对象的编辑,编辑器模板需要呈现一个 AJAX 选择器,其中包含依赖于域对象 ID 的对象列表。我目前使用additionalViewData 参数传递ID,我认为这很容易出错,因此非常难看。

我的表单包含类似于以下的代码:

@Html.EditorFor(model => model.CategoryId, new { id = model.id })

编辑器模板包含如下代码:

@{
var domainObjectId = ViewData["id"] as int?;
}

我正在使用自定义ModelMetadataProvider 来选择对象选择器编辑器模板,并希望使用类似的技术将有关包含模型的信息传递给编辑器模板,但这似乎是不可能的。

所以,我的问题是:

  1. 是否可以使用ModelMetadataProvider 将有关包含模型的信息传递给编辑器模板?
  2. 如果没有,除了通过弱类型 additionalViewData 参数传递每条附加信息之外,是否有任何更简洁/更简单的方法来实现我正在尝试的目标?

提前致谢!

【问题讨论】:

    标签: asp.net .net asp.net-mvc razor mvc-editor-templates


    【解决方案1】:

    您需要了解 EditorTemplate 的设计目的是特定于类型,而不是特定于上下文。使用 AdditionalViewData 参数对此进行了一些思考,但这是您将获得的最佳结果。

    如果您担心类型安全,请改用 ViewBag,它是 ViewData 的类型安全动态包装器。

    @{
        var domainObjectId = ViewBag.Id;
    }
    

    【讨论】:

    • 感谢您的回答。不幸的是,我认为您是对的,因为这是一种设计选择,但是如果它们具有上下文意识,它们只会更有用。我接受你的回答,但我想我会使用常规的部分而不是这些特定字段的编辑器模板,而不是 ViewBag 或类似的。
    • @IanNewson - 我不明白你不愿意使用 ViewBag,因为这正是它的设计目的。我称之为“表格布局心态”。人们了解到使用 html 表格进行布局是不好的,因此他们不再使用表格来处理所有内容,甚至是实际的表格数据(您会看到由 div 组成的表格)。同样,人们知道你应该使用 ViewModels 而不是 ViewData/Bag 并且即使它被用于它的设计目的时也要远离。
    • @IanNewson - 顺便说一下,如果你打算使用部分,你必须特别注意表单控件命名,以确保考虑到嵌套对象。 EditorTemplates 在很大程度上会为您解决这个问题。老实说,无论如何,我都不喜欢使用 EditorTemplates 进行下拉菜单。我也认为这会更好地在外部 javascript 文件中处理并改用数据属性。
    • 一般来说,我不会不情愿地使用 ViewBag,尽管出于两个原因,在这种情况下它不是最佳选择; 1)我正在创建一个可重用的组件,其中几个可能驻留在一个页面上,并且它们可能各自绑定到不同的域对象 2)我正在为其他开发人员创建一个框架,并且我认为显式的强类型性质在这种情况下,部分+扩展方法是可取的。
    • Id 唯一性已经得到处理。我很困惑为什么你说使用外部 JS 文件 + 下拉菜单会更好地处理,因为我认为我没有提到任何类似的实现细节?我的问题仅仅是关于将所需信息传递给需要它的视图,而不是在视图中对这些信息做了什么。
    【解决方案2】:

    我想知道创建这个视图模型的控制器是否应该是选择对象列表的东西。因此,与其在您的视图模型上拥有一个整数属性,您还可以拥有另一种类型的视图模型的子属性,即:

    public class OuterViewModel
    {
        public CategoryViewModel Category { get; set; }
    }
    
    public class CategoryViewModel
    {
        public int CategoryId { get; set; }
    
        public IEnumerable<SelectListItem> ListOfThings { get; set; }
    }
    

    那么你的原始视图可以有:

    @Html.EditorFor(model => model.Category)
    

    使用 CategoryViewModel 的 EditorTemplate,如下所示:

    @model CategoryViewModel
    @Html.DropDownFor(m => m.CategoryId, Model.ListOfThings)
    

    您唯一需要记住的是,如果您执行任何服务器端业务逻辑验证、添加模型错误并返回到您的视图,您将需要在控制器发布操作中重新填充您的事物列表。

    【讨论】:

    • 感谢您的回答。对于普通的select 或类似的我会同意你的看法,但在这种情况下,UI 小部件是通过 AJAX 调用填充的自定义选择器,包括搜索和分页。因此,我需要在 AJAX 调用期间传递生成列表服务器端所需的所有信息。这包括对象的 ID,以及其他一些变量,这是我需要传递给模板的信息。
    • 用一个 int 替换 IEnumerable,它是外部模型的 id,而不是渲染一个下拉列表,渲染你想要的任何东西?
    猜你喜欢
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 2015-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多