具有服务架构的 MVC

MVC with Service architecture

我正在创建一个 MVC 项目,其中一个视图中包含搜索部分和列表部分。 同时我有一个使用服务层的想法(Web API 或 WCF)。

我想问一下,构建此搜索和列表页面的正确方法或设置是哪一种?

我现在这样做的方式是使用局部视图列出每次搜索时都会更新的部分,并将服务层定位在控制器后面(服务层在控制器和业务层的中间) .

谢谢。

MVC 控制器应该是瘦路由驱动程序。一般来说,您的控制器操作应该类似于

[Authorize(Roles = "User,Admin"]
[GET("hosts")]
public ActionResult Hosts(int id)
{
    if (false == ModelState.IsValid) 
            return new HttpStatusCodeResult(403, "Forbidden for reasons....");

    var bizResponse = bizService.DoThings();

    if(bizResponse == null) return HttpNotFound(id + "could not be found")

    if(false == bizResponse.Success) 
        return new HttpStatusCodeResult(400, "Bad request for reasons....");

    return View(bizResponse);
}

您还可以将模型状态检查和响应对象检查(如果您使用通用契约 - 基类型或接口)概括为:

[Authorize(Roles = "User,Admin"]
[GET("hosts")]
[AutoServiceResponseActionFilter]
public ActionResult Hosts(int id)
{
    var bizResponse = bizService.DoThings();

    return View(bizResponse);
}

我是使用序列化从业务层传递到 http/MVC/ASP.NET 层的支持者。您使用的任何东西都不应生成任何正在处理的 http 或 tcp 请求,并且应该使用命名管道进行内存传输。带有 IDesign InProcFactory 的 WCF 为您提供了开箱即用的功能,您无法很好地模拟这个 WebApi,您可以使用 NFX 或服务堆栈来模拟它,但我不确定手头的情况。

如果您希望 bizService 在进程外托管,此时最好的传输方式是使用消息总线或消息队列连接到 bizService。通常,在使用此架构时,您需要一个真正的异步 UI,一旦 http 端点接受请求,它就可以立即收到 http OK 或 http ACCEPTED 响应,并在稍后通知操作的执行。

一般来说,MVC 控制器/ASP.NET http 端点不应该发起 http 请求。如果需要,您的 bizService 可以免费调用第三方 http 服务。最终,往返网络调用会扼杀一切的感知性能。如果您无法避免往返调用,您应该努力将其限制为最多一次读取和最多一次写入。如果您发现自己需要通过线路调用多个读取和多个写入调用,这非常说明业务系统的架构设计不佳。

最后,在设计良好的 SOA 中,您的系统比 OO 更实用。具有不可变数据/缺乏共享状态的功能逻辑是可扩展的。你越依赖任何共享状态,系统就越脆弱,并开始积极地变成 anti-scale。高度有状态很容易导致系统在 20-50 req/s 范围内崩溃。名义上,单个服务器系统应处理 300-500 req/s 的实际使用量。

代理此类业务服务的原因是要遵循受信任的子系统模式。没有用户能够对您的业务服务进行身份验证,只有您的应用程序能够进行身份验证。没有用户能够确定您的业务服务的托管位置。与此相关的是,用户永远不应授权业务服务本身,业务服务 action 应该能够在必要时授权请求的发起者。一般来说,这只需要细粒度控制,例如可以禁止用户访问单个记录。


由于客户端是远程的且不可信任的(用户可以恶意操纵它们,无论它们是 javascript 还是编译的二进制文件),它们永远不应该知道您的服务层。服务层本身可以通过防火墙与整个互联网隔离开来,只允许您的 Web 服务器与服务层通信。您的 Web 服务器中可能有一些表示构建逻辑,例如为您的客户端提供用户 ID、名称、安全令牌等,但它可能是最小的。需要向服务层发起调用的是Web服务器作为代理

简短版本,只有一个控制器应该调用你的服务层。

一个例外,例如,如果您使用像 Azure 服务总线这样的消息队列系统,根据安全限制,您 UI 可以直接将消息排队到 ASB,因为 ASB 可以被处理作为 DMZ,并且仍然保护您的服务不受任何客户知识的影响。直接队列访问的主要风险是恶意用户可能会淹没您的队列以进行拒绝服务类型的攻击(并使您付出金钱)。一个非恶意的风险是,如果您更改过时的队列合同,客户端可能会导致大量死信或有毒消息

我真的相信所有开发的未来都是直接将消息排队的客户端,但目前的技术非常缺乏轻松安全地做到这一点。直接队列访问对于物联网的未来势在必行。 Web 服务器没有能力接收来自成千上万个灯泡和冰箱的连续事件流。