简体   繁体   English

如何使用Restful API提交深层嵌套资源(HATEOAS)

[英]How to Submit Deeply Nested Resource using Restful APIs (HATEOAS)

Say I have an application resource that contains contact details resources, and contact details contains addresses resources. 假设我有一个包含联系详细信息资源的应用程序资源,联系人详细信息包含地址资源。

Eg. 例如。

Application
--> Name
--> Application Amount
--> Application Contacts 
--> --> Contact 1
--> --> --> Address
--> --> Contact 2
--> --> --> Address

When doing a POST to Application, I am creating the root application. 在对应用程序执行POST时,我正在创建根应用程序。 For all sub resources like Application Contacts, I do a POST to create Contact 1 etc... 对于所有子资源,如应用程序联系人,我做一个POST来创建联系人1等...

My question is, Application = to submit somewhere for processing, but I do not want to submit it before everything is filled in, aka all children resources. 我的问题是,Application =提交某个地方进行处理,但我不想在填写所有内容之前提交它,也就是所有子资源。

So the order of submission
1) Create Application Resource --> POST /Application --> Get ID
2) Create Contact 1 Resource --> POST /Application/id/Contacts --> Get ID
3) Create Contact 1 Address Resource --> POST /Application/id/Contacts/id/Addresses
4) Create Contact 2 Resource --> POST /Application/id/Contacts --> Get ID 
5) Create Contact 2 Address Resource --> POST /Application/id/Contacts/id/Addresses
6) DECIDE TO SUBMIT HERE <--- ?? HOW?

Josh 玩笑

Your design isn't RESTful. 您的设计不是RESTful。 Your resources are probably 1-to-1 mappings with your business entities? 您的资源可能与您的业务实体进行一对一的映射? I don't advise this, because it exposes the guts of your domain model to the outside world, which can cause versioning problems. 我不建议这样做,因为它会将您的域模型的内容暴露给外部世界,这可能会导致版本问题。 It also makes problems like this harder than they need to be - although you might be using a REST framework that forces this design on you :-( . 它也会使这样的问题变得比他们需要的更难 - 尽管你可能正在使用一个强制这个设计的REST框架:-(。

The thing to remember is that resources in REST are abstract representations of the element of your domain model that you want the outside world to see, and they may well need mapping and transformation before they can be converted to domain objects. 需要记住的是,REST中的资源是您希望外部世界看到的域模型元素的抽象表示,并且在将它们转换为域对象之前,它们可能需要映射和转换。 They can be arbitrarily complex. 它们可以是任意复杂的。

The solution here, I'd say, is to let the POST to create the Application also create the Contacts and their Addresses. 我要说的是,这里的解决方案是让POST创建应用程序创建联系人及其地址。 The client can then either supply URLs for existing Contacts and Addresses (which the server can dereference to the domain objects), or the necessary details to create new ones in a single POST. 然后,客户端可以为现有的联系人和地址(服务器可以取消引用域对象)提供URL,或者在单个 POST中创建新的URL。 Then the responsibility of creating and associating the entities in a transactional way falls upon the server. 然后,以事务方式创建和关联实体的责任落在服务器上。 It just returns a reference to the URL that identifies the new Application. 它只返回对标识新Application的URL的引用。 If you need to know the URLs for the Contacts, then you re-GET the Application, and it will contain them. 如果您需要知道联系人的URL,那么您重新获取应用程序,它将包含它们。

Assuming a JSON mime type for your resource, the initial POST might look like this: 假设您的资源使用JSON mime类型,初始POST可能如下所示:

{
    Name: "Application name",
    Amount: "123.00",
    Contacts: [
        {
            Name: "Contact name",
            Address: {
                HouseNumber: "45",
                StreetName : "Sesame Street"
            }
        }
    ]
}
Return: {href:  “/Application/6789”}

A GET to /Application/6789 would then return something like: 然后GET到/ Application / 6789将返回如下内容:

{
    Name: "Application name",
    Amount: "123.00",
    Contacts: [
        { mimeType: "application/vnd.com.myStuff.contact+json", href: "/Contact/203" }
    ]
}

Hope I understood your question correctly. 希望我能正确理解你的问题。 Let me know if I missed the point and can always come back with something new. 让我知道,如果我错过了这一点,可以随时回来一些新的东西。

So if all the “sub-resources” are already created from step-1 to step-5. 因此,如果已经从步骤1到步骤5创建了所有“子资源”。 In each of the step, there should be a returned ID to confirm the successful creation of the resource. 在每个步骤中,都应该有一个返回的ID来确认资源的成功创建。 Like, 喜欢,

POST /Application
Return: {appid:  “/Application/id”}

Thus, as soon as the step-5 POST returns, the last resource is created. 因此,只要步骤5 POST返回,就会创建最后一个资源。 Then the next step is to start the application 'processing'. 然后下一步是启动应用程序“处理”。

“Application Processing” could be thought as a resource, and the business actions are: “create the processing” resource and “Check for processing results” “应用程序处理”可以被视为一种资源,业务操作是:“创建处理”资源和“检查处理结果”

They can be modeled using POST and GET respectively on the 'Processing' resource. 它们可以分别在“处理”资源上使用POST和GET建模。

To create the processing resource 创建处理资源

POST /Application/id/Processing
Return:  {processingid: “/Application/id/Processing/id”}

To check the processing resource 检查处理资源

GET /Application/id/Processing/id
Return: {processingid: “/Application/id/Processing/id”, <other info>}

To get the whole application back, 要恢复整个应用程序,

GET /Application/id
Return: {all info on the application including processing status as well…}

Hope this help. 希望这有帮助。

Most likely you will have a status field of some sort to indicate whether application has been submitted or not. 您很可能会有某种状态字段来指示是否已提交申请。 In this case I would suggest the following two approaches: 在这种情况下,我建议采用以下两种方法:

1) Post to an application resource with its status field set to a proper value to indicate your intent: 1)发布到应用程序资源,并将其状态字段设置为适当的值以指示您的意图:

POST /application/654321
status=submitted...

Here is the quote from Fielding Dissertation : 这是Fielding Dissertation的引用:

"REST components perform actions on a resource by using a representation to capture the current or intended state of that resource and transferring that representation between components." “REST组件通过使用表示捕获该资源的当前或预期状态并在组件之间传输该表示来对资源执行操作。”

2) Post an application to a specific collection /submittedapplications which you can also use to search your submitted apps via GET: 2)将应用程序发布到特定的集合/提交的应用程序,您也可以使用它来通过GET搜索您提交的应用程序:

POST /submittedapplications
id=654321...

Since there are most likely additional processing steps beyond just updating the application resource you should use POST verb to indicate that double submission is not OK. 由于除了更新应用程序资源之外,很可能还有其他处理步骤,因此您应该使用POST动词来指示双重提交不正常。

BTW both approaches are not mutually exclusive, you can certainly implement both in the same API. BTW这两种方法并不相互排斥,您当然可以在同一API中实现这两种方法。

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

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