ASP.NET MVC控制器逻辑

时间:2011-03-31 02:21:33

标签: asp.net-mvc

我是新手MVC的新手,所以请耐心等待。

我想知道实现控制器逻辑的正确方法是什么。

换句话说,拿这个非常简单的例子,一个忘记密码的屏幕。在传统的ASP / ASP.Net中,这可以在一个页面中处理,根据流程隐藏/显示div或者两个......完成!!

我想出了以下内容,只是想看看我是否走在正确的轨道上。看看下面的控制器:

Namespace Controllers
    Public Class AuthenticationController
        Inherits ControllerBase

        Private MembershipProvider As New GTGMembershipProvider

        <HttpGet()>
        Function LogOn() As ActionResult
            If (User.Identity.IsAuthenticated) Then
                Return RedirectToAction("Index", "Main")
            End If

            Return View(New LogOnViewModel)

        End Function

        <HttpPost()>
        Function LogOn(Model As LogOnViewModel, ReturnUrl As String) As ActionResult
            If (Not ModelState.IsValid) Then
                Return View(Model)
            End If

            If (Not MembershipProvider.ValidateUser(Model.UserName, Model.Password)) Then
                ModelState.AddModelError("", "Invalid login. Incorrect password/user name.")
                Return View(Model)
            End If

            IssueAuthenticationTicket(Model)

            If (Not ReturnUrl.IsNullOrEmpty) Then
                Return Redirect(ReturnUrl)
            Else
                Return RedirectToAction("Index", "Main")
            End If

        End Function

        Function LogOff() As ActionResult
            FormsAuthentication.SignOut()
            Return RedirectToAction("Index", "Main")

        End Function

        <HttpGet()>
        Function ForgotPassword() As ActionResult
            Return View(New ForgotPasswordViewModel)

        End Function

        <HttpPost()>
        Function ForgotPassword(Model As ForgotPasswordViewModel) As ActionResult
            If (Not ModelState.IsValid) Then
                Return View(Model)
            End If

            Return RedirectToAction("PasswordSent")

        End Function

        <HttpGet()>
        Function PasswordSent() As ActionResult
            Return View()

        End Function

        Private Sub IssueAuthenticationTicket(Model As LogOnViewModel)
            Dim Profile As New CustomerProfile With {.FirstName = "Sam", .ID = 1, .LastName = "Striano"}

            Dim Ticket As New FormsAuthenticationTicket(1, Model.UserName, Now, Now.AddDays(30), Model.RememberLogon, Profile.ToString)
            Dim Cookie As New HttpCookie(FormsAuthentication.FormsCookieName, FormsAuthentication.Encrypt(Ticket))

            HttpContext.Response.Cookies.Add(Cookie)

        End Sub

    End Class
End Namespace

2 个答案:

答案 0 :(得分:1)

你走在正确的轨道上。我必须提出三个更好的代码建议:

  1. IssueAuthenticationTicket实施中重构IAuthenticationService方法,其中IAuthenticationService看起来像

    public interface IAuthenticationService {       bool Authenticate(LogOnViewModel viewModel,HttpContextBase httpContext);  }

    这样你的顾虑就会分开,所以如果你必须改变会话的认证方式,你就不必改变控制器逻辑。实际上,您甚至可以将MembershipProvider依赖项保留在实现中,并使界面看起来像:

    public interface IAuthenticationService {       bool Authenticate(LogOnViewModel viewModel,HttpContextBase httpContext,out string message); }

  2. 查看控制和依赖注入的反转,通过构造函数将依赖项自动注入控制器。我最喜欢的工具是StructureMap。这样您就不必将控制器耦合到特定的实现,也不必从控制器中处理任何创建逻辑。 (这会影响您的示例唯一的事情就是调用创建New GTGMembershipProvider。这不是什么大问题,但是对于更复杂的控制器和更复杂的依赖关系,这可能会占用很多空间并使您的代码可读性降低。)

  3. 您可以将登录模型验证逻辑放在ModelValidator中。但是,这可能是一个好主意,也可能不是一个好主意,因为它需要MembershipProvider的多个实例。如果您的会员提供者被实现为单身,那么这将是有意义的。

  4. 对C#感到抱歉 - 我认为最好用C#编写它,然后用VB编写它。

答案 1 :(得分:1)

我认为这对于作为身份验证控制器很有用,有些人建议创建一个抽象级别并将代码移动到另一个类,但在这种情况下我不认为是必要的,对于其他控制器你做的事情使用您的业务对象是必要的,经验法则(IMHO)是控制器操作应该执行的唯一功能是收集将显示并传递给视图的模型的数据,如何获取该数据应该如何在其他类中,但在这个特定的控制器中,我认为这很简单,可以保持这种方式