【问题标题】:Some architectural advice on ASP.NET MVC 3 replacement of php web site关于 ASP.NET MVC 3 替换 php 网站的一些架构建议
【发布时间】:2011-07-24 05:38:57
【问题描述】:

我正在重写一个网络(应用程序?)。我会尝试简单地设置一下(哈哈)。我客户的网站是内置在 CMS 中的。其中大部分是静态内容。该网站托管在某处,但有一个登录区域供客户跟踪他们的订单和存储在我客户服务器上的其他动态业务内容。身份验证发生在双方([php] cms 管理会话,但包括密码在内的业务逻辑和客户数据驻留在我的客户端数据库中的客户端服务器上,并通过 wcf 提供)。对 wcf webservice 的每个 php 请求都会发布一个 json 身份验证字符串,如果通过身份验证,我的 wcf webservice 返回一个填充了请求数据的 json 结果(然后与 smarty 模板一起使用以生成 cms 发送到浏览器的输出)。

这一切都很好,除了 php 代码是巨大的意大利面条。其实按php标准可能还不算太差,但我习惯了……好吧,谁在乎呢,因为归根结底是我没有写,但我必须扩展它,并且每次修改花费的时间比应有的时间长 10(0?)倍,而且只会用更多的面条淹没干草堆(混合隐喻)。可恶的是,在它们上线之前没有测试更改。必须在生产环境中进行任何更改或添加(由于依赖于 CMS 环境)。因此,我必须将闪电战策略与编辑和祈祷相结合,并将第 11 根手指放在众所周知的还原按钮上(如果它只是还原的一个步骤,那不是很好吗?)。我曾多次尝试重构 php 方面,甚至编写了大约 75% 的完整重新实现。但是……

这个网络应用程序正在承担越来越多的责任和变更请求。对于这个客户,我用 C# 编写了一个 500,000 行的 ERP,他们的所有业务逻辑都驻留在其中。所以,我认为将所有代码都放在 .NET 中,对于我或任何追随者来说,都有一定的投资回报率。

对任何解决方案的唯一真正限制是 CMS 要显示的任何内容都必须附加到变量“$output”。这让事情变得非常开放。

无论如何,(通常是多余的,但希望是书呆子的娱乐)叙述是完整的。因此,我设置了一个简单的 php 包装器,它使用 cURL 来获取由我的新 mvc 应用程序支持的 url 的内容。这适用于get。我的问题是进行此操作的最佳方法是什么。来自 cms 端的每个请求都需要包含一些身份验证信息,它将从数据库(或其他)中检索并随请求一起发布。我想我会蚕食 wcf 网络服务并从 mvc 应用程序中提供所有内容。

所以基本上,编写 mvc 应用程序的最佳方法是什么,其中每个请求都是包含身份验证信息的帖子(可以是 json 或 xml)?我试图避免使用 [HttpPost] 装饰每个控制器方法,并且让每个操作方法都需要我的身份验证 dto 的参数,以便在某些时候我可以快速轻松地将所有身份验证切换为 asp 表单身份验证。

感谢(阅读)!

【问题讨论】:

  • 我为你的客户感到难过。
  • 你为什么为我的客户感到难过?
  • 因为你不明白我为什么为你的客户感到难过。
  • 那个花瓶又来了。
  • 我想那是一种侮辱?如果是这样,你能启发我吗?还是我失败了?

标签: c# php asp.net-mvc-3 content-management-system


【解决方案1】:

实现您自己的操作过滤器,它将集中检测当前登录的用户并将其应用于您的函数的参数。 像这样的:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class UserIDFilter : ActionFilterAttribute
{
    public bool Require { get; set; }

    public override void OnActionExecuting(ActionExecutingContext filterContext)
    {
        if (Require)
        {
            if (Membership.GetUser() == null)
            {
                string formsAuthenticationToken = HttpContext.Current.Request.Form["cookie"];
                if (!string.IsNullOrEmpty(formsAuthenticationToken))
                {
                    FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(formsAuthenticationToken);
                    if (ticket != null)
                    {
                        FormsIdentity identity = new FormsIdentity(ticket);
                        string[] roles = Roles.GetRolesForUser(identity.Name);
                        GenericPrincipal principal = new GenericPrincipal(identity, roles);
                        HttpContext.Current.User = principal;
                    }
                }
                if (Membership.GetUser() == null)
                    throw new UserNotAuthenticatedException();
            }
        }
        const string key = "userId";
        if (filterContext.ActionParameters.ContainsKey(key))
        {
            if (Membership.GetUser() != null)
                filterContext.ActionParameters[key] = (Guid)Membership.GetUser().ProviderUserKey;
            else
                filterContext.ActionParameters[key] = (Guid?)null;
        }

        base.OnActionExecuting(filterContext);
    }
}

然后用以下方式装饰每个动作:

[UserIDFilter]
(and the action will have 1st parameter: Guid? userId)

[UserIDFilter(Require=true)
(and the action will have 1st parameter: Guid userId)

【讨论】:

  • 我希望有一个解决方案,我可以在接收来自 cms 端的请求开始时插入该解决方案,该解决方案将进行身份验证并让请求通过或完全拒绝请求并发送错误回到cms方面的事情。这样我就可以用 [Authorize] 或类似的东西来装饰我的控制器,这样当需要完全放弃 cms 时,我就可以切换到自然身份验证。也让我不必记住装饰每个动作方法。
  • 1) 如果您未通过身份验证,此解决方案将完全拒绝请求(假设您设置 Require=true,或重构为始终要求)。
  • 需要进行哪些修改才能装饰我的控制器而不是我的操作?如果我要使用它,您是说每种方法都需要将 GUID 作为参数。那是因为我需要在我的方法主体中手动做一些事情,还是只是 ActionFilter 需要的东西? (我是 MVC 的新手)。谢谢。
  • 2) 你可以装饰控制器本身,而不是每个动作。然后你就不会忘记了。
  • 只需将该属性放在控制器(类名)之上。如果您不将 userId 参数放入您的操作中,您将获得撤销未经身份验证的用户的功能。如果您确实输入,您将在您的操作中获得 [正确且经过验证的] userId。
【解决方案2】:

我们对您的 CMS 一无所知,我们对您的应用程序一无所知,我们对您的架构一无所知,我们对您的 ERP 一无所知......如果对任何事情一无所知,很难给出有意义的答案。

Ofer 试图为您提供解决方案,但根据您的回复,缺乏可用信息并不能帮助他对您正在寻找的内容做出正确的假设。

想象一下,如果有人向您提出问题,并想象您对此一无所知..您能弄清楚您的意思吗?

另外,我知道你可能觉得你的写作很有趣,也许确实如此......但你似乎比你提出实际问题时更努力地变得有趣。当您尝试让他们尽可能轻松地回答问题时,那些回答问题的人往往会更喜欢它,而不是相反。

【讨论】:

  • 是的,我想我能明白我的意思。我试图指定 CMS 对解决方案的约束。除了使用 .NET 编写的 ERP 之外,无需了解任何信息。我花了整个第一段来解释相关的架构。也许您可以简单地要求与您的答案相关的澄清,而不是您的边缘广告。 Ofer 确实尝试了一个解决方案(我赞成)并要求澄清,根据我的?。但是,由于它使用 cookie 而不是我的问题中要求的发布数据,因此我没有将其标记为答案。
【解决方案3】:

这似乎是其中一种情况,“对于拿着锤子的人来说,一切看起来都像钉子”这句话非常适用。当您声明“CMS”代码是意大利面条时,您无法阻止自己对 php 添加一个不太微妙的挖掘,尽管不是真的,因为就您而言 PHP = spaghetti。

请不要假装伤害了你的感情,因为人们因为你所谓的问题包含更多描述完美世界中事物的叙述,而不是实际相关的技术细节或具体查询,所以对你提出了批评。

除了对 .NET 脚本进行 CURL 调用之外,您使用 PHP 的架构是荒谬的。当您的议程明确时,为什么还要浪费我们的时间。去向你的客户说明你的理由,为什么他们对微软技术堆栈的投资比其他任何事情都要大得多,他们将这个堆栈扩展到前端是有意义的。我们在 PHP 世界中有许多提供 MVC 的优秀框架。很明显,PHP 并不在您的舒适区,在这种情况下,向客户说明混合解决方案不能很好地为他们提供服务似乎是很合乎逻辑的。

【讨论】:

  • 哇。你也是,嗯?你(可能)一点也不知道。代码是意大利面条。当你有 100 行长的函数时,将 SQL 代码与 HTML 字符串混合在一起,还有一个小型 Web 服务器,它在“名词动词和副词”上运行,它通过要求不断新的英语语法知识修改来限制系统的可扩展性扩展数组以处理业务逻辑扩展......编写它的程序员是认为在运算符之间放置空格是不必要的奢侈的人之一。 MVC 和 OOP 成为标准是有原因的。
  • 无论如何我没有说 CMS 是意大利面条,我说处理这个特定网络应用程序的 php 代码是意大利面条。
  • 我的理解是apache是​​一个web服务器。为什么要写另一个除了解决问题之外什么都不做的文章?这就是为什么我拒绝使用它。那以及由于对运行时环境的依赖而无法测试更改的事实。您是否喜欢在测试客户端请求的唯一方法是将代码上传到生产服务器,使用真实用户的帐户登录并查看是否有问题的情况下编写代码?当数百名用户在任务几乎关键的情况下使用系统时?如果是这样,那么我为您的客户感到难过。
  • 我知道 php 中有提供 MVC 的框架。我用过它们。好的和坏的代码可以用几乎任何语言编写(想想 VB)。关键是这段代码很糟糕,与其用同一种语言重写我的客户的代码库被分成两种语言,我应该把它带到一种与他的代码库的其他 99.9% 相对应的语言。至于我的叙述,是的,我很抱歉试图用对话来表达问题。我一定忘记了一些程序员对人性的幼稚敏感。
  • 在您的陈述中,我真正感兴趣的唯一一点是为什么“除了对您的 .NET 脚本进行 CURL 调用之外,使用 PHP 绝对是荒谬的”。这就是我的“建筑”问题。为什么这很荒谬?就像我说的,这个客户的网站是在这个 CMS 中构建的,所以,为了保持网站的外观和感觉,(对我来说)简单地将动态内容注入现有网站是有意义的。我认为没有理由不这样做。你?我的解决方案和当前解决方案之间的区别在于,我会从 asp 生成表格和表单
猜你喜欢
  • 2010-11-08
  • 1970-01-01
  • 2018-05-23
  • 2011-04-06
  • 1970-01-01
  • 2011-09-26
  • 1970-01-01
  • 2011-11-26
  • 1970-01-01
相关资源
最近更新 更多