简体   繁体   English

具有服务架构的MVC

[英]MVC with Service architecture

I'm creating a MVC project where in one of its View, there will be search part and the listing part. 我正在创建一个MVC项目,在该视图的其中一个视图中,将包含搜索部分和清单部分。 At the same time I have an idea of using a service layer (Web API or WCF). 同时,我有一个使用服务层(Web API或WCF)的想法。

I would like to ask which one is correct way or setup for building this search and listing page ? 我想问问哪个是正确的方法或设置来构建此搜索和列表页面?

The way I'm doing it at the moment is using partial view for listing part that will get updated every time searching occurs and position the service layer behind the controller (service layer in the middle of controller and business layer). 我目前的操作方式是使用局部视图列出列出的部分,该部分视图将在每次搜索时进行更新,并将服务层放置在控制器后面(服务层位于控制器和业务层的中间)。

Thank you. 谢谢。

MVC Controllers should be thin route drivers. MVC控制器应该是瘦路由驱动程序。 In general your controller actions should look similar to 通常,您的控制器动作应类似于

[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);
}

You can also generalize the model state checking and response object checking (if you use a common contract - base type or interface) to simply have: 您还可以泛化模型状态检查和响应对象检查(如果您使用通用协定-基本类型或接口),则只需:

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

    return View(bizResponse);
}

I am a proponent of using serialization to pass from the business layer to the http/MVC/ASP.NET layer. 我支持使用序列化从业务层传递到http / MVC / ASP.NET层。 Anything that you use should not generate any http or tcp requests if it is in-process and should used named-pipes for in memory transport. 如果使用的任何内容都在进程中,则不应生成任何http或tcp请求,并且应将命名管道用于内存传输。 WCF with IDesign InProcFactory gives you this out of the box, you can't emulate this very well WebApi, you may be able to emulate this with NFX or Service Stack but I am not sure off hand. 使用IDesign InProcFactory的WCF可以立即使用,您无法很好地模拟WebApi,您可以使用NFX或Service Stack来模拟,但是我不确定是否可以立即使用。

If you want the bizService to be hosted out of process the best transport at this point is to use a Message Bus or Message Queue to the bizService. 如果您希望将bizService托管到进程外,则此时的最佳传输方法是将消息总线或消息队列用于bizService。 Generally when working with this architecture you need a truly asynchronous UI that once the http endpoint accepts the request it can immediately receive the http OK or http ACCEPTED response and be informed later of the execution of the action. 通常,在使用这种体系结构时,您需要一个真正的异步UI,一旦http端点接受了请求,它便可以立即收到http OK或http ACCEPTED响应,并在以后通知该操作已执行。

In general a MVC controller / ASP.NET http endpoint should never initiate a http request. 通常,MVC控制器/ASP.NET http终结点永远不要发起http请求。 Your bizService if necessary is free to call a third party http service. 您的bizService如有必要,可以免费调用第三方http服务。 Ultimately roundtrip network calls are what kills the perceived performance of everything. 最终,往返网络呼叫会破坏所有感知性能。 If you cannot avoid roundtrip calls you should strive to limit it to at most one for read and at most one for write. 如果您无法避免往返呼叫,则应努力将其限制为最多只能读取一次,最多只能写入一次。 If you find yourself needing to invoke multiple read and multiple write calls over the wire that is highly illustrative of a bad architectural design of the business system. 如果您发现自己需要通过线路调用多个读取和多个写入调用,则可以很好地说明业务系统的体系结构设计不正确。

Lastly in well designed SOA, your system is much more functional than OO. 最后,在设计良好的SOA中,您的系统比OO具有更多的功能。 Functional logic with immutable data / lack of shared state, is what scales. 具有不变数据/缺少共享状态的功能逻辑可以扩展。 The more dependent you are on any shared state the more fragile the system is and starts to actively become anti -scale. 您对任何共享状态的依赖性越强,系统就越脆弱,并开始积极地变成规模。 Being highly stateful can easily lead to systems that fracture at the 20-50 req/s range. 保持高度状态很容易导致系统以20-50 req / s的速率崩溃。 Nominally a single server system should handle 300-500 req/s of real world usage. 名义上,单个服务器系统应能够处理300-500 req / s的实际使用量。

The reason to proxy business services such as this is to follow the trusted subsystem pattern. 代理此类业务服务的原因是遵循受信任的子系统模式。 No user is ever able to authenticate to your business service, only your application is able to authenticate. 没有用户能够对您的业务服务进行身份验证,只有您的应用程序能够进行身份验证。 No user is ever able to determine where your business services are hosted. 没有用户能够确定您的业务服务的托管位置。 Related to this is users should never authorize to business service itself, a business service action should be able to authorize the originator of the request if necessary. 与此相关的是,用户永远不要授权业务服务本身,业务服务操作应该能够授权请求的发起者。 In general this is only needed for fine grained control such as individual records can be barred from a user. 通常,这仅适用于细粒度控制,例如可以禁止用户使用单个记录。


Since clients are remote and untrustworthy (users can maliciously manipulate them whether they're javascript or compiled binaries) they should never have any knowledge of your service layer. 由于客户端是远程且不可信任的(用户可能是恶意脚本,无论是JavaScript还是编译的二进制文件,用户都可以对其进行恶意操纵),因此他们永远不应对服务层有任何了解。 The service layer itself could literally be firewalled off from the entire internet only allowing your web servers to communicate to the service layer. 服务层本身实际上可以从整个Internet进行防火墙保护,仅允许您的Web服务器与服务层进行通信。 Your web server may have some presentation building logic in it, such as seeding your client with userId, name, security tokens etc but it will likely be minimal. 您的Web服务器中可能包含一些表示法构建逻辑,例如,使用userId,名称,安全令牌等为客户端设置种子,但是这可能很小。 It is the web server acting as a proxy that needs to initiate calls to the service layer Web服务器充当代理,需要启动对服务层的调用

Short version , only a controller should call your service layer. 简短版 ,只有控制器可以调用您的服务层。

One exception, if you use a message queuing system like Azure Service Bus for example, depending on security constraints it could be fine by your UI to directly enqueue messages to the ASB as the ASB could be treated as a DMZ and still shields your services from any client knowledge. 一个例外,例如,如果您使用诸如Azure Service Bus之类的消息排队系统,则根据安全约束,UI可以将消息直接排队到ASB中就可以了,因为ASB可以被视为DMZ,并且仍然可以保护您的服务免受任何客户知识。 The main risk of direct queue access is a malicious user could flood your queue for a denial of service type attack (and costing you money). 直接访问队列的主要风险是恶意用户可能会在您的队列中充斥着拒绝服务类型的攻击(并造成金钱损失)。 A non-malicious risk is if you change the queue contract out of date clients could result in numerous dead letters or poison messages 一种非恶意的风险是,如果您过时更改了队列合同,则客户端可能会导致许多死信或有毒消息

I really believe the future of all development are clients that directly enqueue messages but current technology is very lacking for doing this easily and securely. 我真的相信,所有开发的未来都是直接将消息放入队列中的客户,但是目前的技术非常缺乏轻松,安全地执行此操作的能力。 Direct queue access will be imperative for the future of Internet of Things. 对于物联网的未来,直接队列访问必不可少。 Web servers just do not have the capacity to receive continuous streams of events from thousands or millions of light bulbs and refrigerators. Web服务器只是没有能力接收来自成千上万个灯泡和冰箱的连续事件流。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM