21、构建基于业务对象的Web Forms用户界面

构建基于业务对象的Web Forms用户界面

在Web开发领域,构建高效且功能强大的用户界面是至关重要的。本文将深入探讨如何利用业务对象创建Web Forms界面,并阐述相关的技术细节和操作步骤。

1. Web开发与对象选择

在Web开发中,数据访问模型的选择对网站性能和可维护性有着重要影响。一般来说,Web应用有三种基本的数据访问模型:
- 直接使用DataReader :当数据集相对较小且页面处理速度快时,直接使用DataReader可以将数据直接从数据库提取到页面,无需将数据复制到内存容器中,提高了性能。但如果数据集较大或页面处理缓慢,使用DataReader会导致数据库连接长时间保持打开状态,增加服务器连接数,降低可扩展性,并且代码难以维护。
- 使用DataSet或对象 :大多数情况下,使用DataSet或对象比直接使用DataReader具有更好的可扩展性,并且代码更易于维护。在选择使用DataSet、DTO(数据传输对象)、实体对象还是业务对象作为有状态的内存数据容器时,需要考虑对象的功能。数据容器对象只是简单的数据容器,不提供业务行为;而业务对象不仅提供对应用程序数据的访问,还封装了业务逻辑,是更好的选择。

2. 状态管理

状态管理是Web开发的关键问题。由于Web技术最初设计仅用于文档查看,状态管理技术的发展较为随意。目前主要有以下三种状态管理策略:
| 状态管理策略 | 优点 | 缺点 |
| — | — | — |
| 状态保存在Web服务器 | 易于编码和使用,与业务对象配合良好 | 使用全局字段/数据是不良编程习惯,通过Web农场实现可扩展性和容错性需要增加基础设施的复杂性 |
| 状态在每次页面请求时在服务器和客户端之间传输 | 通过实现Web农场可以轻松实现可扩展性和容错性 | 代码复杂,需要手动编写大量代码,在慢速网络链接上性能较差 |
| 状态存储在临时文件或数据库表中 | 通过实现Web农场可以轻松实现可扩展性和容错性,能够存储大量或非常复杂的状态数据 | 每次页面请求都会增加数据库服务器的负载,需要手动编写代码,需要实现数据清理以处理废弃的状态数据 |

3. 界面设计与应用配置
  • 界面设计 :以PTWeb项目为例,该项目使用主页面提供一致的布局和导航,所有处理业务数据的页面都使用相同的业务对象,并通过数据绑定构建。主页面定义了标题栏、导航区域和内容区域,内容页面通过ContentPlaceHolder与主页面关联。
  • 应用配置 :通过web.config文件提供基本配置信息,包括配置数据门户或数据库连接字符串,以及配置CslaDataSource控制。数据门户可以配置为本地模式或远程模式,通过不同的网络通道与应用服务器通信。
4. 关键操作步骤
  • 配置CslaDataSource控制 :在Web Forms中使用CslaDataSource控制,需要在web.config文件中定义控制前缀:
<controls>
  <add tagPrefix="csla" namespace="Csla.Web" assembly="Csla"/>
</controls>
  • 配置身份验证 :通过web.config文件控制身份验证方式,例如使用自定义身份验证:
<appSettings>
  <add key="CslaAuthentication" value="Csla" />
</appSettings>
  • 配置本地数据门户 :在web.config文件中提供数据库连接字符串:
<connectionStrings>
  <add name="PTracker" connectionString="your connection string"
    providerName="System.Data.SqlClient" />
  <add name="Security" connectionString="your connection string"
    providerName="System.Data.SqlClient" />
</connectionStrings>
  • 配置远程数据门户(使用WCF) :在web.config文件中配置WcfProxy和客户端端点:
<appSettings>
  <add key="CslaAuthentication" value="Csla" />
  <add key="CslaDataPortalProxy"
            value="Csla.DataPortalClient.WcfProxy, Csla"/>
</appSettings>
<system.serviceModel>
  <client>
    <endpoint name="WcfDataPortal"
              address="http://localhost:4147/WcfHost/WcfPortal.svc"
              binding="wsHttpBinding"
              contract="Csla.Server.Hosts.IWcfPortal"/>
  </client>
</system.serviceModel>
5. 业务功能实现

以RolesEdit、ProjectList和ProjectEdit页面为例,这些页面使用MultiView控制提供不同的视图,通过CslaDataSource控制进行数据绑定,并使用Session缓存业务对象以优化性能。以下是这些页面的主要操作流程:

graph LR
    A[用户访问页面] --> B{页面类型}
    B -->|RolesEdit| C[选择视图]
    C -->|MainView| D[显示角色列表]
    C -->|InsertView| E[添加新角色]
    B -->|ProjectList| F[显示项目列表]
    F -->|选择项目| G[跳转到ProjectEdit页面]
    F -->|添加项目| H[跳转到ProjectEdit页面创建新项目]
    F -->|删除项目| I[调用DeleteProject方法删除项目]
    B -->|ProjectEdit| J{是否有id参数}
    J -->|有| K[获取现有项目]
    J -->|无| L[创建新项目]
    K --> M[显示项目详情]
    L --> N[显示默认值]
    M -->|编辑项目| O[更新项目数据]
    M -->|删除项目| P[调用DeleteProject方法删除项目]
    M -->|分配资源| Q[选择资源并分配]

通过以上步骤和策略,可以构建一个高效、可扩展且易于维护的Web Forms用户界面。在实际应用中,需要根据具体需求选择合适的状态管理策略和数据访问模型,以达到最佳性能和用户体验。

构建基于业务对象的Web Forms用户界面

6. 各页面详细实现
6.1 RolesEdit页面

RolesEdit页面用于管理角色列表,支持查看、添加、编辑和删除角色的操作。
- 使用MultiView控制 :该页面使用MultiView控制包含MainView和InsertView两个视图,通过设置ActiveViewIndex属性切换视图。

Private Enum Views
  MainView = 0
  InsertView = 1
End Enum
  • 使用CslaDataSource控制 :通过CslaDataSource控制将Roles集合绑定到GridView和DetailsView控制上。
<csla:CslaDataSource ID="RolesDataSource" runat="server"
  TypeName="ProjectTracker.Library.Admin.Roles, ProjectTracker.Library"
  OnDeleteObject="RolesDataSource_DeleteObject"
  OnInsertObject="RolesDataSource_InsertObject"
  OnSelectObject="RolesDataSource_SelectObject"
  OnUpdateObject="RolesDataSource_UpdateObject">
</csla:CslaDataSource>
  • 缓存对象 :为了优化性能,将业务对象存储在Session中,使用GetRoles()方法获取角色对象。
Private Function GetRoles() As ProjectTracker.Library.Admin.Roles
  Dim businessObject As Object = Session("currentObject")
  If businessObject Is Nothing OrElse Not (TypeOf businessObject Is _
    ProjectTracker.Library.Admin.Roles) Then
    businessObject = ProjectTracker.Library.Admin.Roles.GetRoles()
    Session("currentObject") = businessObject
  End If
  Return DirectCast(businessObject, ProjectTracker.Library.Admin.Roles)
End Function
  • 插入角色 :点击AddRoleButton按钮切换到InsertView,用户输入新角色信息后点击Insert按钮,触发InsertObject事件添加新角色。
Protected Sub RolesDataSource_InsertObject(ByVal sender As Object, _
  ByVal e As Csla.Web.InsertObjectArgs)
  Try
    Dim obj As ProjectTracker.Library.Admin.Roles = GetRoles()
    Dim role As ProjectTracker.Library.Admin.Role = obj.AddNew()
    Csla.Data.DataMapper.Map(e.Values, role)
    Session("currentObject") = obj.Save()
    e.RowsAffected = 1
  Catch ex As Csla.DataPortalException
    Me.ErrorLabel.Text = ex.BusinessException.Message
    e.RowsAffected = 0
  Catch ex As Exception
    Me.ErrorLabel.Text = ex.Message
    e.RowsAffected = 0
  End Try
End Sub
  • 更新角色 :用户点击Edit链接进入编辑模式,触发UpdateObject事件更新角色信息。
Protected Sub RolesDataSource_UpdateObject(ByVal sender As Object, _
  ByVal e As Csla.Web.UpdateObjectArgs)
  Try
    Dim obj As ProjectTracker.Library.Admin.Roles = GetRoles()
    Dim role As ProjectTracker.Library.Admin.Role = _
      obj.GetRoleById(CInt(e.Keys("Id").ToString()))
    role.Name = e.Values("Name").ToString()
    Session("currentObject") = obj.Save()
    e.RowsAffected = 1
  Catch ex As Csla.DataPortalException
    Me.ErrorLabel.Text = ex.BusinessException.Message
    e.RowsAffected = 0
  Catch ex As Exception
    Me.ErrorLabel.Text = ex.Message
    e.RowsAffected = 0
  End Try
End Sub
  • 删除角色 :用户点击Delete链接,触发DeleteObject事件删除角色。
Protected Sub RolesDataSource_DeleteObject(ByVal sender As Object, _
  ByVal e As Csla.Web.DeleteObjectArgs)
  Try
    Dim obj As ProjectTracker.Library.Admin.Roles = GetRoles()
    Dim id As Integer = CInt(e.Keys("Id"))
    obj.Remove(id)
    Session("currentObject") = obj.Save()
    e.RowsAffected = 1
  Catch ex As Csla.DataPortalException
    Me.ErrorLabel.Text = ex.BusinessException.Message
    e.RowsAffected = 0
  Catch ex As Exception
    Me.ErrorLabel.Text = ex.Message
    e.RowsAffected = 0
  End Try
End Sub
  • 授权控制 :在页面加载时调用ApplyAuthorizationRules()方法,根据用户权限显示或隐藏相关控件。
Private Sub ApplyAuthorizationRules()
  Dim canEdit As Boolean = _
    Csla.Security.AuthorizationRules.CanEditObject( _
    GetType(ProjectTracker.Library.Admin.Roles))
  Me.GridView1.Columns( _
    Me.GridView1.Columns.Count - 1).Visible = canEdit
  Me.AddRoleButton.Visible = canEdit
End Sub
6.2 ProjectList页面

ProjectList页面用于显示项目列表,支持选择、添加和删除项目的操作。
- GridView控制 :使用GridView控制显示项目列表,Name列使用HyperLinkField,点击项目名称可跳转到ProjectEdit页面。

<asp:GridView ID="GridView1" runat="server"
  AllowPaging="True" AutoGenerateColumns="False"
  DataSourceID="ProjectListDataSource" PageSize="4"
  OnRowDeleted="GridView1_RowDeleted"
  DataKeyNames="Id">
  <Columns>
    <asp:BoundField DataField="Id" HeaderText="Id"
      SortExpression="Id" Visible="False" />
    <asp:HyperLinkField DataNavigateUrlFields="Id"
      DataNavigateUrlFormatString="ProjectEdit.aspx?id={0}"
      DataTextField="Name" HeaderText="Name" />
    <asp:CommandField ShowDeleteButton="True"
      SelectText="Delete" />
  </Columns>
</asp:GridView>
  • 数据加载 :通过ProjectListDataSource控制的SelectObject事件加载项目列表。
Protected Sub ProjectListDataSource_SelectObject(ByVal sender As Object, _
  ByVal e As Csla.Web.SelectObjectArgs)
  e.BusinessObject = GetProjectList()
End Sub
  • 添加项目 :点击NewProjectButton按钮,重定向到ProjectEdit页面创建新项目。
Protected Sub NewProjectButton_Click(ByVal sender As Object, ByVal e As EventArgs) _
  Handles NewProjectButton.Click
    ' allow user to add a new project
  Response.Redirect("ProjectEdit.aspx")
End Sub
  • 删除项目 :点击Delete链接,触发DeleteObject事件删除项目。
Protected Sub ProjectListDataSource_DeleteObject(ByVal sender As Object, _
  ByVal e As Csla.Web.DeleteObjectArgs)
  Try
    ProjectTracker.Library.Project.DeleteProject( _
      New Guid(e.Keys("Id").ToString()))
    e.RowsAffected = 1
  Catch ex As Csla.DataPortalException
    Me.ErrorLabel.Text = ex.BusinessException.Message
    e.RowsAffected = 0
  Catch ex As Exception
    Me.ErrorLabel.Text = ex.Message
    e.RowsAffected = 0
  End Try
End Sub
  • 授权控制 :在页面加载时调用ApplyAuthorizationRules()方法,根据用户权限显示或隐藏相关控件。
Private Sub ApplyAuthorizationRules()
  Me.GridView1.Columns(Me.GridView1.Columns.Count - 1).Visible = _
    Csla.Security.AuthorizationRules.CanDeleteObject(GetType(Project))
  NewProjectButton.Visible = _
    Csla.Security.AuthorizationRules.CanCreateObject(GetType(Project))
End Sub
6.3 ProjectEdit页面

ProjectEdit页面用于查看和编辑项目详情,支持分配资源、删除项目等操作。
- 缓存项目对象 :使用GetProject()方法从Session或数据库中获取项目对象。

Private Function GetProject() As Project
  Dim businessObject As Object = Session("currentObject")
  If businessObject Is Nothing OrElse _
    Not (TypeOf businessObject Is Project) Then
    Try
      Dim idString As String = Request.QueryString("id")
      If Not String.IsNullOrEmpty(idString) Then
        Dim id As New Guid(idString)
        businessObject = Project.GetProject(id)
      Else
        businessObject = Project.NewProject()
      End If
      Session("currentObject") = businessObject
    Catch generatedExceptionName As System.Security.SecurityException
      Response.Redirect("ProjectList.aspx")
    End Try
  End If
  Return DirectCast(businessObject, Project)
End Function
  • 创建新对象 :在DetailsView控制的ItemCreated事件中设置默认值。
Protected Sub DetailsView1_ItemCreated(ByVal sender As Object, _
  ByVal e As EventArgs)
  If DetailsView1.DefaultMode = DetailsViewMode.Insert Then
    Dim obj As Project = GetProject()
    DirectCast(DetailsView1.Rows(1).Cells(1).Controls(0), TextBox).Text = _
      obj.Name
    DirectCast(DetailsView1.Rows(2).Cells(1).Controls(0), TextBox).Text = _
      obj.Started
    DirectCast(DetailsView1.Rows(3).Cells(1).Controls(0), TextBox).Text = _
      obj.Ended
    DirectCast(DetailsView1.FindControl("TextBox1"), TextBox).Text = _
      obj.Description
  End If
End Sub
  • 保存项目 :使用SaveProject()方法保存项目数据。
Private Function SaveProject(ByVal project As Project) As Integer
  Dim rowsAffected As Integer
  Try
    Session("currentObject") = project.Save()
    rowsAffected = 1
  Catch ex As Csla.Validation.ValidationException
    Dim message As New System.Text.StringBuilder()
    message.AppendFormat("{0}", ex.Message)
    If project.BrokenRulesCollection.Count > 0 Then
      message.Append("<ul>")
      For Each rule As Csla.Validation.BrokenRule In project.BrokenRulesCollection
        message.AppendFormat("<li>{0}: {1}</li>", rule.Property, rule.Description)
      Next
      message.Append("</ul>")
    End If
    Me.ErrorLabel.Text = message.ToString()
    rowsAffected = 0
  Catch ex As Csla.DataPortalException
    Me.ErrorLabel.Text = ex.BusinessException.Message
    rowsAffected = 0
  Catch ex As Exception
    Me.ErrorLabel.Text = ex.Message
    rowsAffected = 0
  End Try
  Return rowsAffected
End Function
  • 数据绑定 :通过ProjectDataSource、ResourcesDataSource、RoleListDataSource和ResourceListDataSource控制进行数据绑定。
Protected Sub ProjectDataSource_SelectObject(ByVal sender As Object, _
  ByVal e As Csla.Web.SelectObjectArgs)
  e.BusinessObject = GetProject()
End Sub
Protected Sub ResourcesDataSource_SelectObject(ByVal sender As Object, _
  ByVal e As Csla.Web.SelectObjectArgs)
  Dim obj As Project = GetProject()
  e.BusinessObject = obj.Resources
End Sub
Protected Sub RoleListDataSource_SelectObject(ByVal sender As Object, _
  ByVal e As Csla.Web.SelectObjectArgs)
  e.BusinessObject = RoleList.GetList()
End Sub
Protected Sub ResourceListDataSource_SelectObject(ByVal sender As Object, _
  ByVal e As Csla.Web.SelectObjectArgs)
  e.BusinessObject = ProjectTracker.Library.ResourceList.GetResourceList()
End Sub
  • 授权控制 :在页面加载时调用ApplyAuthorizationRules()方法,根据用户权限显示或隐藏相关控件。
Private Sub ApplyAuthorizationRules()
  Dim obj As Project = GetProject()
  ' project display
  If Csla.Security.AuthorizationRules.CanEditObject(GetType(Project)) Then
    If obj.IsNew Then
      Me.DetailsView1.DefaultMode = DetailsViewMode.Insert
    Else
      Me.DetailsView1.DefaultMode = DetailsViewMode.Edit
    End If
    Me.AddResourceButton.Visible = Not obj.IsNew
  Else
    Me.DetailsView1.DefaultMode = DetailsViewMode.ReadOnly
    Me.AddResourceButton.Visible = False
  End If
  Me.DetailsView1.Rows(Me.DetailsView1.Rows.Count - 1).Visible = _
    Csla.Security.AuthorizationRules.CanEditObject(GetType(Project))
  ' resource display
  Me.GridView1.Columns(Me.GridView1.Columns.Count - 1).Visible = _
    Csla.Security.AuthorizationRules.CanEditObject(GetType(Project))
End Sub
7. 总结

通过以上对各页面的详细实现,我们可以看到如何利用业务对象构建一个完整的Web Forms用户界面。在这个过程中,我们需要关注以下几个关键方面:
- 数据访问模型选择 :根据数据集大小和页面处理速度选择合适的数据访问模型,如直接使用DataReader或使用DataSet、业务对象等。
- 状态管理策略 :根据应用需求选择合适的状态管理策略,如将状态保存在Web服务器、在服务器和客户端之间传输状态或存储在临时文件或数据库表中。
- 界面设计与配置 :使用主页面和主题提供一致的界面,通过web.config文件配置数据门户、身份验证等信息。
- 业务功能实现 :使用MultiView控制和CslaDataSource控制实现数据绑定和视图切换,通过Session缓存业务对象优化性能。
- 授权控制 :使用CSLA .NET授权子系统根据用户权限显示或隐藏相关控件,确保系统的安全性。

通过合理运用这些技术和策略,我们可以构建出高效、可扩展且易于维护的Web Forms用户界面,满足不同用户的需求。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值