0

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

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

4

1 回答 1

1

我都明白了。由于 Google Chrome 阻止了.zip 文件,因此我无法下载MvcContrib 源代码存档,但我能够使用 Internet Explorer 获取它。

这是将其适应我的应用程序后的重要部分。希望这可以帮助某人。我已尽力正确格式化我的答案,这是我第一次在 StackOverflow 上发帖:

在可移植类库中

  1. 使用 ICommandResult 接口创建一个 LoginResult 类

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

    public class LoginMessage : ICommandMessage<LoginResult>
    {
        public LoginResult Result { get; set; }
        public LoginViewModel Input { get; set; }
    }
    
  3. 在 Login 控制器的 HttpPost 动作中,创建一个 LoginMessage 的实例,从登录视图中传入 LoginViewModel,并使用 MvcContrib.Bus.Send 将其发送到 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。成功由主机设置(如下所示)。我这样做是因为某些主机应用程序具有仅适用于该应用程序的特定附加逻辑,所以我让主机做它需要做的事情并返回到便携式设备,让它知道它是通过还是失败。最终,我将首先在 Portable 中拥有基本的身份验证逻辑,然后让 Host 完成额外的工作,但为了这个示例,我保持简单。

在 Host Web 应用程序中(它引用了我的 Portable 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为 True时,在我之前描述的控制器中设置 Portable 将重定向到的 defaultUrl 。您不需要使用表单身份验证,可以将模式设置为无,但您需要拥有 defaultUrl 才能使其正常工作。

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

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

于 2019-12-05T18:26:02.637 回答