Thursday, March 18, 2010

SPFolder related operations in SharePoint

1) Get SPListItem(s) of a particular SPFolder


SPList splist;
SPFolder spfolder; //Get the required folder instance
SPQuery spquery = new SPQuery();
spquery.Query = string.Empty;
spquery.Folder = spfolder;
spquery.ViewAttributes = "Scope=\"Recursive\""; //For nested folder structure

SPListItemCollection itemCol = splist.GetItems(spquery)


2) Create a SPListItem based on a custom ContentType or SPFolder ContentType

SPWeb spweb; //get the SPWeb instance
SPContentType myCType = splist.ContentTypes["Custom content type"];
SPList splist = spweb.Lists["My SPList"];
SPListItem splistitem = splist.Items.Add();
splistitem["ContentTypeId"] = myCType.Id;
splistitem.Update();

splistitem["Title"] = "New Item";
splistitem.Update();


3) Add a SPListItem in a particular SPFolder

SPWeb spweb; //get the SPWeb instance
SPContentType myCType = splist.ContentTypes["Custom content type"];
SPList splist = spweb.Lists["My SPList"];
//get folder instance
SPFolder spfolder = splist.Folders[1];
SPListItem splistitem
= splist.Items.Add(spfolder.ServerRelativeUrl
, SPFileSystemObjectType.File, null);

splistitem["ContentTypeId"] = myCType.Id;
splistitem.Update();

splistitem["Title"] = "New Item";
splistitem.Update();

Image Preview functionality in SharePoint

Question:
How to display the Image preview without actually uploading the file in SharePoint?

Solution:
To check the image preview we can temporary move/place the file in Layout folder. Then pass URL in following format to Image control:
"/_layouts/images/MYFOLDER/MyImageName.jpg

After checking the Image preview and final upload of image file, we can delete the temporary image file from 12 hive.

Code snippet (comments are self-explanatory):


FileUpload FileUploadImage; //FileUpload control to select image file
Image myImage; //Image control to be used for preview functionality

//Getting 12 hive path through SPUtility.GetGenericSetupPath() function
string folderPath =
Microsoft.SharePoint.Utilities.SPUtility.GetGenericSetupPath("TEMPLATE")
+ "\\IMAGES\\MYFOLDER\\";

//Check folder path
if (!Directory.Exists(folderPath))
Directory.CreateDirectory(folderPath);

//Copy the image file to a temporary folder in 12 hive
File.WriteAllBytes(folderPath + FileUploadImage.FileName,
FileUploadImage.FileBytes);

/* //File.Copy() will not work in case of remote image upload
File.Copy(FileUploadImage.PostedFile.FileName,
folderPath + FileUploadImage.FileName, true);
*/

//Set the URL of image control
myImage.ImageUrl =
"/_layouts/images/MYFOLDER/" + FileUploadImage.FileName;


Note: In a similar manner we can preview media file (like *.wmv) before actual upload in SharePoint.

Custom RSS Feed in SharePoint

SharePoint provides SPList’s level RSS Feed url [SPList Toolbar > Actions > View RSS Feed].
http://<server-name:port>/_layouts/listfeed.aspx?List=List_GUID

In above URL by specifying List’s GUID we can get feeds for all records (irrespective of any SPView or of Default View).

Now consider a scenario where we want SPView specific feeds.

In File System, ListFeed.aspx file is placed at following:
C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS\ListFeed.aspx

ListFeed.aspx refers Microsoft.SharePoint.ApplicationPages.ListFeed.cs class file. Using Reflector we can get the idea that ListFeed.aspx can accept 3 query strings as parameters: List GUID, Meeting Instance ID and View GUID.


Guid guid = new Guid(base.Request.QueryString.GetValues("List")[0]);
string[] values = base.Request.QueryString.GetValues("InstanceID");
string g = base.Request.QueryString["View"];


ListFeed.cs is using following function to get the feeds:

base.spList.WriteRssFeed(base.Response.OutputStream,
base.meetingInstanceId, this.spView);


MSDN Description of WriteRssFeed function:

public void WriteRssFeed (
Stream outputStream,
int meetingInstanceId,
SPView spView
)

Parameters
outputStream : A Stream object that represents the document stream.
meetingInstanceId : An integer value that represents the meeting instance.
spView :An SPView object that represents the view.


WriteRssFeed supports 3 overload methods:
SPList.WriteRssFeed(Stream) :
Writes the RSS feeds from the list to the specified document stream.

SPList.WriteRssFeed (Stream, Int32) :
Writes the RSS feeds from the list that are associated with the specified meeting to the specified document stream.

SPList.WriteRssFeed (Stream, Int32, SPView) :
Writes the RSS feeds from the list that are associated with the specified meeting and view to the specified document stream.

So if we want View specific feed then we have to specify all 3 parameters, but here comes the issue: what does Meeting Instance ID mean and from where we get this value?



Now to get the SPView specific feed, we can write custom RSS Feed. I referred this post- blah.winsmarts.com. I modified the original code little bit. I created a application page and instead of writing inline server code I created a class library so that I can debug the page.

HTML Code:

<%@ Page Language="C#"
Inherits="MyNameSpace.MyFeed,MyNameSpace,
Version=1.0.0.0,Culture=neutral,PublicKeyToken=1d5ac09ccd41620f" %>


C# Code:

using System;
using System.Web;
using System.Text;
using Microsoft.SharePoint;
namespace MyNameSpace
{
public class MyFeed
: Microsoft.SharePoint.WebControls.UnsecuredLayoutsPageBase
{
public void Page_Load()
{
try
{
Response.Write(GetRSSFromListView(
Request.QueryString["List"],
Request.QueryString["View"]));
}
catch (Exception ex)
{
Response.Write("<pre>");
Response.Write(ex.ToString());
Response.Write("</pre>");
}
}
private static string GetRSSFromListView(string strListGUID,
string strViewGUID)
{
StringBuilder sb = new StringBuilder();
sb.Append("<?xml version=\"1.0\"?>");
sb.Append("<rss version=\"2.0\">");

using (SPSite site = new SPSite(SPContext.Current.Web.Url))
using (SPWeb web = site.OpenWeb())
{
SPList list = web.Lists[new Guid(strListGUID)];
SPView view = null;
if (strViewGUID != null)
view = list.Views[new Guid(strViewGUID)];
else
view = list.DefaultView;

sb.Append("<channel>");
AddTag("title", list.Title, sb);
AddTag("description", list.Description, sb);

SPListItemCollection items = list.GetItems(view);
foreach (SPListItem item in items)
{
sb.Append("<item>");
AddTag("title", item["LinkTitle"].ToString(), sb);
AddTag("link", list.RootFolder.Url
+ "/DispForm.aspx?ID=" + item.ID, sb);
sb.Append("<description>");
foreach (string viewField in view.ViewFields)
{
if (viewField != "LinkTitle")
{
AddTag(
viewField.Replace("_x0020_", " "),
HttpContext.Current.Server.HtmlEncode
(item.GetFormattedValue(viewField)),
sb);
}
}
sb.Append("</description>");
sb.Append("</item>");
}
sb.Append("</channel>");
sb.Append("</rss>");
}
return sb.ToString();
}


private static void AddTag(string tagText,
string tagValue, StringBuilder sb)
{
sb.Append("<");
sb.Append(tagText.Replace(" ", "_"));
sb.Append(">");
sb.Append(HttpContext.Current.Server.HtmlEncode(tagValue));
sb.Append("</");
sb.Append(tagText.Replace(" ", "_"));
sb.Append(">");
}
}
}


Now if we use the above custom RSS Feed page URL and pass it to SharePoint’s out-of-box RSS Viewer Webpart, then we will get following error:

The RSS webpart does not support authenticated feeds.

Solution -
Changing to Kerberos authentication
1. On the Central Administration page, click Application Management.
2. Under the Application Security section, click Authentication Providers.
3. Click the Default provider, and change Integrated Widows authentication from NTLM to Negotiate (Kerberos).

OR
We can use custom RSS Viewer WebPart, which is already developed and uploaded at : philwicklund.com


References:
RSS Feed
how-to-get-moss-2007-rss
RSS Reader
Technet
MSDN

Google