MVC5 Portable Area,如何使用消息总线?

MVC5 Portable Area, how do you use message bus?

我花了几个小时阅读了许多不同的示例和文档,以使用 ASP.NET MVC 设置一个可移植区域,目的是共享一个具有多个应用程序身份验证的公共登录页面。我把它们放在一起,到目前为止效果很好,但我遇到的一件事是消息总线的使用。我看到这是主机和便携式组件之间的一种通信方式,但我没有看到如何执行此操作的明确方法。

例如;如果我的便携式登录成功,我如何告诉主机以便它可以做一些事情(设置 cookie、重定向到特定页面等)?另外,如果我想向 Portable 发送一些东西(比如主机应用程序的标题或程序集版本),我该怎么做?我还没有尝试任何东西,因为我似乎找不到完整的例子。

我都弄明白了。有一个 MvcContrib source code archive 我无法下载,因为 Google Chrome 阻止了 .zip 文件,但我可以使用 Internet Explorer 获取它。

以下是根据我的应用程序进行调整后的重要部分。希望这可以帮助某人。我已尽力正确格式化我的答案,这是我第一次在 Whosebug 上发帖:

在便携式 class 库中

  1. 使用 ICommandResult 接口创建 LoginResult class

    public class LoginResult: MvcContrib.PortableAreas.ICommandResult
    {
        public bool Success { get; set; }
        public string Message { get; set; }
        public string Username { get; set; }
    }
    
  2. 创建一个 LoginMessage class,它也使用带有 LoginResult 的 ICommandResult 接口。 LoginMessage class 有一个 属性 用于我在 Login.cshtml 视图中使用的 LoginViewModel(它有用户名、密码和视图所需的其他一些字段)

    public class LoginMessage : ICommandMessage<LoginResult>
    {
        public LoginResult Result { get; set; }
        public LoginViewModel Input { get; set; }
    }
    
  3. 在Login controller的HttpPost action中,创建一个LoginMessage的实例,传入login view的LoginViewModel,用MvcContrib.Bus.Send[=16=发送给Host ]

    [HttpPost]
    public ActionResult Login(LoginViewModel mdl)
    {
        // TODO: Do basic auth here first, then send to Host for additional validation
    
        // Create and send message to the Host
        var message = new LoginMessage { Input = mdl, Result = new LoginResult() };
    
        MvcContrib.Bus.Send(message);
    
        if (message.Result.Success)
        {
            // Redirect to defaultUrl set in the Host's web.config
            FormsAuthentication.RedirectFromLoginPage(mdl.Username, false);
        }
    
        return View("Login", "_Layout", mdl);
    }
    

注意:LoginMessage设置一个新的空LoginResult,然后等待Success。 Success 由主机设置(如下所示)。我这样做是因为某些 Host 应用程序具有仅适用于该应用程序的特定附加逻辑,因此我让 Host 执行它需要的操作,并向 Portable return 通知它是通过还是失败。最终,我将首先在 Portable 中拥有基本的身份验证逻辑,然后让 Host 完成额外的工作,但为了这个示例,我保持简单。

在主机 Web 应用程序中(它引用了我的便携式 dll)

  1. 为 Portable.LoginMessage 创建一个处理程序,以便我们可以在主机中读取它。请注意,IsValidLogin 是我最终将执行附加身份验证逻辑以查看用户是否有效的地方

    public class LoginHandler : MvcContrib.PortableAreas.MessageHandler<Portable.LoginMessage>
    {
        public override void Handle(Portable.LoginMessage message)
        {
            if (IsValidLogin(message.Input.Username, message.Input.Password))
            {
                message.Result.Success = true;
                message.Result.Username = message.Input.Username;
            }
            else
            {
                message.Result.Message = "Username or Password was incorrect";
            }
        }
    
        private bool IsValidLogin(string username, string password)
        {
            // TODO: Replace with actual authentication
            return username.Equals("admin") && password.Equals("password");
        }
    }
    
  2. 在web.config中,当message.Result.Success时,在我之前描述的控制器中设置Portable将重定向到的defaultUrl是真的。您不需要使用 Forms 身份验证,模式可以设置为 None,但您需要有 defaultUrl 才能正常工作。

    <system.web>
        <authentication mode="Forms">
            <forms loginUrl="~/Portable/Login" defaultUrl="~/Home/Index" />
        </authentication>
    </system.web>
    

就是这样!这对我来说是一次很好的锻炼和学习经历。我仍在弄清楚问题的第二部分,我需要先将信息发送到便携式设备(例如应用程序标题和程序集版本),但我认为我可以做几乎相同的事情,但反过来,我发送的地方当我的主机启动时向便携式设备发送 ICommandMessage (global.asax)。