SharePoint check in SPListItem - c#

In sharepoint how can you check in an SPListItem?

See on MSDN: SPListItem.File.CheckIn();
For example:
SPFile file = item.File;
if (file.CheckOutStatus != SPFile.SPCheckOutStatus.None)
{
file.CheckIn("Reason for check in.", SPCheckinType.MajorCheckIn);
}
The optional second parameter allows specification of either minor, major or overwrite check in via the SPCheckinType enumeration.

Great response, however in 2010, CheckOutStatus is declining - use SPCheckOutType instead. You might also want to Approve the item as well - for example:
SPList MyLib = TheWeb.Lists["MyLibrary"];
if (MyLib != null)
{
if (MyLib.Items.Count > 0)
{
foreach(SPListItem AnItem in MyLib.Items)
{
SPFile TheFile = AnItem.File;
if (TheFile.CheckOutType != SPFile.SPCheckOutType.None)
{
TheFile.CheckIn("Check in comment", SPCheckinType.MajorCheckIn);
TheFile.Approve("Approval comment");
}
}
}
}
David M. Sterling
SICG

Related

Differentiate iTunes internal playlists and user playlist

Following my previous question
When I fetch Playlists in iTunes library I get some entries which seems to be default playlists for iTunes
Here is my code:
App = new iTunesAppClass();
IITSourceCollection sources = App.Sources;
foreach (IITSource src in sources)
{
if (src.Name == "Library")
{
IITPlaylistCollection pls = src.Playlists;
foreach (IITPlaylist pl in pls)
{
// add pl.Name to a List<string> and them show them on TreeView
}
}
}
This is the result:
You see that I have created a playlist named "Music". There is also a default entry named "Music". How can I differentiate these two playlist ? Is there any property in iTunesLib which says which one is the default one and which is the one I have created?
Using Kind and SpecialKind properties, I was able to implement a solution:
App = new iTunesAppClass();
IITSourceCollection sources = App.Sources;
foreach (IITSource src in sources)
{
if (src.Name == "Library")
{
IITPlaylistCollection pls = src.Playlists;
foreach (IITPlaylist pl in pls)
{
/* here is the trick */
if (p is IITUserPlaylist)
{
var upl = (IITUserPlaylist)p;
if (upl.SpecialKind != ITUserPlaylistSpecialKind.ITUserPlaylistSpecialKindNone)
continue;
}
/* and this one */
if (p.Kind == ITPlaylistKind.ITPlaylistKindLibrary)
continue;
// add pl.Name to a List<string> and them show them on TreeView
}
}
}

How do I find the data type of an AD attribute not having a value

I am struggling to find the data type of AD attributes that are not having a value already.
Thus far a resulting DirecoryEntry only contains a property for attributes that already have a value. I can't find a method to obtain information about all other attributes.
Adding a value to the 'PropertiesToLoad' doesn't seem to do anything. The returned DirectoryEntry object contains all attributes (with values) regardless of what is added here.
Code used:
public void Test(string ldapPath)
{
Type orgType;
try
{
using (DirectoryEntry searchRoot = GetSearchRoot(ldapPath))
{
using (DirectorySearcher search = new DirectorySearcher(searchRoot))
{
search.Filter = "(&(objectCategory=person)(objectClass=user)(sAMAccountName=coen))";
search.PropertiesToLoad.Add("msExchHomeServerName");
SearchResult searchResult = search.FindOne();
{
using (DirectoryEntry entry = searchResult.GetDirectoryEntry())
{
if (entry != null)
{
if (entry.Properties.Contains("msExchHomeServerName"))
{
orgType = entry.Properties["msExchHomeServerName"].GetType();
}
else // The value is empty and NOT present in the current 'entry.Properties' object.
{
throw new Exception("Unknown type");
}
}
}
}
}
}
}
catch (Exception e)
{
<handle exception>
}
}
Is there a way to find the data type of the 'msExchHomeServerName' (or any of the 'empty' attributes) attribute?
Any help would be highly appreciated!
Coen
Active Directory has a schema. Obvious to say, not obvious to think about since, by default, you cannot explore it.
However, you can Register the Active Directory Schema MMC Snap-In1 and then, in a fresh instance of MMC, add that Snap-In.
This then allows you to explore the Classes and Attributes that make up your current AD schema (and add new classes/attributes if you know what you're doing and choose to do so).
msExchHomeServerName can then be discovered to be a "Unicode String", which means a plain string from C# should be acceptable. Note also that some types (particularly numeric ones) may also specify Minimums and Maximums which should be observed.
You can also explore the schema programatically via the ActiveDirectorySchema class, by e.g. calling ActiveDirectorySchema.GetCurrentSchema(); and then explore from there.
1I cannot remember if you need to have installed the general Domain Admin tools (such as Users and Computers) in order for that DLL to exist on your system.
Thanks to Damien_The_Unbeliever who pointed me in the right direction, I managed to create the following method:
public Dictionary<string, ActiveDirectorySyntax> GetAttributeSyntaxes(List<string> lstAttributeNames)
{
Dictionary<string, ActiveDirectorySyntax> dictRes = new Dictionary<string, ActiveDirectorySyntax>();
if (lstAttributeNames.Count > 0)
{
DirectoryContext directoryContext = new DirectoryContext(DirectoryContextType.DirectoryServer,
m_Server, m_UserName, m_Password);
using (ActiveDirectorySchema currentSchema = ActiveDirectorySchema.GetSchema(directoryContext))
{
using (ActiveDirectorySchemaClass objClass = currentSchema.FindClass("user"))
{
if (objClass != null)
{
ReadOnlyActiveDirectorySchemaPropertyCollection propcol = objClass.GetAllProperties();
foreach (ActiveDirectorySchemaProperty schemaProperty in propcol)
{
foreach (string attrName in lstAttributeNames)
{
if (schemaProperty.Name.Equals(attrName))
{
dictRes.Add(attrName, schemaProperty.Syntax);
break;
}
}
}
}
}
}
}
return dictRes;
}
The returned 'schemaProperty.Syntax' contains sufficient information to determine the actual data type.
Thanks Damien!

How to validate if a folder already exists

I want to create folders and add classes within the folders. I can create the folder once, but once I have created it, I just want to add classes. My code gives error because I'm trying to create a folder several times, which is not right. So before adding a class to the folder, I want to check if the folder already exists and if it exists I just want to add the class.
ProjectItem rootFolder = project.ProjectItems.AddFolder(folder);
ProjectItem item = rootFolder.ProjectItems.AddFromTemplate(itemPath, className);
According to documentation, there is no kind of Exists function which would tell us if a folder already existed.
So you have at least two options:
1. Try and ignore
Simply:
try
{
var rootFolder = project.ProjectItems.AddFolder(folder);
}
catch
{
/* folder already exists, nothing to do */
}
2. Solution folders can only occur in the first level below the solution root node, so we can get away with a non-recursive solution.
public static bool CheckIfSolutionFolderExists(ProjectItems projectItems, string foldername)
{
foreach(var projectItem in projectItems)
{
if(projectItem.Kind == EnvDTE.vsProjectItemKindVirtualFolder)
{
if(projectItem.Name == foldername)
{
return true;
}
}
}
return false;
}
For a recursive solution, I found this, which boils down to:
public static bool CheckIfFileExistsInProject(ProjectItems projectItems, string fullpath)
{
foreach(ProjectItem projectItem in projectItems)
{
if(projectItem.Name == fullpath)
{
return true;
}
else if ((projectItem.ProjectItems != null) && (projectItem.ProjectItems.Count > 0))
{
/* recursive search */
return CheckIfFileExistsInProject(projectItem.ProjectItems, fullpath);
}
}
return false;
}
A robust pattern for solution and project folder management would use AddFromDirectory whenever you want to mirror the file system hierarchy in the project tree, and AddFolder only for virtual folders that have no representation in the file system.
ProjectItem item;
if(Directory.Exists(itemname))
{
item = project.AddFromDirectory(itemname);
}
else
{
item = project.AddFolder(itemname);
}
(source: inspired from this)
You can use method Directory.Exists
and in your code it'll be look like there
if(!Directory.Exists(folder)) {
ProjectItem rootFolder = project.ProjectItems.AddFolder(folder);
}
ProjectItem item = rootFolder.ProjectItems.AddFromTemplate(itemPath, className);
You need to do the following:
if(Directory.Exists(path))
{
// The folder already exists
}
else
{
//Create a new folder here ...
}
Please check this out for more details on Directory.Exists

Linq query Object reference not set to an instance of an object. 2

This is returning the right Element cause in the intel-sense the nexp reads
like this Offline I am trying to change the Element with the Offline value to Ready.
public void ChangeConnectionStatus(string SelectedFile)
{
System.IO.DirectoryInfo dirInfo = new System.IO.DirectoryInfo(#"C:\Users\Rick\Documents\Visual Studio 2010\Projects\Server\server.config\DC_Classes\");
//Getting All file names from the directory info
System.IO.FileInfo[] fileNames = dirInfo.GetFiles(SelectedFile + "*.xml*");
//Foreach itterator
foreach (System.IO.FileInfo fi in fileNames)
{
XElement main = XElement.Load(fi.FullName);
IEnumerable<XElement> Nongroups = from nexp in main.XPathSelectElements("Network/Posted_Status")
where nexp.Element("Posted_Status").Value == "Offline"
select nexp;
////Handle the process here
foreach (XElement nexp in Nongroups)
{
DialogResult Yes = MessageBox.Show("This Will Online This Group Are You Sure You Want To Do This","System Info",MessageBoxButtons.YesNo,MessageBoxIcon.Information);
if (Yes == DialogResult.Yes)
{
nexp.SetValue("Ready");
}
}
}
}
If you are not sure about the type of the object, then just use var
foreach (var nexp in Nongroups)
And assign the value in this way:
if (Yes == DialogResult.Yes)
{
nexp.Element("Posted_Status").Value = "Ready";
}
My guess is that you are missing the namespace as you can see in this SO thread. So i am expecting nexp is being set to null on this line:
from nexp in main.XPathSelectElements("Network/Posted_Status")
You can read this MSDN thread as well.
Give it a try, hope it helps!

copy list items from one list to another in sharepoint

In Sharepoint how can you copy a list item from one list to another list
eg copy from "List A" to "List B" (both are at the root of the site)
I want this copying to occur when a new list item is added to "List A"
I tried using the CopyTo() method of an SPListItem inside the ItemAdded event receiver but couldnt figure out the url to copy to.
Here is the code I use. Pass it a SPlistItem and the name of the destination list as seen in Sharepoint(Not the URL). The only restriction is that both list must be in the same site:
private SPListItem CopyItem(SPListItem sourceItem, string destinationListName) {
//Copy sourceItem to destinationList
SPList destinationList = sourceItem.Web.Lists[destinationListName];
SPListItem targetItem = destinationList.Items.Add();
foreach (SPField f in sourceItem.Fields) {
//Copy all except attachments.
if (!f.ReadOnlyField && f.InternalName != "Attachments"
&& null != sourceItem[f.InternalName])
{
targetItem[f.InternalName] = sourceItem[f.InternalName];
}
}
//Copy attachments
foreach (string fileName in sourceItem.Attachments) {
SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + fileName);
byte[] imageData = file.OpenBinary();
targetItem.Attachments.Add(fileName, imageData);
}
return targetItem;
}
Indeed as Lars said, it can be tricky to move items and retain versions and correct userinfo. I have done similar things with that before so if you need some code examples, let me know through a comment and can supply you with some guidance.
The CopyTo method (if you decide to go with that) need an absolute Uri like:
http://host/site/web/list/filename.doc
So, if you are performing this in an event receiver you need to concatinate a string containing the elements needed. Something like (note that this can be done in other ways to):
string dest=
siteCollection.Url + "/" + site.Name + list.Name + item.File.Name;
Copying and moving files, items and folders in SharePoint can be tricky if you want to retain all metadata, timestamps, author info and version history. Take a look a CopyMove for SharePoint - it also has a Web Service API.
There's many tools on the market for copying a list item to another list (avepoint, metavis, etc.) but they are pretty expensive if you're planning to do this on only one list.
If you can do this manually once a week for example, look at the following tool : http://en.share-gate.com/sharepoint-tools/copy-move-sharepoint-list-items-with-metadata-and-version-history
Here is a powershell equivalent of Sylvian's that does allow for cross-site copy. His code could be modified similarly as well...
param([string]$sourceWebUrl, [string]$sourceListName, [string]$destWebUrl, [string]$destListName)
$sourceWeb = get-spweb $sourceWebUrl;
$sourceList = $sourceWeb.Lists[$sourceListName];
$destWeb = get-spweb $destWebUrl;
$destList = $destWeb.Lists[$destListName];
$sourceList.Items |%{
$destItem = $destList.Items.Add();
$sourceItem = $_;
$sourceItem.Fields |%{
$f = $_;
if($f.ReadOnlyField -eq $false -and $f.InternalName -ne "Attachments" -and $sourceItem[$f.InternalName] -ne $null){
$destItem[$f.InternalName] = $sourceItem[$f.InternalName];
}
}
$destItem.Update();
}
To use, copy and past to a file copy-listitems.ps1 and run using Sharpoint powerhsell commandline...
Make sure you call CopyTo(url) method on SPFile, not on SPListItem.
for example:
ItemUpdated(SPItemEventProperties properties)
{
//...
string url = properties.Web.Site.Url + "/" + properties.Web.Name + "Lists/ListName/" + properties.ListItem.File.Name;
//properties.ListItem.File.MoveTo(url);
properties.ListItem.File.CopyTo(url);
//...
}
private void CopyAttachmentsToList(SPListItem srcItem, SPListItem tgtItem)
{
try
{
//get source item attachments from the folder
SPFolder srcAttachmentsFolder =
srcItem.Web.Folders["Lists"].SubFolders[srcItem.ParentList.Title].SubFolders["Attachments"].SubFolders[srcItem.ID.ToString()];
//Add items to the target item
foreach (SPFile file in srcAttachmentsFolder.Files)
{
byte[] binFile = file.OpenBinary();
tgtItem.Update();
tgtItem.Attachments.AddNow(file.Name, binFile);
tgtItem.Update();
}
}
catch
{
//exception message goes here
}
finally
{
srcItem.Web.Dispose();
}
}
Don't forget to add this line, tgtItem.Update();, else you will get an err.
So, the lists have the exact same or similar columns? Either way, you could create a simple workflow that runs automatically when an item is created in "List A". Since the workflow in question is relatively simple, I'd recommend using SharePoint Designer (which is free) to create it, since you can easily match up the columns from the two lists. The walk through below should be able to help you get started.
Create a Workflow - SharePoint Designer
I had the same problem.
After experimenting a bit instead of
targetItem[f.InternalName] = sourceItem[f.InternalName];
I used:
targetItem[childField.Title] = sourceItem[parentField.Title];
How to copy field and save versions:
public static SPListItem CopyItem(SPListItem sourceItem, SPList destinationList)
{
SPListItem targetItem = destinationList.AddItem();
//loop over the soureitem, restore it
for (int i = sourceItem.Versions.Count - 1; i >= 0; i--)
{
//set the values into the archive
foreach (SPField sourceField in sourceItem.Fields)
{
SPListItemVersion version = sourceItem.Versions[i];
if ((!sourceField.ReadOnlyField) && (sourceField.InternalName != "Attachments"))
{
SetFields(targetItem, sourceField, version);
}
}
//update the archive item and
//loop over the the next version
targetItem.Update();
}
foreach (string fileName in sourceItem.Attachments)
{
SPFile file = sourceItem.ParentList.ParentWeb.GetFile(sourceItem.Attachments.UrlPrefix + fileName);
targetItem.Attachments.Add(fileName, file.OpenBinary());
}
targetItem.SystemUpdate();
return targetItem;
}
private static bool SetFields(SPListItem targetItem, SPField sourceField, SPListItemVersion version)
{
try
{
targetItem[sourceField.InternalName] = version.ListItem[sourceField.InternalName];
return true;
}
catch (System.ArgumentException)//field not filled
{
return false;
}
catch (SPException)//field not filled
{
return false;
}
}
Copy List Items from one SharePoint List or library to Another SharePoint list or library using c# server side code
//Itecollection is a collection of data from source list
public void CopyItemsFromOneListToAnotherList(SPListItemCollection itemCollection)
{
using (SPSite site = new SPSite(siteUrl))
{
using (SPWeb web = site.OpenWeb())
{
//Get destination list/library
//destListName - Destination list/library name
SPList destList = web.Lists.TryGetList(destListName);
foreach (SPListItem sourceItem in itemCollection)
{
//Add new Item to list
SPListItem destItem = destList.Items.Add();
foreach (SPField field in sourceItem.Fields)
{
if (!field.ReadOnlyField && !field.Hidden && field.InternalName != "Attachments")
{
if (destItem.Fields.ContainsField(field.InternalName))
{
//Copy item to destination library
destItem[field.InternalName] = sourceItem[field.InternalName];
}
}
}
//Update item in destination library or list
destItem.Update();
Console.WriteLine("Copied " + sourceItem["ID"] + "to destination list/library");
}
}
}
}

Categories

Resources