Index: fluid-engage-core/components/artifactView/js/ArtifactView.js
===================================================================
--- fluid-engage-core/components/artifactView/js/ArtifactView.js	(revision 9320)
+++ fluid-engage-core/components/artifactView/js/ArtifactView.js	(working copy)
@@ -61,23 +61,10 @@
      * @param {Object} that,the component
      */    
     var renderArtifactPage = function (that) {
-        var artifact = that.model.artifact;
-        
-        var tree = buildComponentTree(artifact);
-        
-        // Attach collect handler
-        tree.children.push({
-        	ID: "artifactCollectLink",
-        	decorators: [{
-                type: "jQuery",
-                func: "click",
-                args: that.collectView.collectHandler
-            }]
-        });
-
+        var tree = buildComponentTree(that.model.artifact);
         fluid.selfRender(that.locate("renderScope"), tree, {
             cutpoints: that.options.cutpoints, 
-            model: artifact, 
+            model: that.model.artifact, 
             debug: true
         });
     };
@@ -105,8 +92,8 @@
             that.locate("collectArtifact"),
         	{
             	artifactCollected: that.options.artifactCollected,
-        		museum: that.options.museum,
-        		artifactId: that.options.model.id
+        		museum: that.model.museum,
+        		artifactId: that.model.artifact.id
         	}
         ]);
 
Index: fluid-engage-core/components/artifactView/js/ArtifactCollectView.js
===================================================================
--- fluid-engage-core/components/artifactView/js/ArtifactCollectView.js	(revision 9320)
+++ fluid-engage-core/components/artifactView/js/ArtifactCollectView.js	(working copy)
@@ -49,17 +49,11 @@
      * "uncollect"
      */
     var switchCollectLink = function (that, collect) {
-        // TODO: that.locate won't work on a rendered DOM, we need to make it work
-        var collectLink = fluid.jById(that.options.collectId);
-        if (collectLink.length === 0) {
-            collectLink = that.locate("collect");
-        }
-        
         if (collect) {
-            collectLink.text(that.options.strings.collect);
+            that.collectLink.text(that.options.strings.collect);
             that.options.operation = "POST";
         } else {
-            collectLink.text(that.options.strings.uncollect);
+            that.collectLink.text(that.options.strings.uncollect);
             that.options.operation = "DELETE";          
         }
     };
@@ -70,31 +64,33 @@
      * 
      * @param {Object} that, the component.
      */
-    var confirmCollect = function (that) {
-        // TODO: that.locate won't work on a rendered DOM, we need to make it work
-        var collectLink = fluid.jById(that.options.collectId);
-        var collectStatus = collectLink.next().children();
-        
-        collectStatus.attr("href", "http://" + location.host + compileUsersPath() + 
+    var confirmCollect = function (that) {        
+        that.collectStatus.attr("href", "http://" + location.host + compileUsersPath() + 
                 "/myCollection.html" + "?uuid=" + that.uuid);
-        collectStatus.addClass("active");
+        that.collectStatus.addClass("active");
         
         if (that.options.operation === "POST") {
-            collectStatus.text(that.options.strings.collectedMessage);
+            that.collectStatus.text(that.options.strings.collectedMessage);
         } else {
-            collectStatus.text(that.options.strings.uncollectedMessage);
+            that.collectStatus.text(that.options.strings.uncollectedMessage);
         }
         
-        collectStatus.fadeTo(1000, 1, function () {
-            collectStatus.fadeTo(4000, 0, function () {
+        that.collectStatus.fadeTo(1000, 1, function () {
+            that.collectStatus.fadeTo(4000, 0, function () {
                 switchCollectLink(that, that.options.operation === "DELETE");
-                collectStatus.removeClass("active");
-                collectStatus.removeAttr("href");
+                that.collectStatus.removeClass("active").removeAttr("href");
             });
         });
     };
     
     var setupArtifactCollectionView = function (that) {
+        // Grab the collect/uncollect link from the DOM and bind the collection toggle handler to it.
+        that.collectLink = that.locate("collectLink");
+        that.collectLink.click(function (evt) {
+            that.toggleCollectedArtifact();
+            evt.preventDefault();
+        });
+        
         // TODO: The user subcomponent should be refactored into a handful of stateless functions.
         that.user = fluid.initSubcomponent(that, "user");
 
@@ -117,7 +113,10 @@
     fluid.engage.artifactCollectView = function (container, options) {
         var that = fluid.initView("fluid.engage.artifactCollectView", container, options);
         
-        that.collectHandler = function () {
+        /**
+         * Collects or uncollects the current artifact.
+         */
+        that.toggleCollectedArtifact = function () {
             var url = "http://" + location.host + compileArtifactPath(that.uuid, that.options.museum, that.options.artifactId);
             
             $.ajax({
@@ -126,10 +125,10 @@
                 type: that.options.operation
             });
 
-            setupArtifactCollectionView(that);
             confirmCollect(that);
         };        
                 
+        setupArtifactCollectionView(that);
         return that;
     };
     
Index: fluid-engage-core/framework/js/Engage.js
===================================================================
--- fluid-engage-core/framework/js/Engage.js	(revision 9317)
+++ fluid-engage-core/framework/js/Engage.js	(working copy)
@@ -65,7 +65,7 @@
                     "path": "Description",
                     "func": "getDescription"
                 },
-                "id": "_id"
+                "id": "id"
             },
             mappers: {
                 getDescription: function (value) {
@@ -126,7 +126,7 @@
                 "artifactMention": "value.mention",
                 "artifactRelated": "value.relatedArtifacts",
                 "artifactRelatedCount": "value.relatedArtifactsCount",
-                "id": "_id"
+                "id": "id"
             },
             mappers: {
                 getImage: function (value) {
Index: fluid-engage-kettle/src/main/webapp/services/myCollection/js/collectOperations.js
===================================================================
--- fluid-engage-kettle/src/main/webapp/services/myCollection/js/collectOperations.js	(revision 9317)
+++ fluid-engage-kettle/src/main/webapp/services/myCollection/js/collectOperations.js	(working copy)
@@ -77,26 +77,43 @@
         fluid.myCollection.common.ajaxCall(collectionUrl, function () {}, JSON.stringify(userCollection), "PUT");       
     };
     
-    /**
-     * Creates an acceptor for adding and removing artifacts from the user collection.
-     * 
-     *  @param {Object} config, the JSON config file for Engage.
-     *  @param {Object} app, the Engage application.
-     */
+    var collectArtifact = function (pathInfo, config) {
+        collectOperation(pathInfo, config, addArtifact);
+    };
+    
+    var uncollectArtifact = function (pathInfo, config) {
+        collectOperation(pathInfo, config, removeArtifact);
+    };
+    
     fluid.collectOperations.initAcceptor = function (config, app) {
-        var dataHandler = function (env) {
-            if (env.env.REQUEST_METHOD === "POST") {
-                collectOperation(env.urlState.pathInfo, config, addArtifact);
-            } else if (env.env.REQUEST_METHOD === "DELETE") {
-                collectOperation(env.urlState.pathInfo, config, removeArtifact);
-            } else {
-                fluid.log("Bad HTTP method: " + env.env.REQUEST_METHOD);
-                return [500, {"Content-Type": "text/plain"}, "Bad HTTP method '" + env.env.REQUEST_METHOD + "'"];
+        // Custom acceptor for collecting/uncollecting artifacts. This acceptor responds to URLs like:
+        //        /users/[userId]/collection/[museumId]/artifacts/[artifactId]
+        // POST will collect the specified artifact into the user's personal collection; DELETE will uncollect
+        fluid.engage.mountAcceptor(app, "users", {
+            accept: function (segment, relPath, pathInfo, context) {
+                var pathSegs = pathInfo.pathInfo;
+                var method = context.method;
+                
+                // TODO: This is totally hard coded. A framework-wide solution to resource-oriented URL mounting is needed.
+                if (pathSegs.length !== 6 || pathSegs[2] !== "collection" || pathSegs[4] !== "artifacts") {
+                    return null;
+                }
+                
+                // TODO: This should really be replaced by framework-specific code for matching methods, ala makeAcceptorForResource()
+                if (method !== "POST" || method !== "DELETE") {
+                    return fluid.kettle.METHOD_NOT_ALLOWED;
+                }
+                
+                return {
+                    handle: function (env) {
+                        if (method === "POST") {
+                            collectArtifact(env.urlState.pathInfo, config);
+                        } else {
+                            uncollectArtifact(env.urlState.pathInfo, config);
+                        }
+                    }
+                };
             }
-            return [200, {"Content-Type": "text/plain"}, "OK"];
-        };
-
-        var acceptor = fluid.engage.makeAcceptorForResource("users/.*/collection/.*/artifacts/.*", "", dataHandler);
-        fluid.engage.mountAcceptor(app, "users", acceptor);
+        });
     };
-})(jQuery);
\ No newline at end of file
+})(jQuery);
