protected function putHandler($className, $id)
    {
        $obj = DataObject::get_by_id($className, $id);
        if (!$obj) {
            return $this->notFound();
        }

        if (!$obj->canEdit($this->getMember())) {
            return $this->permissionFailure();
        }

        $reqFormatter = $this->getRequestDataFormatter($className);
        if (!$reqFormatter) {
            return $this->unsupportedMediaType();
        }

        $responseFormatter = $this->getResponseDataFormatter($className);
        if (!$responseFormatter) {
            return $this->unsupportedMediaType();
        }

        try {
            /** @var DataObject|string */
            $obj = $this->updateDataObject($obj, $reqFormatter);
        } catch (ValidationException $e) {
            return $this->validationFailure($responseFormatter, $e->getResult());
        }

        if (is_string($obj)) {
            return $obj;
        }

        $this->getResponse()->setStatusCode(202); // Accepted
        $this->getResponse()->addHeader('Content-Type', $responseFormatter->getOutputContentType());

        // Append the default extension for the output format to the Location header
        // or else we'll use the default (XML)
        $types = $responseFormatter->supportedExtensions();
        $type = '';
        if (count($types)) {
            $type = ".{$types[0]}";
        }

        $urlSafeClassName = $this->sanitiseClassName(get_class($obj));
        $apiBase = $this->config()->api_base;
        $objHref = Director::absoluteURL($apiBase . "$urlSafeClassName/$obj->ID" . $type);
        $this->getResponse()->addHeader('Location', $objHref);

        return $responseFormatter->convertDataObject($obj);
    }