Microsoft Land

File Upload Custom Site Field Control – SharePoint 2010 – Part 2

Posted on: May 18, 2011


Please read the Part 1 of this blog entry to understand the Background if needed.

Ok Let’s create a Empty SharePoint Project in Visual Studio 2010 (SharePoint2010.Controls).

Add Mapped SharePoint folders (Right click on solution)

1) Control Templates

2) XML (Template/XML)

Add a new Class for our FileUploadCustomField (FileUploadCustomField.cs -> Namespace SharePoint2010.Controls.FileUploadCustomField).  Below is the code for this class.  We will use a Custom Property i.e., UploadDocumentLibrary to save the name of the document library to where the documents / images have to be uploaded (Selected from the drop down when creating the column).  Inherit this class from Microsoft.SharePoint.SPTextField.

 public FileUploadCustomField(SPFieldCollection fields, string fieldName) : base(fields, fieldName) { Init(); }
public FileUploadCustomField(SPFieldCollection fields, string typeName, string displayName) : base(fields, typeName, displayName) { Init(); }

private string _UploadDocumentLibrary = string.Empty;
public string UploadDocumentLibrary
{
get
{
return _UploadDocumentLibrary;
}
set
{
this.SetCustomProperty(“UploadDocumentLibrary”, value);
_UploadDocumentLibrary = value;
}
}

private void Init()
{
this.UploadDocumentLibrary = this.GetCustomProperty(“UploadDocumentLibrary”) + string.Empty;
}

public override void Update()
{
this.SetCustomProperty(“UploadDocumentLibrary”, this.UploadDocumentLibrary);
base.Update();
}

public override BaseFieldControl FieldRenderingControl
{
get
{
BaseFieldControl fieldControl = new FileUploadCustomFieldControl();
fieldControl.FieldName = InternalName;
return fieldControl;
}
}

Now let’s create the class FieldUploadCustomFieldControl under the same namespace as above. This will have to be Inherited from Microsoft.Sharepoint.WebControls.BaseFieldControl.  Below is the code for this class.

protected FileUpload UploadFileControl;
protected Button UploadButton;
protected Label StatusLabel;
protected HiddenField hdnFileName;

public override void Focus()
{
if (Field == null || this.ControlMode == SPControlMode.Display)
{ return; }
EnsureChildControls();
UploadFileControl.Focus();
}
public override object Value
{
get
{
EnsureChildControls();
if (hdnFileName.Value!=string.Empty)
return hdnFileName.Value;
else if (UploadFileControl.PostedFile != null)
{
string strFileName = UploadFileControl.PostedFile.FileName.Substring(UploadFileControl.PostedFile.FileName.LastIndexOf(“\\”) + 1);
return strFileName;
}
else
{
return null;
}
}
set
{
EnsureChildControls();
hdnFileName.Value = (string)this.ItemFieldValue;
StatusLabel.Text = “File: <a href='” + (string)this.ItemFieldValue + “‘ target=’_blank’>View (” + (string)this.ItemFieldValue + “)</a>”;
}
}

protected override void CreateChildControls()
{
if (Field == null || this.ControlMode == SPControlMode.Display)
{ return; }

base.CreateChildControls();

UploadFileControl = (FileUpload)TemplateContainer.FindControl(“UploadFileControl”);
UploadButton = (Button)TemplateContainer.FindControl(“UploadButton”);
StatusLabel = (Label)TemplateContainer.FindControl(“StatusLabel”);
hdnFileName = (HiddenField)TemplateContainer.FindControl(“hdnFileName”);

UploadButton.Click += new EventHandler(UploadButton_Click);

if (hdnFileName.Value==string.Empty)
StatusLabel.Text = “Select file and click on upload.”;
else
StatusLabel.Text = “File: <a href='” + hdnFileName.ToString() + “‘ target=’_blank’>View (” + hdnFileName.ToString() + “)</a>”;
Controls.Add(StatusLabel);
}

protected void UploadButton_Click(object sender, EventArgs e)
{
SPWeb sourceWeb;

SPSite sourceSite = SPControl.GetContextSite(Context);
sourceWeb = sourceSite.AllWebs[“/”];
sourceWeb.AllowUnsafeUpdates = true;
FileUploadCustomField _field = (FileUploadCustomField)this.Field;
SPList objList = sourceWeb.Lists[_field.UploadDocumentLibrary];
SPFolder destFolder = objList.RootFolder;
try
{
if (UploadFileControl.PostedFile == null) return;
string strFileName = UploadFileControl.PostedFile.FileName.Substring(UploadFileControl.PostedFile.FileName.LastIndexOf(“\\”) + 1);

Stream fStream = UploadFileControl.PostedFile.InputStream;

SPFile objFile = destFolder.Files.Add(strFileName, fStream, true);
objFile.Item.UpdateOverwriteVersion();

StatusLabel.Text = “Upload File :: Success <a href='” + “/” + objFile.ParentFolder + “/” + strFileName + “‘ target=’_blank’>View (” + “/” + objFile.ParentFolder + “/” + strFileName + “)</a>”;
hdnFileName.Value = “/” + objFile.ParentFolder + “/”  + strFileName;
sourceWeb.Dispose();
}
catch (Exception ex)
{
StatusLabel.Text = “Upload File :: Failed ” + ex.Message;
}

}

protected override string DefaultTemplateName
{
get
{
return “FileUploadControlTemplate”;
}
}

Now, see the DefaultTemplateName property that we are overriding.  We are returning “FileUploadControlTemplate” as the Template name.  Let’s create this template (an ASCX file that needs to go under Control templates folder – An user control).  Delete the .CS files for this as we don’t need them.

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register Tagprefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register Tagprefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” %>

<SharePoint:RenderingTemplate ID=”FileUploadControlTemplate” runat=”server”>
<Template>
<asp:FileUpload ID=”UploadFileControl” runat=”server” CssClass=”ms-ButtonHeightWidth” Width=”250px” />
<asp:Button ID=”UploadButton” runat=”server” CssClass=”ms-ButtonHeightWidth” Width=”50px” CausesValidation=”false” Text=”Upload”/>
<asp:Label ID=”StatusLabel” runat=”server” Width=”300px” />
<asp:HiddenField ID=”hdnFileName” runat=”server” />
</Template>
</SharePoint:RenderingTemplate>

Now we have Field and Field Control ready.  We also need to create an Editor control which will display the Drop down while creating the Column to show the Target document library into which the file has to be uploaded (We are using that in the Field Control above). Add a User Control to the solution (FileUploadFieldEditControl.ASCX).  Now move the .ASCX to the control templates folder and leave the .CS files under the solution as we want to Package them and Push the ASCX to the Control Templates folder.

ASCX File will be

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”
Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register TagPrefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages”
Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true” Inherits=”SharePoint2010.Controls.FileUploadFieldEditControl” %>
<%@ Register TagPrefix=”wssuc” TagName=”InputFormControl” Src=”~/_controltemplates/InputFormControl.ascx” %>
<%@ Register TagPrefix=”wssuc” TagName=”InputFormSection” Src=”~/_controltemplates/InputFormSection.ascx” %>
<wssuc:InputFormSection runat=”server” id=”UploadControl” Title=”Upload Control Configuration Section”>
<template_inputformcontrols>
<wssuc:InputFormControl runat=”server” LabelText=”Select document library”>
<Template_Control>
<asp:DropDownList ID=”ddlDocLibs” runat=”server” CssClass=”ms-ButtonheightWidth” Width=”250px” />
</Template_Control>
</wssuc:InputFormControl>
</template_inputformcontrols>
</wssuc:InputFormSection>

Declare the Drop Down Control in the Designer CS file.

protected DropDownList ddlDocLibs;

Add the Logic in the User Control Code behind file to populate the drop down with Document Libraries.  This class has to inherit from System.Web.UI.UserControl and the Interface Microsoft.SharePoint.WebControls.IFieldEditor.

FileUploadCustomField _field = null;

public bool DisplayAsNewSection
{
get { return true; }
}

public void InitializeWithField(SPField field)
{
this._field = field as FileUploadCustomField;
}

public void OnSaveChange(SPField field, bool isNewField)
{
FileUploadCustomField myField = field as FileUploadCustomField;
myField.UploadDocumentLibrary = ddlDocLibs.SelectedItem.Text;
}

protected override void CreateChildControls()
{
base.CreateChildControls();
SPListCollection objLists = SPContext.Current.Web.Lists;
foreach (SPList objList in objLists)
{
if (objList is SPDocumentLibrary)
ddlDocLibs.Items.Add(new ListItem(objList.Title, objList.Title));
}
if (!IsPostBack && _field != null)
{
if (!String.IsNullOrEmpty(_field.UploadDocumentLibrary))
FindControlRecursive<DropDownList>(this, “ddlDocLibs”).Items.FindByText(_field.UploadDocumentLibrary).Selected = true;
}
}

protected T FindControlRecursive<T>(Control rootControl, String id)
where T : Control
{
T retVal = null;
if (rootControl.HasControls())
{
foreach (Control c in rootControl.Controls)
{
if (c.ID == id) return (T)c;
retVal = FindControlRecursive<T>(c, id);
if (retVal != null) break;
}
}
return retVal;
}

Now, we have come to last step of building this control and deploying it.  Create an XML file under the XML folder and name it “FLDTYPES_FileUploadCustomField.xml”.

<?xml version=”1.0″ encoding=”utf-8″ ?>
<FieldTypes>
<FieldType>
<Field Name=”TypeName”>FileUploadCustomField</Field>
<Field Name=”TypeDisplayName”>File Upload Custom Field</Field>
<Field Name=”TypeShortDescription”>File Upload Custom Field</Field>
<Field Name=”ParentType”>Text</Field>
<Field Name=”UserCreatable”>TRUE</Field>
<Field Name=”ShowInListCreate”>TRUE</Field>
<Field Name=”ShowInSurveyCreate”>TRUE</Field>
<Field Name=”ShowInDocumentLibraryCreate”>TRUE</Field>
<Field Name=”ShowInColumnTemplateCreate”>TRUE</Field>
<Field Name=”FieldTypeClass”>SharePoint2010.Controls.FileUploadCustomField, $SharePoint.Project.AssemblyFullName$</Field>
<Field Name=”FieldEditorUserControl”>/_controltemplates/FileUploadFieldEditControl.ascx</Field>
<PropertySchema>
<Fields>
<Field Name=”UploadDocumentLibrary” DisplayName=”Select target Document Library” Type=”Text” Hidden=”True”/>
</Fields>
</PropertySchema>
</FieldType>
</FieldTypes>

And build and deploy the solution.

About these ads

39 Responses to "File Upload Custom Site Field Control – SharePoint 2010 – Part 2"

[…] I am going to explain this in two different blog posts – Part 1 – Outline the need / design, Part 2 – Code – Howtos […]

can you please post the download link for the sourcecode

Do you happen to have the solution available for download? I’m unsure as to where the first Custom Properties are to be created.

I didn’t attach the WSP with the post. Will attach it. Which custom property are you referring to?

Thanks. Think I’ve figured it out … now a little unclear on the following …

Now we have Field and Field Control ready. We also need to create an Editor control which will display the Drop down while creating the Column to show the Target document library into which the file has to be uploaded (We are using that in the Field Control above). Add a User Control to the solution (FileUploadFieldEditControl.ASCX). Now move the .ASCX to the control templates folder and leave the .CS files under the solution as we want to Package them and Push the ASCX to the Control Templates folder.

This is great code btw. Thanks for sharing.

When the user / administrator is adding a new column and selects the data type as the file control field he will see this control so that he can control the document library into which the uploaded documents are stored.

Thanks. I understood that. Was just having a late Friday cloudy moment I think. I’ve completed the deployment but am getting a error.

Could not load type ‘SharePoint2010.Controls.FileUploadFieldEditControl’
Source File: /_controltemplates/FileUploadFieldEditControl.ascx Line: 10
Line 10:

I think this might be related to the fact that I couldn’t seperate the .cs and place it in the project root (instead of the controltemplates folder). I’ve double checked that it’s still being deployed and compiled.

Please advise. Thanks for all your help … this is a great piece of code.

Hi Sriram. Any idea what could cause the above or when you uploading the solution? Your help is really appreciated.

Hi Chris, It looks like the Signature of the Control is mentioned wrong in the FileUploadFieldEditControl.ascx, Can you double check that?

That does seem to be the issue, however, I can’t spot what’s wrong. Visual Studio is showing warnings that the InputFormControl and InputFormSection aren’t known elements.

Here’s what I have for the file. I’ve tried several permutations to no avail.

Code being stripped so have replaced the angle brackets.

<%@ Assembly Name=”$SharePoint.Project.AssemblyFullName$” %>
<%@ Assembly Name=”Microsoft.Web.CommandUI, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”SharePoint” Namespace=”Microsoft.SharePoint.WebControls”
Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”Utilities” Namespace=”Microsoft.SharePoint.Utilities” Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Register TagPrefix=”asp” Namespace=”System.Web.UI” Assembly=”System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35″ %>
<%@ Import Namespace=”Microsoft.SharePoint” %>
<%@ Register TagPrefix=”WebPartPages” Namespace=”Microsoft.SharePoint.WebPartPages”
Assembly=”Microsoft.SharePoint, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c” %>
<%@ Control Language=”C#” AutoEventWireup=”true” Inherits=”SharePoint2010.Controls.FileUploadFieldEditControl” %>
<%@ Register TagPrefix=”wssuc” TagName=”InputFormControl” Src=”~/_controltemplates/InputFormControl.ascx” %>
<%@ Register TagPrefix=”wssuc” TagName=”InputFormSection” Src=”~/_controltemplates/InputFormSection.ascx” %>
<wssuc:InputFormSection runat=”server” id=”UploadControl” Title=”Upload Control Configuration Section”>
<template_inputformcontrols>
<wssuc:InputFormControl runat=”server” LabelText=”Select document library”>
<Template_Control>
<asp:DropDownList ID=”ddlDocLibs” runat=”server” CssClass=”ms-ButtonheightWidth” Width=”250px” />
</Template_Control>
</wssuc:InputFormControl>
</template_inputformcontrols>
</wssuc:InputFormSection>

Hi Sriram,

Have you been able to spot my mistake at all?

Chris.

Hi Chris

I know this is a slightly old thread, but i would like to use this custom field in a project, but i am getting syntax errors? It seems you are the only one who managed to get it to work? Can you send me your working project please?? :-)

Don’t worry … Cracked it. Had the wrong assembly and namespace specified for my solution.

hi chris wsp file can we have it?

Hi Sriram, I want to upload documents to specific folder in document library and if folder is not available provide option to create folder and then add documnet..any idea how to do this?

This control is only having the option to upload it to a document library which is selected while configuring the column on the list. You can have an additional logic with a checkbox in the ASCX (to enable / disable creation of folders) and use that value in the logic to create folder if it doesn’t exist. Should be simple change 1) in the ASCX and 2) Folder exist check / creation logic change upload path.

It is really a nice and useful piece of information. I am happy that you shared this helpful info with us. Please stay us informed like this. Thanks for sharing.

Hi Sriram,
How do I make the fldtypes_*.xsl for this. This is if I want to show the image thumbnail in the list view

Hey Sriram,

I want to use your control inside a webpart, but I can’t get it working. I’m have the FileUploadCustomField and I’m accessing the FieldRenderingControl property of it, but if I add this control to the Controls collection, nothing seems to happen.

This code is for creating a field rather than having this logic in a webpart. Having this in a webpart is quite easier. You can place a FileUpload control on the webpart and use SPWeb.Files.Add

Hi
can u share the solution as we are facing some issues it like
TYPE SYSTEM.WEB.UI.USECONTROL DOES NOT HAVE A PUBLIC PROPERTY NAMED ‘TEMPLATE_INPUTFROMCONTROLS’
THANKS IN ADVANCE

Hi bhargavi,

You will need to reference the System.Web in your Visual Studio before importing into the code.

regards,
Kodle

can you please post the download link for the sorcecode

Hi, how can I display it in a List this custom field as hyperlink to the file, actually I have now only as path “Library/filename” like, I think I schould do something in xsl file, right?

Do you have the vb code for the above? It would be much appreciated.

Nice post. But when i create a new fileUpload custom field i got an error “Earlier versions of client programs might not support this type of column. Adding this column might block those programs from saving documents to this library.”

Hi Sriram, I would like to link FileName to File Url, I schould do it in xsl but I have now Idee how, could you please help me?

Hi Looking good blog
i am able to develop custom field type as file upload control i am able to configure the location of document library but i am getting exception like List” ” deos not existing in url http://sp-dev-12:6241 when i trying to click the upload button after browse can any one tell what i need to do

i got an error Unable to cast object of type ‘ASP._controltemplates_fileuploadfieldeditcontrol_ascx’ to type ‘Microsoft.SharePoint.WebControls.IFieldEditor’ whenever i’ve tried to add the column which i’ve created based on your steps above

would you guide me to solve it

so the issue was that i forget to inherit from “IFieldEditor”

sorry

Hi Sriram,

I think your code are missing some lines, for example, in the “FileUploadCustomField.cs”, on the ‘FieldRenderingControl’, your new FileUploadCustomField() doesn’t input the arguments as required by the 2 constructors that you have included in this example.

Or point me out if I’m wrong here.

Regards,
Kodle

FileUploadCustomField.cs doesn’t instantiate FileUploadCustomField, it will create a BaseFieldControl of type FileUploadCustomFieldControl which is the one that needs to be rendered.

Hi Sriram.

I have to hand it to you, this is a very good solution! Is there any chance you could upload the actual project its self?

Would really appreciate it.

Thanks.

Hi Ritzy,

Unfortunately i cannot upload the solution as-is. That’s the reason why i have inserted the code. It’s almost the same. Can you tell me the errors that you are having. I would be able to reply to that.

Regards
Sriram

Hi Sriram

I managed to get a little further. I am now able to select the column from the list and specify the document library. After i select my document, i press Upload button i get an error. So i modified the Button_Click event as follows ;

String siteURL = SPContext.Current.Web.Url;
string error_string = “”;

try
{
using (SPSite sourceSite = new SPSite(siteURL))
{
error_string = “SPSite ” + sourceSite.Url;
using (SPWeb sourceWeb = sourceSite.OpenWeb())
{
error_string = “SPWeb ” + sourceWeb.Url;
sourceWeb.AllowUnsafeUpdates = true;
FileUploadCustomField _field = (FileUploadCustomField)this.Field;
error_string = “_field.UploadDocumentLibrary ” + _field.UploadDocumentLibrary;
SPList objList = sourceWeb.Lists[_field.UploadDocumentLibrary];
error_string = “SPList ” + objList.Title;
SPFolder destFolder = objList.RootFolder;

if (UploadFileControl.PostedFile == null) return;
string strFileName = UploadFileControl.PostedFile.FileName.Substring(UploadFileControl.PostedFile.FileName.LastIndexOf(“\\”) + 1);
error_string = strFileName;
Stream fStream = UploadFileControl.PostedFile.InputStream;

SPFile objFile = destFolder.Files.Add(strFileName, fStream, true);
objFile.Item.UpdateOverwriteVersion();

StatusLabel.Text = “Upload File :: Success View (” + “/” + objFile.ParentFolder + “/” + strFileName + “)“;
hdnFileName.Value = “/” + objFile.ParentFolder + “/” + strFileName;
sourceWeb.Dispose();
}
}
}
catch (Exception ex)
{
StatusLabel.Text = “Upload File ” + error_string + ” :: Failed ” + ex.Message + ” ” + ex.StackTrace;
}

error_string captures the value of objects as the code is exectued.

The error returned to sharepoint is as follows.

Upload File _field.UploadDocumentLibrary :: Failed List ” does not exist at site with URL ‘http://mysharepointsite:40861/ims/QMS’. at Microsoft.SharePoint.SPListCollection.GetListByName(String strListName, Boolean bThrowException) at SharePoint2010.Controls.FieldUploadCustomFieldControl.UploadButton_Click(Object sender, EventArgs e)

So it seems for some reason UploadDocumentLibrary is being returned as ” “.

An ideas why? Where could i start looking inorder to debug the error?

I’m getting syntax errors and would just like to compare my project with a working version.

Hi,

I’ve been trying to get this working for a few days now but am getting the following error when clicking the ok button to add the new column (after selecting the document library).

Constructor on type ‘my.namespace.FileUploadCustomField.FileUploadFieldEditControl’ not found.

The only difference between your code and mine is that I have changed the namespace to match my solution (represented above by ‘my.namespace’ AND I could not seperate the .cs files in file FileUploadFieldEditControl.ascx and so they are still sitting under the CONTROLTEMPLATES mapped folder.

Any ideas what the problem could be?

Another solution:

http://www.sparqube.com/SharePoint-Document-Column/

It is custom field type that allows to upload multiple documents per list item or browse existing ones from SharePoint site.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

My Tweets

Follow

Get every new post delivered to your Inbox.

Join 121 other followers

%d bloggers like this: