Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/268.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在ASP.NET MVC中处理来自不同部分的操作复杂视图模型_C#_Asp.net Mvc - Fatal编程技术网

C# 如何在ASP.NET MVC中处理来自不同部分的操作复杂视图模型

C# 如何在ASP.NET MVC中处理来自不同部分的操作复杂视图模型,c#,asp.net-mvc,C#,Asp.net Mvc,我有一个复杂的表单,具有视图模型的层次结构,我想知道如何构造代码,以便我的控制器不会包含所有操作的处理程序 以下是一个简化的示例: 使用相应的ViewModel: 公共类MyPageViewModel { 公共列表选项卡{get;set;} 公共客户服务模型客户; } 公共类TabViewModel { 公共字符串DisplayLabel{get;set;} 已选择公共布尔值{get;set;} } 类CustomerViewModel { 公共字符串名{get;set;} 公共字符串Last

我有一个复杂的表单,具有视图模型的层次结构,我想知道如何构造代码,以便我的控制器不会包含所有操作的处理程序

以下是一个简化的示例: 使用相应的ViewModel:

公共类MyPageViewModel
{
公共列表选项卡{get;set;}
公共客户服务模型客户;
}
公共类TabViewModel
{
公共字符串DisplayLabel{get;set;}
已选择公共布尔值{get;set;}
}
类CustomerViewModel
{
公共字符串名{get;set;}
公共字符串LastName{get;set;}
公共列表地址{get;set;}
}  
公共课堂演讲
{
公共字符串Street{get;set;}
公共字符串City{get;set;}
}
我知道如何在单独的组件中单独呈现页面的每个部分:我正在使用
@Html.EditorFor
@Html.DisplayFor
,并且模型的每个部分都有一个单独的视图(由上图中的红色矩形指示)。这个很好用。ViewModel的某些部分(例如
选项卡ViewModel
类)也可以在其他页面上重复使用

我在事件处理逻辑方面有问题。此页面上可以执行的操作很少(以蓝色背景表示)。一种可能是使用多个表单标签——每个标签对应上图中的一个红色矩形。每个表单都有不同的操作URL,并由不同的控制器处理。但使用这种方法时,我可能会丢失相同的数据。例如:如果用户更改了名字,然后单击“删除地址”按钮,那么名字将不会发回服务器,更改将丢失

这就给了我整页一张表格。这意味着所有操作都应该由单个控制器类处理。我真的不喜欢这种方法,因为:

  • 我将最终得到一个大而胖的控制器,它包含所有按钮的操作处理代码
  • 或者在我的控制器中有一个大的switch语句,它将识别动作,定位单独的类,知道如何处理动作,然后将处理委托给它(糟糕!这听起来像是在20世纪90年代编写windows消息事件处理代码–WindowProc)
我读过关于Html.ActionFor的文章,它使您能够从视图中调用单独的控制器,但我认为这也不是一个好方法(它发生在视图渲染时,这是不好的)

总之,这里再次提出了一个问题:是否有一种方法可以处理复杂视图模型不同部分触发的操作/事件,从而不会在控制器中造成混乱?对于实际应用程序,最佳做法是什么(不是由Visual studio脚手架生成的101个CRUD示例)

更新:请注意,这只是一个简化的示例-在现实中,视图模型要复杂得多,可以执行的操作也更多。我想问一下在controller中构造代码的一般方法(或将其移动到单独的类中)在ASP.NET MVC应用程序中。WebForms提供了用户控件,这使我们能够封装视图部分(ASCX)和事件处理程序。MVC有一个很好的封装视图的解决方案,我正在尝试找到正确的方法来构造逻辑/事件处理程序。

我将添加一个“保存”按钮设置客户数据字段,并在用户点击保存按钮时保存/发布所有客户数据。这样,在编辑发布操作中,您将只使用
CustomerServiceWModel

“添加新地址”和“删除此地址”将使用javascript添加和删除
地址所需的html

“搜索现有客户”和“从外部数据库中选择”可以显示一个弹出窗口,其中包含表单中相应部分所需的数据。使用Ajax获取数据


这样,您将有一个用于CustomerData字段集的简单Edit Post操作,两个用于在弹出窗口中显示数据的操作,以及一些用于操作addresses部分的javascript。

对于您的示例,我认为您需要“保存”如果您想使用多控制器/表单方法,请单击“名称/名称修改”按钮。使用jQuery和Ajax,这将非常简单,因为在发布某些数据时页面不会刷新,但对于较旧/不太兼容的浏览器,这显然不能很好地伸缩,但这可能是您必须付出的代价pay@MikeSW:我没有深入了解angualrjs。它是一个非常好的框架,但现在我决定不使用它,因为它代表了对我目前使用的方法和工具的过于严格的更改。@Charleh,谢谢,但我不是问如何解决页面刷新问题(我们已经在使用Ajax)。我正在询问如何在服务器上构造代码。仍然不明白这是一个问题的原因-如果您在地址上单击“删除地址”,您只需向所需的控制器发送删除地址命令,然后刷新包含地址信息的页面部分(或仅在JS中执行)。用户不会因为不刷新页面的该部分而丢失“名称”数据…我错了吗?jQuery.ajax允许您将响应写回页面的某个区域-事实上,您可以调用一个不返回任何特定页面数据的控制器,在ajax调用刷新成功后,再次调用当前URL…有选项谢谢,但“保存”按钮会破坏用户体验。我不能要求用户单击“附加”按钮,因为我在服务器上构建代码时遇到问题。@matra如果不使用“保存”按钮,如何保存对客户数据字段集的更改?即使“删除此地址”,对客户的更改也应保存单击按钮或选择“历史记录”选项卡。这意味着它们必须是eac的一部分
public class MyPageViewModel
{
   public List<TabViewModel> Tabs {get; set; }
   public CustomerViewModel Customer;
}

public class TabViewModel
{
    public string DisplayLabel { get; set; }
    public bool Selected { get; set; }
}

class CustomerViewModel
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public List<Address> Addresses { get; set; }
}  

public class Address
{
    public string Street { get; set; }
    public string City { get; set; }
}