WS API: questions about deleting Attachments and AttachmentContent

Document ID : KB000057532
Last Modified Date : 14/02/2018
Show Technical Document Details

Issue

Attachment and AttachmentContent are separate objects in WS API.

1. If an attachment is deleted will its content be also deleted, or an orphaned AttachmentContent object remains in the system unless it is explicitly deleted?
2. If an attachment content is deleted will the relevant attachment be also deleted, or an empty attachment object remains in the system?

Resolution

1. If an attachment is deleted will its content be also deleted, or an orphaned AttachmentContent object remains in the system unless it is explicitly deleted?

Content of the attachment is automatically deleted when the related attachment is successfully deleted.

There are two separate objects in WS API related to this discussion: Attachment, which has a Content attribute, and a separate AttachmentContent object.
Content attribute points to the relevant AttachmentContent object.
Here is a Ruby example based on CA Agile Central Ruby REST Toolkit that deletes a specific attachment:
?
require 'rally_api'

#Setup custom app information
headers = RallyAPI::CustomHttpHeader.new()
headers.name = "My Utility"
headers.vendor = "Nick M RallyLab"
headers.version = "1.0"

# Connection to CA Agile Central
config = {:base_url => "https://rally1.rallydev.com/slm"}
config[:username] = "user@co.com"
config[:password] = "secret"
config[:workspace] = "W1"
config[:project] = "P1"
config[:version] = "v2.0"
config[:headers] = headers #from RallyAPI::CustomHttpHeader.new()

@rally = RallyAPI::RallyRestJson.new(config)

query = RallyAPI::RallyQuery.new()
query.type = :attachment
query.workspace = {"_ref" => "https://rally1.rallydev.com/slm/webservice/v2.0/workspace/111" } #use valid workspace oid 
query.query_string = "(ObjectID = \"12345\")" 
query.fetch = "ObjectID"

result = @rally.find(query).first
puts result["ObjectID"]

result.delete #success

Let's say we have an artifact in CA Agile Central of type defect with one attachment.

Replace ObjectIDs in this example with those valid in your subscription if you want to follow the steps outlined below and delete? attachments and attachment content in your subscription.

Paste a valid defect endpoint in the browser

https://rally1.rallydev.com/slm/webservice/v2.0/Defect/12353153797

The json includes Attachments collection object:

Count 1 indicates that there is only one element in this collection. Click on the reference. This single attachment's URL is:
https://rally1.rallydev.com/slm/webservice/v2.0/attachment/26764658198

The json of the attachment includes a reference to AttachmentContent object:
https://rally1.rallydev.com/slm/webservice/v2.0/attachmentcontent/26764658199

If a Ruby code example above is run with this query:
query.query_string = "(ObjectID = \"26764658198\")" 
and the attachment is successfully deleted, pasting the following URLs in the browser shows that both?the attachment and the content are gone:

https://rally1.rallydev.com/slm/webservice/v2.0/attachment/26764658198

{
  • OperationResult:?{
    • _rallyAPIMajor:?"2",
    • _rallyAPIMinor:?"0",
    • Errors:?[
      • "Cannot find object to read"
      ],
    • Warnings: [ ]
    }
}
https://rally1.rallydev.com/slm/webservice/v2.0/attachmentcontent/26764658199
{
  • OperationResult:?{
    • _rallyAPIMajor:?"2",
    • _rallyAPIMinor:?"0",
    • Errors:?[
      • "Cannot find object to read"
      ],
    • Warnings: [ ]
    }
}

2. If an attachment content is deleted will the relevant attachment be also deleted, or an empty attachment object remains in the system?

If an attachment content is deleted, an empty attachment object remains in the system.

Here is a fragment of code example that deletes attachment content:
?
@rally = RallyAPI::RallyRestJson.new(config)

query = RallyAPI::RallyQuery.new()
query.type = :attachment
query.workspace = {"_ref" => "https://rally1.rallydev.com/slm/webservice/v2.0/workspace/1111" } #use valid workspace oid 
query.query_string = "(ObjectID = \"56789\")" 
query.fetch = "ObjectID,Content"

result = @rally.find(query).first
puts result["ObjectID"]
puts result["Content"]["_ref"]
content = result["Content"]
content.delete

After the code is run, we copy the output of this line from the terminal
puts result["Content"]["_ref"]
https://rally1.rallydev.com/slm/webservice/v2.0/attachmentcontent/26764657898

and paste it in the browser,? "Cannot find object to read" is returned:

{
  • OperationResult:
    ?
    {
    • _rallyAPIMajor: "2",
    • _rallyAPIMinor: "0",
    • Errors:
      ?
      [
      • "Cannot find object to read"
      ],
    • Warnings: [ ]
    }
}

If we download the respective attachment from CA Agile Central, it will show size 0.
?