Sharepoint list attachments
Using out of the box sharepoint functionality, it is easy to add and view attachments to list items.
However, a common issue in WSS 3.0 is that customised list views do not support attachments ... or, "attachement". The error "This form was customized not working with attachement" is displayed.
The only supported way of storing attachments to a list item, is to use the default newform.aspx page, associated with the given list.
This works, but has a number of restrictions:
Branding
It is difficult to brand or customise the upload form. Even though an upload.aspx file is associated with the list, it is not used (by default). The actual upload form which is used, is located in the 'Layouts' directory, on the webserver; any customisation of this would change the uploading form for all sites in the site collection. This is not desirable.
Views
The default newform.aspx used a listview to display the fields associated with the list. Unfortunately, there is no easy way to change the fields that are displayed to the user; all fields associated with the list are shown by default.
Customisation
With respect to general customisation of the newform.aspx, it is also possible to view the data using dataview webparts, and custom list forms. Unfortunately, both of these approaches appear to strip support for attachments; dataview webparts do not support an upload control, and custom list forms throw the error in the screenshot above.
Solution
In order to overcome the above issues, it is fairly simple to implement a custom webpart using the Visual Studio extensions for WSS.
The general process is as follows:
Setup the project
Firstly, create a new webpart project, using the VSeWSS. Then, change the class declaration to inherit from
Microsoft.SharePoint.WebPartPages.WebPart
The existing class definition inherits from the standard ASP.NET 2.0 WebPart class – this ensures interoperability with existing .NET webparts, but does not provide access to all of the sharepoint WebPart features.
Create the code structure
The default WebPart project contains a single overridable method "Render". The render method outputs straight html, via the use of a HtmlTextWriter. This method is not useful for our purposes: delete it. Create two new methods: CreateChildControls(), and RenderWebPart() – both should be defined as "protected override void".
The CreateChildControls() method instantiates the ASP.net controls that you want to use – in this case, a HtmlInputFile (for the attachment). Make sure you declare the controls globally. The RenderWebPart() method adds the controls to the Html, using the format
myControl.RenderControl(output)
Add your submission eventhandler
In your CreateChildControls() method, add a button with an event handler – this will be used to submit the entire form. Make sure you also render this button in the RenderWebPart() method.
In the eventhandler, create a SPList object pointing to the list you want to add an item to, and add an SPListItem to the list, using:
SPListItem myItem = myList.items.add()
Now, add any properties to the listitem using:
myItem["Title"] = "{title here}";
And, add the attachment, using:
Stream fstream = myHtmlInputFile.PostedFile.InputStream;
byte[] contents = new byte[fstream.length];
fstream.Read(contents, 0, (int)fstream.length);
fstream.Close();
fstream.Dispose();
myItem.Attachments.Add(Path.GetFileName(myHtmlInputFile.PostedFile.FileName), contents);
Finally, make sure you commit these changes to the listitem, using
myItem.Update();
Summary
Hopefully, a future sharepoint release will solve the current implementation issues with list attachments. In the meantime, you may need to either use the default sharepoint behaviour (without customisation), or create a custom webpart. If you choose to follow the latter route, the preceding instructions should provide you with all of the tools you need to get started.
When creating a site using Windows Sharepoint Services, search is typically managed at the web application level. This means that although the pages you create for your site will inherit the styles and layout designated in your site masterpage, any search results will be displayed using the default web application theme. By taking the following steps, it is possible to customise the way search results are shown, without affecting other sites operating in your WSS web application.
Create a custom searchresults aspx page
When you perform a sharepoint site search, the search results are displayed using the searchresults.aspx page. This is located in C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS. Copy the contents of this file. Now, navigate to your site (using sharepoint designer), and create a new aspx page named ‘CustomSearchResults.aspx’. Paste the contents of searchresults.aspx into your newly created page. At this point, you need to make two changes to the page.
Firstly, update the Page directive to point to your site masterpage.
For ie, <%@ Page language="C#" MasterPageFile="~masterurl/default.master" ... %>
In order to ensure that this is set out correctly, it is best to copy this from another page in your site that inherits from your site masterpage.
Secondly, remove unnecessary controls from the page. There will be a number of controls registered at the top of the page; it is likely that these are already registered in your masterpage. Therefore, remove all except the following controls:
<%@ Register Tagprefix="SharePoint" Namespace=
"Microsoft.SharePoint.WebControls" ... %> <%@ Register Tagprefix="SearchWC" Namespace=
"Microsoft.SharePoint.Search
.Internal.WebControls" ... %>
<%@ Register Tagprefix="WebPartPages" Namespace=
"Microsoft.SharePoint.WebPartPages" ... %>
Create a custom searchresults controlYour customised search results page is now inheriting from your masterpage. In order to display the results of a given search, it is necessary to create a customised control to place on your masterpage. Navigate to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\CONTROLTEMPLATES and locate SearchArea.ascx. This is the control which displays the search bar on your site, and passes the search parameters supplied to the search results page. Again, copy the contents of this file, and create a new CustomSearchBox.ascx control (this time, in the CONTROLTEMPLATES directory) with the pasted contents of SearchArea.ascx.
Open CustomSearchBox.ascx and make the following changes:
Firstly, update the referenced url to reflect your customised search results page, near the top of the page.string strEncodedUrl= SPHttpUtility.EcmaScriptStringLiteralEncode(SPHttpUtility.UrlPathEncode(web.Url + "/CustomSearchResults.aspx", false, false));
Secondly, update the names of the searchscope and searchstring, near the bottom of the page.<SELECT id='idSearchScope' name='CustomSearchScope' class='ms-searchbox' ... >>
<INPUT Type=TEXT id='idSearchString' size=35 name='CustomSearchString' display='inline' ... >>
And, thirdly, update the javascript calls to reflect a custom search function.<INPUT Type=TEXT id='idSearchString' size=35 name='CustomSearchString' ... onKeyDown="return
CustomSearchKeyDown(event, <%=strEncodedUrl%>);" ... >
<a target='_self' href='javascript:' onClick="javascript:
SubmitCustomSearchRedirect(<%=strEncodedUrl%>);javascript:return false;" ... > </a>
Edit Core.jsIn order to redirect the page to your custom search results page, we need to create a couple of custom javascript functions. Navigate to C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\1033, and open the Core.js file. Search for the “SubmitSearchRedirect” function. This is the default search function. Unfortunately, the Form actions at the end cause sharepoint to require a screen refresh each time you navigate to your custom search results page. To solve this, we can create a new function, as follows: (the new function ensures existing site search will remain unaffected)
function SubmitCustomSearchRedirect(strUrl)
{
var frm=document.forms["frmSiteSearch"];
frm=document.forms[MSOWebPartPageFormName];
var searchText=frm.elements["CustomSearchString"].value;
var searchScope=frm.elements["CustomSearchScope"].value;
strUrl=strUrl+"?k="+escapeProperly(searchText)
+"&u="+escapeProperly(searchScope);
window.location = strUrl;
}
Likewise, search for the SearchKeyDown function, duplicate it, and edit as follows:
function CustomSearchKeyDown(event, strUrl)
{
if (IsKeyDownSubmit(event))
{
SubmitCustomSearchRedirect(strUrl);
return false;
}
return true;
}
Adding your custom searchresults control to the site masterpageYou have now created a customised search control, which utilises a custom search results page. In order to utilise this in your site, it is necessary to add the control to your masterpage.
This is a simple process, consisting of the following steps:
Firstly, register your control at the top of your masterpage.
<%@ Register TagPrefix="provoke" TagName="CustomSearchBox" src="~/_controltemplates/CustomSearchBox.ascx" %>
And, secondly, place the control at the appropriate location on your masterpage.
<asp:ContentPlaceHolder ID="ProvokeCustomSearch" runat="server">
<provoke:CustomSearchBox id="CustomPlaceHolderSearchArea" runat="server"/></asp:ContentPlaceHolder>
At this point, you should be able to run your site search (after a hard browser refresh), and view your customised search results page.