+ Start a Discussion
dke01dke01 

System.SObjectException: Field is not writeable: Attachment.ParentId

I want to make a reusable component I can use to upload files.

 

I want to set the attachment.ParentID but do not know that as the file may be uploaded before the object is inserted.  

 

I thought I would be able to add the attachment to a Temporary object.  wait for the newly inserted object to get an ID  when set the ParentID  and then call an Update.

 

 

But I get the error  Field is not writeable: Attachment.ParentId  anyway around this,. Why does force.com allow ParentID to change?

 

Is there a way I can getNextID()   so before I insert an object I know what its ID will be?

Message Edited by dke01 on 22-03-2010 03:48 PM
Best Answer chosen by Admin (Salesforce Developers) 
dke01dke01

Gezz, that is a lot of code, thank for your help  (and sorry for the late reply)

All Answers

TomSnyderTomSnyder

hope this helps:

 

 

<apex:actionFunction action="{!gohome}" name="done"/> <c:SiteAttachment maxAttachments="5" showAttachments="true" parentId="{!SelectedCert.qualificationId}" allowDelete="false" accept="application/pdf, application/x-zip-compressed, application/zip, application/msword, application/vnd.ms-excel" InstuctionsUrl="{!URLFOR($Resource.file_upload_instructions)}" CompleteOnClick="javascript:done();" />

 

 

 

 

 

<apex:component id="satt" allowDML="true" controller="ctrlSiteAttachment">
<apex:attribute name="parentId" type="string" description="value" required="true" assignTo="{!parentId}"/>
<apex:attribute name="accept" type="string" description="Comma diliminated list of context-types accepted" required="true" assignTo="{!accept}"/>
<!-- <apex:attribute name="onComplete" type="ApexPages.Action" description="onComplete Listener" required="true"/> -->
<apex:attribute name="CompleteOnClick" type="string" description="Complete OnClick event (JS)" required="false" default="void();"/>
<apex:attribute name="CompleteLabel" type="string" description="label on complete button" required="false" default="Done"/>
<apex:attribute name="showAttachments" type="boolean" description="value" required="false" default="false" />
<apex:attribute name="allowDelete" type="boolean" description="Allow deletion of an attachment (showAttachments must be try)" required="false" default="true" />
<apex:attribute name="maxAttachments" type="integer" description="maximum number of attachment" required="false" default="1" />
<apex:attribute name="InstuctionsUrl" type="string" description="Url for Upload Instructions" required="false" />

<!-- ===============================================================
SHOW Attachments
==================================================================-->
<apex:outputpanel id="attlist" rendered="{!showAttachments}">
<table width="100%">
<tr><td style="text-align: left;"><h3 class="pageHeader">{!$ObjectType.attachment.labelPlural}</h3></td></tr>
<apex:outputpanel rendered="{!!isBlank(InstuctionsUrl)}">
<tr><td style="text-align: right;"><a target="_blank" href="{!InstuctionsUrl}">File Upload Instructions</a></td></tr>
</apex:outputpanel>
</table><BR/>
<apex:datatable cellpadding="2px" var="att" value="{!Attachments}" width="100%" rowClasses="odd,even" rendered="{!Attachments!=null}" styleClass="thinborder" rules="cols">
<apex:column >
<apex:facet name="header">&nbsp;</apex:facet>
<apex:commandLink action="{!deleteAttachment}" value="X" rendered="{!allowDelete}" >
<apex:Param name="selectAtt" assignTo="{!selectAtt}" value="{!att.id}"/>
</apex:commandLink>
</apex:column>
<apex:column >
<apex:facet name="header">{!$ObjectType.attachment.fields.name.label}</apex:facet>
<apex:outputText value="{!att.name}" />
</apex:column>
<apex:column >
<apex:facet name="header">{!$ObjectType.attachment.fields.createddate.label}</apex:facet>
<apex:outputText value="{!att.createddate}"/>
</apex:column>
<apex:column >
<apex:facet name="header">{!$ObjectType.attachment.fields.BodyLength.label} (bytes)</apex:facet>
<apex:outputText escape="false" value="{!att.BodyLength}"/>
</apex:column>
</apex:datatable>
<apex:outputpanel rendered="{!Attachments.size==0}">
No {!$ObjectType.attachment.labelPlural}.
</apex:outputpanel>

</apex:outputpanel>

<!-- ===============================================================
UPLOAD FILE
==================================================================-->
<apex:outputpanel id="upld" rendered="{!parentid!=null}">
<apex:actionRegion >
<br/><br/>
<apex:outputLabel value="{!$ObjectType.attachment.label}:" />
<apex:inputFile value="{!newAttachment.Body}" filename="{!newAttachment.name}" contentType="{!newAttachment.contentType}" />
<br/><br/>
<!-- Messages -->
<b>
<apex:outputText id="msg1" value="{!$Label.site.file_not_found}" rendered="{!AttMsg=='file_not_found'}"/>
<apex:outputText id="msg2" value="{!AttMsg}" rendered="{!!(maxAttachments<=totalAttachments)}"/>
<apex:outputText id="msg3" value="{!$Label.site.error2}: {!$Label.site.sorry_for_inconvenience}" rendered="{!AttMsg=='sorry_for_inconvenience'}"/>
<apex:outputText id="msg4" value="ContentType: {0} is not accepted." rendered="{!AttMsg=='invalid_contenttype'}">
<apex:param value="{!invalidContentType}"/>
</apex:outputText>
<apex:outputText id="otmax" value="limit_exceeded [{0}]" rendered="{!(maxAttachments<=totalAttachments)}">
<apex:param value="{!maxAttachments}"/>
</apex:outputText>
<apex:outputText id="msgUpSuccess" value="File uploaded succesfully." rendered="{!AttMsg=='upload_successful'}"/>
<apex:outputText id="msgdlSuccess" value="File deleted succesfully." rendered="{!AttMsg=='delete_successful'}"/>
</b>
<br/><br/>
<apex:commandbutton id="upload" action="{!uploadAttachment}" value="{!$Label.site.submit} {!$ObjectType.attachment.labelPlural}" disabled="{!(maxAttachments<=totalAttachments)}" />
&nbsp;&nbsp;<input type="button" value="{!CompleteLabel}" onclick="{!CompleteOnClick}" />
</apex:actionRegion>
</apex:outputpanel>

</apex:component>

 

 


public class ctrlSiteAttachment {
public Attachment newAttachment { get; set; }
public string AttMsg { get; set; }
public string parentId { get; set; }
public string Accept { get; set; }
public ID selectAtt { get; set; }
public string invalidContentType { get; set; }

public ctrlSiteAttachment() {
newAttachment=new Attachment();
selectAtt=null;
}
private LIST<Attachment> siteAttachments;
///////////////////////////////////////////////////////////////////////////////////////////////

public integer totalAttachments {
GET {
if (siteAttachments==null)
refreshAttachments();
return siteAttachments.size();
}
}
///////////////////////////////////////////////////////////////////////////////////////////////
public LIST<Attachment> Attachments {
GET { return siteAttachments; }
}



///////////////////////////////////////////////////////////////////////////////////////////////
public void deleteAttachment() {
if (selectAtt!=null) {
Database.delete(selectAtt);
selectAtt=null;
}
refreshAttachments();
AttMsg='delete_successful';
}
///////////////////////////////////////////////////////////////////////////////////////////////
public PageReference uploadAttachment() {
AttMsg='';
invalidContentType='';
//Validate a file has been uploaded

if (newAttachment==null || newAttachment.body==null) {
AttMsg='file_not_found';
newAttachment = new Attachment();
return null;
}

//Validate ContentType
Accept=Accept.toLowerCase();
SET<string> ctypes = Util.splitToSet(Accept,'(,\\s*)');
if (newAttachment.ContentType==null || (! ctypes.contains(newAttachment.ContentType.toLowercase()) ) ) {
invalidContentType=newAttachment.ContentType;
AttMsg='invalid_contenttype';
newAttachment = new Attachment();
return null;
}

if (parentid!=null) {
try {
newAttachment.ParentId = parentid;
insert newAttachment;
AttMsg='upload_successful';
refreshAttachments();
}
catch (Exception ex ) {
AttMsg=String.valueOf(ex);
}
}
else
AttMsg='sorry_for_inconvenience';

newAttachment = new Attachment(); //clear out viewstate (transient will not work)
return null;
}

///////////////////////////////////////////////////////////////////////////////////////////////
private void refreshAttachments() {
if (parentId!=null) {
siteAttachments = new LIST<Attachment>([
SELECT Id, Name,CreatedDate, CreatedById, ContentType, BodyLength
FROM Attachment
WHERE CreatedById = : UserInfo.getUserId()
AND ParentId = :parentId
]);

}
else
siteAttachments = new LIST<Attachment>();
}
}

 

 

 

 

 

Message Edited by tesii on 03-22-2010 01:38 PM
Message Edited by tesii on 03-22-2010 01:42 PM
dke01dke01

Gezz, that is a lot of code, thank for your help  (and sorry for the late reply)

This was selected as the best answer