0

我有几个关于 MVC 应用程序中的逻辑位置的问题。

这是控制器中的一个示例操作,想知道这是否逻辑过多,如果是,您还会把它放在哪里:

仅供参考 -Manager是一种服务类型层,我们将 BO 转换为 DTO/ViewModels 来回转换到另一个执行我们 BL 的层

Public Function ChangeClaim(model As ChangeClaimViewModel) As ActionResult
        Manager.SetClaimNumber(model.ClaimNumber)

        Dim securityToken = Manager.ClaimSecurityToken

        If (securityToken.ValidClaim) Then
            Session("ClaimNumber") = model.ClaimNumber
            If (Not securityToken.ConflictAccess) Then
                ModelState.AddModelError("ClaimNumber", "You do not have access to this claim.")
            End If
        Else
            ModelState.AddModelError("ClaimNumber", "Invalid claim number.")
        End If

        If (Not ModelState.IsValid) Then
            Return View(Manager.GetViewModel())
        End If

        If (model.URL.Contains("ChangeClaim") OrElse model.URL.Contains("EnterClaim")) Then
            model.URL = Url.Action("Index", "Home")
        End If

        Return Redirect(model.URL)

    End Function

另外,我会假设挂起boolViewModel 以在视图中执行类似这样的逻辑可以吗?

@if (Model.HasExposureAccess)
    {
        <li><a href="#tab-pane-2">@Model.Labels.Reimbursements</a></li>
    }

还有其他改进建议吗?

哦,对不起 VB 和 C# 的混合,我工作的商店除了 VB 中的视图之外什么都做,我不得不努力争取在 C# 中做视图!!??

编辑#1

因此,If (securityToken.ValidClaim) Then让我尽我所能为您介绍整个过程,看看您是否有任何建议。

当用户尝试更改索赔编号时,它进入模型,传递给Manager.SetClaim方法(管理器是我们创建的一种服务层,能够使用我们现有的 BO 框架,别笑, 是 CSLA.NET V1 的一个经过大量修改的版本,它们是非常紧密耦合的对象,因为 BL 和 DAL 都存在于对象内部。根本不是我的选择,但是你做什么:)) 验证它是一个有效的声明,并且用户可以访问它。我正在尽我最大的努力使图层尽可能地分开:

1) MVC 应用程序
2) 应用程序管理器
3)​​ 现有 BOF

我说的有道理吗?

编辑#2

因此,我将控制器操作中的逻辑放入了一个操作过滤器中,如下所示:

Public Class ValidateClaimAttribute
Inherits ActionFilterAttribute

Public Overrides Sub OnActionExecuting(filterContext As System.Web.Mvc.ActionExecutingContext)
    MyBase.OnActionExecuting(filterContext)

    Dim model As ChangeClaimViewModel = CType(filterContext.ActionParameters("model"), ChangeClaimViewModel)
    Dim manager As IInjuredWorkerManager = DependencyResolver.Current.GetService(Of IInjuredWorkerManager)()
    Dim securityToken = manager.ClaimSecurityToken

    manager.SetClaimNumber(model.ClaimNumber)

    If (securityToken.ValidClaim) Then
        filterContext.HttpContext.Session("ClaimNumber") = model.ClaimNumber
        If (Not securityToken.ConflictAccess) Then
            filterContext.Controller.ViewData.ModelState.AddModelError("ClaimNumber", "You do not have access to this claim.")
        End If
    Else
        filterContext.Controller.ViewData.ModelState.AddModelError("ClaimNumber", "Invalid claim number.")
    End If

End Sub
End Class

<ValidateClaim()>
    Public Function ChangeClaim(model As ChangeClaimViewModel) As ActionResult
        If (Not ModelState.IsValid) Then
            Return View(Manager.GetViewModel())
        End If

        If (model.URL.Contains("ChangeClaim") OrElse model.URL.Contains("EnterClaim")) Then
            model.URL = Url.Action("Index", "Home")
        End If

        Return Redirect(model.URL)

    End Function

这看起来更像是正确的做法吗?

编辑#3 因此,我对此进行了进一步优化:

<ValidateClaim()>
    Public Function ChangeClaim(model As ChangeClaimViewModel) As ActionResult
        If (Not ModelState.IsValid) Then
            Return View(Manager.GetViewModel())
        End If

        Return New MyRedirect(model.URL)

    End Function
    Public Class ValidateClaimAttribute
Inherits ActionFilterAttribute

Public Overrides Sub OnActionExecuting(filterContext As System.Web.Mvc.ActionExecutingContext)
    MyBase.OnActionExecuting(filterContext)

    Dim model As ChangeClaimViewModel = CType(filterContext.ActionParameters("model"), ChangeClaimViewModel)
    Dim manager As IInjuredWorkerManager = DependencyResolver.Current.GetService(Of IInjuredWorkerManager)()
    Dim securityToken = manager.ClaimSecurityToken

    manager.SetClaimNumber(model.ClaimNumber)

    If (securityToken.ValidClaim) Then
        filterContext.HttpContext.Session("ClaimNumber") = model.ClaimNumber
        If (Not securityToken.ConflictAccess) Then
            filterContext.Controller.ViewData.ModelState.AddModelError("ClaimNumber", "You do not have access to this claim.")
        End If
    Else
        filterContext.Controller.ViewData.ModelState.AddModelError("ClaimNumber", "Invalid claim number.")
    End If

End Sub

End Class

Public Class MyRedirect
Inherits ActionResult

Private _url As String

Public Sub New(url As String)
    _url = url
End Sub

Public Overrides Sub ExecuteResult(context As System.Web.Mvc.ControllerContext)
    Dim urlHelper As New UrlHelper(context.RequestContext)

    If (_url.Contains("ChangeClaim") OrElse _url.Contains("EnterClaim")) Then
        _url = urlHelper.Action("Index", "Home")
    End If

    context.HttpContext.Response.Redirect(_url)
End Sub
End Class

完整的控制器代码:

Imports System.Web.Mvc
Imports System.Security.Principal
Imports Telerik.Web.Mvc
Imports System.Globalization

Namespace Controllers
<HandleException(View:="Error")>
<OutputCache(Duration:=0)>
Public MustInherit Class InjuredWorkerController
    Inherits SAIF.Web.Mvc.Framework.Controllers.ContextController



    Public Property Manager As IInjuredWorkerManager

    Public Sub New(manager As IInjuredWorkerManager)
        _Manager = manager
        _Manager.ValidationDictonary = New ModelStateWrapper(ModelState)


    End Sub

    <ValidateClaim()>
    Public Function ChangeClaim(model As ChangeClaimViewModel) As ActionResult
        If (Not ModelState.IsValid) Then
            Return View(Manager.GetViewModel())
        End If

        Return New MyRedirect(model.URL)

    End Function

    Public Function SetCulture(culture As String, returnUrl As String) As ActionResult
        Response.Cookies.Add(New HttpCookie("culture") With {
                             .Value = culture,
                             .Expires = DateTime.Now.AddYears(1)
                         })

        Return Redirect(returnUrl)

    End Function

    Protected Overrides Sub ExecuteCore()
        Dim cultureName = "en-US"
        Dim cultureCookie = Request.Cookies("culture")

        If (cultureCookie IsNot Nothing) Then
            cultureName = Request.Cookies("culture").Value
        End If

        Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(cultureName)
        Threading.Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(cultureName)

        MyBase.ExecuteCore()
    End Sub

    Protected Overrides Sub OnActionExecuting(filterContext As System.Web.Mvc.ActionExecutingContext)
        MyBase.OnActionExecuting(filterContext)

        Dim controller = filterContext.RouteData.Values("controller").ToString
        Dim action = filterContext.RouteData.Values("action").ToString

        If (action.ToLower = "enterclaim" OrElse action.ToLower = "changeclaim") Then
            Return
        Else
            Dim claimNumber As String = String.Empty
            Dim workerID As Decimal

            If (Session("ClaimNumber") IsNot Nothing) Then
                claimNumber = Session("ClaimNumber").ToString
            End If

            If (Session("WorkerID") IsNot Nothing) Then
                workerID = CDec(Session("WorkerID"))
            End If

            If (String.IsNullOrEmpty(claimNumber)) Then
                If (workerID = 0) Then
                    If (Manager.IsExternalUser) Then
                        workerID = Manager.GetWorkerIdByDomainUser
                        claimNumber = Manager.GetMostRecentClaimNumber(workerID)
                    Else
                        filterContext.Result = New RedirectResult("/MyClaim/Home/EnterClaim")
                    End If
                End If
            End If

            Manager.SetClaimNumber(claimNumber)

        End If

    End Sub

    Public Function SendMessage(<Bind(prefix:="SendMessage")> model As IWSendMessageViewModel) As ActionResult
        Manager.SendAdjusterEmail(model.AdjusterEmail, model.PersonEmail, "IW Contact Message", model.Message, model.SendCopyToSender)
        Return Json(New With {.message = "Success"}, "application/json")
    End Function

End Class

End Namespace
4

1 回答 1

2

对于控制器动作来说,这绝对是太多了。诸如此类的东西If (Not securityToken.ConflictAccess)应该进入一个自定义Authorize属性,你的控制器操作应该用它来装饰。ModelState.AddModelError("ClaimNumber", "Invalid claim number.")诸如进入自定义验证属性之类的事情,或者如果您在模型的 FV 验证器中使用FluentValidation.NET(我强烈建议您这样做)。

像这样的事情:

If (model.URL.Contains("ChangeClaim") OrElse model.URL.Contains("EnterClaim")) Then
    model.URL = Url.Action("Index", "Home")
End If

可以进入您将返回的自定义操作结果。

就视图中的条件逻辑而言,没问题。您可以使用视图模型属性来显示/隐藏某些 UI 元素。显然,适当的授权(通过自定义 Authorize 属性)应该在相应的控制器操作中完成,因为您隐藏了用户的链接这一事实并不意味着恶意用户无法伪造请求并且仍然能够调用您的控制器行动。

于 2012-07-26T15:30:27.130 回答