ASP.NET MVC结构/逻辑

时间:2012-07-26 15:21:58

标签: vb.net asp.net-mvc-3

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

这是控制器中的一个示例动作,并且想知道这是否是太多逻辑,如果是这样,你还会把它放在哪里:

FYI - 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

另外,我假设在视图中挂起bool的ViewModel用来做逻辑就好了吗?

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

还有其他改进建议吗?

哦,抱歉VB和&amp;混合使用C#,我工作的商店除了VB中的视图外都做了一切,我不得不争取在C#中做观点!! ??

编辑#1

至于If (securityToken.ValidClaim) Then让我尽力让您完成整个过程,看看您是否有任何建议。

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

1)MVC App
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

1 个答案:

答案 0 :(得分: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元素。显然,应该在相应的控制器操作中进行适当的授权(通过自定义授权属性),因为您隐藏了用户链接的事实并不意味着恶意用户无法伪造请求并且仍然能够调用您的控制器动作。