I was investigating the documentation and it's not clear for me what exactly is the difference between conversationThread and conversation on Microsoft Graph (v1.0 Reference)?
The documentation for conversation states: A conversation is a collection of threads, and a thread contains posts to that thread. All threads and posts in a conversation share the same subject. The relationship is threads.
Here I assume that same subject means under the umbrella of that conversation?
In another hand, the documentation for conversationThread states: A conversationThread is a collection of posts. The last post's recipients collection is the aggregated recipients of the entire thread. A thread can have a growing collection of recipients. A new thread is created when a recipient is removed from the thread. The relationship is posts. Not a clue here, if conversationThread is a collection of posts, that's pretty much the same of what conversation offers?
What I have been trying to do? I'm using Fiddler to play with the HTTP requests groups/<id>/conversations and groups/<id>/threads and I've noticed that the most obvious difference is that threads has a isLocked property which conversations doesn't. Then the question popped up in my mind: "Why and in which circumstances I'd be using group/<id>/threads over group/<id>/conversations anyway?". Maybe because I don't understand the difference between conversationThread and conversation.
Please bare in mind I'm a novice on Microsoft Graph and I'd really appreciate if the community could help me to clarify this question.
Many thanks in advance!
EDIT
Using Fiddler, we've managed to create a new thread. However, rather than creating a new thread in a specified conversation as expected, it creates a new conversation to go with the new thread. A have also attempted creating a new post within the newly created thread but i am facing the following error: "The OData request is not supported" using the request body: "
{
"body": {
"contentType": "application/json",
"content": "This is a test"
}
}"
Thank you for your interest and trying out the group conversations API. I'd like to share my understanding with you regarding your few questions:
"What exactly is the difference between conversationThread and conversation on Microsoft Graph (v1.0 Reference)?"
"Why and in which circumstances I'd be using group//threads over group//conversations anyway?"
In terms of group conversation feature design, as you probably have read, a post is always a part of some thread and that thread part of some conversation. In terms of API support, the API provides "parity" between conversation and thread - the convenience of not requiring you to always reference the parent conversation for a post. Just to be clear, that doesn't mean you can have a post or thread without a parent conversation; you just don't necessarily have to reference the parent conversation every time you access an existing thread or post. I'll start with creating a post:
If you want to start posting to a new conversation, there are a few ways to do it, for your convenience:
(a) You can first create a conversation (POST /groups//conversations). You would specify a new thread and post in the request body. A successful query would create that new conversation, thread and post.
(b) Or, you can create a thread without referencing any existing conversation (POST /groups//threads). You would specify the new thread and post in the request body. A successful query would create a new conversation containing that new thread and post.
After a post is created, you can use its ID to get, reply, forward, create or access attachments for that post by specifying both the parent conversation and thread, or just by specifying the parent thread. This is the so-called conversation and thread parity.
"Here I assume that same subject means under the umbrella of that conversation?"
Yes, a conversation, its threads and posts all share the same subject. I think "subject" here is represented by the topic property.
"if conversationThread is a collection of posts, that's pretty much the same of what conversation offers?"
What pulls threads and posts together under a conversation is the "subject". Think of it in the end user scenario - once a person on a conversation changes the subject, that person starts a new conversation.
In a conversation, sometimes a participant can spin off a side thread with a subset of the original participants. That constitutes a new "thread", as the subject has remained the same, just fewer participants.
Such is the feature design difference between conversations and threads. In terms of API functionality, you can reply to a thread (or post) and reference the parent thread, but you cannot reply by just referencing the parent conversation.
"have also attempted creating a new post within the newly created thread"
I suspect you did a POST to an existing thread to try to create a post?
If that's the case, I'd like to point out that you cannot use POST to create a new group post. You can get a post created in one of the following ways:
- When creating a new conversation (POST /groups//conversations)
- When creating a new thread (POST /groups//threads)
- When replying to a thread
- When replying to a post
Hope that helps.
Angelgolfer-ms
Related
Would someone be able to direct me to the correct API that I could use to mark a Student Subject and Course to ‘Complete’?
I found out ‘Grade.CourseCompletion’ API could serve the purpose, but not sure if that's correct understanding.
Also, where could I find below highlighted fields and how I can change their value?
"OrgUnitId": <number:D2LID>,
**"CompletionId": <number:D2LID>,**
"UserId": <number:D2LID>,
**"CompletedDate": <string:UTCDateTime>,**
"ExpiryDate": <string:UTCDateTime>|null
Thanks
Vivek
You cannot change a CompletionId; it's an entity identifier for the completion record that gets created by Brightspace when the completion record gets created. (I believe you could, however, delete a completion record and create a new one.)
You use the POST and PUT routes for course completion to create new (or update existing) course completion records. The JSON structure you provide when you do a create or update operation allows you to specify a CompletedDate.
I would also point out that D2L has a developer-specific community to support clients and partners and you may find that answers to your questions are more timely there.
I have two questions on how the MVC works. I'm pretty sure I should add several resources, but I'm just coming to this conclusion and wanted to ask first to get a better understanding.
First question:
I have two models, user and subject. Users can enter subjects into the database. For each subject there are 5 data entry forms (Baseline, 3month, 6month,...) that are about 100-200 questions each (The relationship would be each subject has 1 of each data entry form). Should each data entry form be a new resource?
Second Question:
Lets say I want to randomize a few subjects into a group:
From the view, the user enters the amount of subjects to be randomized into a group, as well as the group name to be assigned. The form tag specifies an action I created, just for this function, called randomize.
From the controller, randomize uses the params sent from the view to query the database, and then to update each record to reflect the group. Instead of creating a new action for the randomize function, should I create a new resource for it? And as a side note, should any of these calculations be done in the model (other than defining the variables)?
Thank you for your time. Any help would be greatly appreciated. I am officially over-whelmed by all of the information I'm learning about this...but I feel that I'm really close to actually understanding the MVC.
I'll answer your second question first.
You should be creating controllers to handle CRUD tasks for resources. In this question you ask about creating a "Group". Regardless of whether this is an actual resource, or just a modification to a collection of other resources, you have the concept of creating a "Group", probably reading/updating a "group" and certainly deleting one.
Based on this, I would rather have a RandomGroup controller which I can call using a standard REST interface, rather than some #randomize action stuffed in the side of another controller.
As for your first question ... maybe, maybe not.
It really depends on whether an data entry form has any business logic of its own. If it doesn't then there's no harm it being part of a large object. But if your tests and code start to become too complex within the Subject model you may want to split it out into multiple models or at least multiple modules included into that model.
Perhaps you could consider that "Baseline", "3month", "6month" are all the same ... aside from their lead time. Perhaps that is a model in itself, and Subject could has_many :forms ??
Food for thought.
I expect that this is a rather common problem seeing as a lot of sites use threaded messaging, but I haven't been able to find anything on the internets.
Basically the way I envision this working is I have a column called thread_id in my messages table. The column is not unique, because obviously a lot of messages will be sharing the same thread. What I'd like to see happen is when I insert a new message, if I specify a thread_id, it uses it as expected, but if I don't, it uses the next available thread_id by auto incrementing the highest value.
So if I have a series of messages with thread ids: 1,1,2,2,3,2,2,3,3,4,2,5,3,3,3,4 and then I insert a row without an id, it would use the id 6.
Is this possible? If not, how do most people accomplish threaded messaging?
Thanks!
One thing you could do is create a wrapper model:
class Thread < ActiveRecord::Base
has_many :messages
end
to act as the parent of your messages. That way, if you know which thread you want to add a message to you can just call #thread.messages.create!(params[:message]). If want to add a message to a new thread, you can just create a new thread and add the message in the same way. You won't have to worry about assigning an incremented thread_id to the message, as the Thread model will automatically auto-increment the id of the new thread and assign it to the message.
This method also allows you keep track of info about the thread, like when the thread was created by having a "created_at" column, if that at all interests you.
Working in JBoss AS7, using Conversation Scope to manage the user's interactions within a browser tab.
I note that my pages get ?cid parameters appended. This is great - until the user bookmarks the page then tries to return to it! The Conversation Filter gives a "No such conversation" message.
Is there a better way of managing conversations? Perhaps an implementation or a switch to make it use hidden fields (with appropriate care in AJAX)? Alternatively I'll have to start trying to intercept the Conversation Exception or modify the filter!
Thanks
- Richard
Further:
I'm intercepting the BeforeRestoreView event for other purpose (login handling mainly). You'd think this would work:
/**
* #return true if there is no valid Conversation context.
*/
private boolean conversationNotActive()
{
Context conversationContext = m_beanManager.getContext(ConversationScoped.class);
return !conversationContext.isActive();
}
But I can't get the context to ask if if it's active! Will just throw a Try-Catch in for now.
We now take a two pronged approach.
A quite complex conversation manager detects a bad conversation Id and takes appropriate action. It responds currently to the After Restore View event. I'd like to move it earlier but am having problems deriving the view ID at this stage. I've written a JSF to CDI bridge to pass the events to CDI. SeamFaces would do the same, but proved too heavyweight for us.
For a normal GET the Conversation Manager redirects to self without the cid parameter in order to cause a new conversation to be started. For a postback it returns an HTTP 410 error. The detection of dead conversation is as above. We could use a more random conversation Id when we create conversations to try to prevent collision if an ID is reused.
The Conversation Manager will also start a conversation depending on metadata it holds about the pages. (All pages under /forms/ require a conversation in our application). It uses redirect when it does this to ensure that the CID parameter is everywhere it needs to be. This may become unnecessary if I can solve the problem of getting the form ID before RestoreView phase.
We use the browser history API to remove the cid from the user's browser URL window.
Consider the typical blog with objects Post and Comment.
For a DDD demo example i have been building i have (till now) found that both the entities Post and Comment have been appropriate for the same aggregate- the Post aggregate. But now i'm not so sure..
In my controllers i am finding, like you would expect, that i need to add and remove Comments from Posts. With my current model i am not tracking the identity of a Comment globally (like the Blue Book suggests). You you might expect that my action to delete a Comment may look like this:
public ActionResult DeleteComment(int postID, int commentID)
Obviously i need the Post's id to retrieve it from the repository and the identifier for the particular Comment on that Post that i want to delete.
My problem is the body of the DeleteComment( action:
Is it ok to traverse the Post with a query mechanism to get the Comment for deletion? like this:
var comment = this._postRepo.WithID(postID).Comments
.SingleOrDefault(c => c.ID == commentID);
this._postRepo.Delete(comment);
return RedirectToAction("detail", new { id = postID });
..or should i be selecting the Comment from the repo similar to this?:
var comment = this._postRepo.CommentWithID(commentID)
..or:
var comment = this._postRepo.CommentWithID(postID, commentID)
The two above examples might seem a little silly since i shouldn't need the Post ID if i can track the Comment globally. But then if i'm tracking the Comment globally, shouldn't it have it's own aggregate and then is that right when Post and Comment seem to go together?
As others have said, it depends greatly on whether a comment has any meaning outside of a Post. I tend to think that it does, for several reasons. First, things other than posts can conceptually be commented upon in a normal blog engine (e.g. an image, a news item, another comment). Second, as was also brought up, you often see widgets of just comments, which are independent of their posts. I also think that this scenario makes the decisions you're agonizing over a bit more trivial.
That said, if you do choose to make them one aggregate, then remember that a repository will often load the entire aggregate when making queries, relying on mechanisms like caching and such to make that efficient. So your scenario would be a query for a post, followed by a search of that post's comments for the 'right' comment to edit/delete/whatever.
In my opinion , comment should be part of Post Aggregate, but comment should be entity, bcoz two comment with the same answer is still two separate comment.
If you create comment as separate aggregate where comment is root then, comment will have store method that means any body can create comment but the basic idea is comment should not be created without its post.Comment is related with post.
If you think logically , Comment cannot be evolve it's own. That means when commented is created it should be part of post.
The question is whether a comment has any meaning outside of the post aggregate. IMHO, there isn't any, so I think you shouldn't move the comment to its own aggregate.