构建基于业务对象的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用户界面,满足不同用户的需求。
超级会员免费看
465

被折叠的 条评论
为什么被折叠?



