Showing posts with label MOSS. Show all posts
Showing posts with label MOSS. Show all posts

Thursday, May 06, 2010

Manage Custom Actions on Sharepoint

Today I searched over an hour until I found the following 3 Links regarding custom actions on Sharepoint.



You find there an example for any custom action possibility which GroupId and Location you have to set for a CustomAction.

Thanks to them!

Thursday, April 22, 2010

MOSS 2007 reading from list including attachments

The following code sample display how to read from a Sharepoint 2007 list which includes also attachments. I haven't used this code for MOSS 2010!

    

private ICredentials GetCredentials()
{
return new NetworkCredential("username", "password", "domain");
}

private DataRowCollection LoadSharepointData(string viewFields, string listName)
{
WebServiceRef.Lists sp = new WebServiceRef.Lists();
sp.Url = "http://your.sharepoint.com/_vti_bin/Lists.asmx";
sp.Credentials = GetCredentials();

// this part is needed to receive the link to document attachments and all specified fields
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");
ndQueryOptions.InnerXml = "<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>";
ndViewFields.InnerXml = viewFields;
ndQuery.InnerXml = ""; // <Query />

XmlNode allLists = sp.GetListCollection();
XmlNode lists = sp.GetListItems(listName, "", ndQuery, ndViewFields, "10000", ndQueryOptions, "");

XmlNodeReader r = new XmlNodeReader(lists);
DataSet ds = new DataSet();
ds.ReadXml(r, XmlReadMode.Auto);

return ds.Tables[1].Rows;
}


WebServiceRef is a normal Web Service reference to Sharepoints List Webservice:
- http://your.sharepoint.com/_vti_bin/lists.asmx

The following code blocks contain various helper classes to extract data row by row, download attachments and saving data to a local folder.

Here we have the class to download files from Sharepoint:


public class AttchmentHandler
{
private static CookieContainer _cookieContainer;
public static CookieContainer CookieContainer
{
get
{
if (_cookieContainer == null)
{
_cookieContainer = new CookieContainer();
}
return _cookieContainer;
}
}

public class CookieAwareWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = AttchmentHandler.CookieContainer;
(request as HttpWebRequest).KeepAlive = false;
}
return request;
}
}

public string DownloadSharepointAttachment(string url, string filename, ICredentials credentials)
{
string localFolder = @"D:\\LocalFolder\\";

// ensure we do not overwrite files with the same name.
string uniqueGuid = Guid.NewGuid().ToString();
//now the code that will download the file
try
{
using (WebClient client = new CookieAwareWebClient())
{
client.Credentials = credentials;
// client.DownloadFile("http://address.com/somefile.pdf", @"c:\\temp\savedfile.pdf");
client.DownloadFile(url, localFolder + uniqueGuid + "_-_" + filename);
client.Dispose();
}
return localFolder + uniqueGuid + "_-_" + filename;
}
catch (Exception ex)
{
Console.WriteLine("DownloadSharepointAttachment: " + ex.Message);
return string.Empty;
}
}
}


To extract data from the DataRowCollection we have to Parse each row. For that i had to write 2 methods, one which retrieves the row and another one which extract the data from the column.



public void ParseAndExtractRow(System.Data.DataRow data, ICredentials credentials)
{
this.ContentTypeId = this.GetRowValue(data, "ows_ContentTypeId");
this.Title = this.GetRowValue(data, "ows_Title");
this.Date = this.GetRowValue(data, "ows_Date");

if (string.IsNullOrEmpty(this.Date))
this.Date = DateTime.Now.ToString();

DateTime.TryParse(this.Date, out this.DateTimeSorting);

this.Attribute_01 = this.GetRowValue(data, "Attribute_01");
// add here all other attributes
// ....
// ...
// ...
}

private string GetRowValue(System.Data.DataRow data, string columnName)
{
try
{
if (data[columnName] != null)
return data[columnName].ToString();
else
return string.Empty;
}
catch (Exception ex)
{
// Console.WriteLine(ex.Message);
return string.Empty;
}
}


Finally a method which uses all this code:

    private List<Data> ExtractList()
{
string listname = "SharepointListName";

string viewFields = "";
DataRowCollection rows = LoadSharepointData(viewFields, listname);
List<Data> data = new List<Data>();
int i = 0;
foreach (DataRow row in rows)
{
Data b = new Data();
try
{
b.ParseAndExtractRow("Name", row, GetCredentials());
data.Add(b);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
finally
{
b = null;
}
}
return data;
}


enjoy

Sharepoint MOSS 2007 distribute announcement over several site collections

The following lines of code iterate over all site collections within a Sharepoint / MOSS 2007 Farm and it's adding an announcement to each site collection.

To use this code i had to impersonate the user to the application pool user. This is the only user which allows me to access all content databases.

// connect to sharepoint and read all site collections under "default web site"
foreach (var application in SPWebService.ContentService.WebApplications)
{
siteCollectionMax = application.Sites.Count;

this.UpdateProcess(string.Format("Connecting to: {0}", application.Name));
this.UpdateProcess(string.Format("Total Amount of #{0} site collections", siteCollectionMax));

this.UpdateProcess("- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - ");

string currentUrl = string.Empty;
this.UpdateProcess(
"Connecting to Sharepoint this can take some seconds!"
);
System.Threading.Thread.Sleep(500);

foreach (SPSite site in application.Sites)
{
try
{
currentUrl = site.Url;
siteCollectionCounter++;

using (SPSite s = new SPSite(site.Url))
{

using (SPWeb web = s.OpenWeb())
{
SPList list = web.GetList(s.Url + "/Lists/Announcements");
if (list != null)
{
SPListItemCollection items = list.Items;
SPListItem item = items.Add();
item["Title"] = title.Trim();
item["Body"] = body.Trim();
item["Expires"] = expiries;
item.Update();
this.UpdateProcess(
string.Format("#{0} of {1} - Announcement added to 'Site Collection': {2}", siteCollectionCounter.ToString(), siteCollectionMax.ToString(), currentUrl)
);
}
else
{
string txt = string.Format("Following 'Site Collection' does not contain an Announcement List: {0}", currentUrl);
this.UpdateProcess(
txt
);
errors.Add(txt);
}
}
}
System.Threading.Thread.Sleep(250);
}
catch (Exception ex)
{
this.UpdateProcess(
string.Format("An error occured: {0}", ex.Message)
);
}
}
}


The this.UpdateProcess(...) method is a helper method which writes into a log file. You can simply replace it and write to the Console.

Tuesday, April 20, 2010

The security validation for this page is invalid. Click Back in your Web

While i was developing certain Sharepoint MOSS 2007 maintenance stuff I received the following error:

"The security validation for this page is invalid. Click Back in your Web..."

I developed the code against MOSS API and not on the website and was a kind of irritated about it!

The solution to solve this can be one of the following ways:

Option A)
turn off the security validation over your central administration:
- Central Administration
- Application Management
- Web Application Aettings
- "turn security validation off"

Option B)
You can modify the setting also within you coding:

SPSecurity.RunWithElevatedPrivileges(new SPSecurity.CodeToRunElevated(
delegate()
{
using (SPSite oSite = new SPSite("http://your.website.com/"))
{
using (SPWeb web = oSite.OpenWeb())
{
SPWebApplication webApp = web.Site.WebApplication;
webApp.FormDigestSettings.Enabled = false;
web.AllowUnsafeUpdates = true;


web.AllowUnsafeUpdates = false;
webApp.FormDigestSettings.Enabled = true;
web.close();
}
}
}
)
);

Monday, April 19, 2010

Development often requires impersonation with Sharepoint (MOSS) 2007


public class Impersonator
{
public string CurrentUser
{
get
{
return this.username;
}
}

public string Domain
{
get
{
return this.domain;
}
}

// private members for holding domain user account credentials
private string username = String.Empty;
private string password = String.Empty;
private string domain = String.Empty;
// this will hold the security context for reverting back to the client after impersonation operations are complete
private WindowsImpersonationContext impersonationContext = null;

// disable instantiation via default constructor
private Impersonator()
{ }

public Impersonator(string username, string domain, string password)
{
// set the properties used for domain user account
this.username = username;
this.domain = domain;
this.password = password;
}

private WindowsIdentity Logon()
{
IntPtr handle = new IntPtr(0);
handle = IntPtr.Zero;

// This stuff required for impersonation
//const int LOGON32_LOGON_NETWORK = 3;
//const int LOGON32_LOGON_SERVICE = 3;
const int LOGON32_PROVIDER_DEFAULT = 0;
const int LOGON32_LOGON_INTERACTIVE = 2;

// attempt to authenticate domain user account
// bool logonSucceeded = LogonUser(this.username, this.domain, this.password, LOGON32_LOGON_NETWORK, LOGON32_PROVIDER_DEFAULT, ref handle);
bool logonSucceeded = LogonUser(this.username, this.domain, this.password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref handle);

if (!logonSucceeded)
{
// if the logon failed, get the error code and throw an exception
int errorCode = Marshal.GetLastWin32Error();
throw new Exception("User logon failed. Error Number: " + errorCode);
}

// if logon succeeds, create a WindowsIdentity instance
WindowsIdentity winIdentity = new WindowsIdentity(handle);

// close the open handle to the authenticated account
CloseHandle(handle);

return winIdentity;
}


public void Impersonate()
{
// authenticates the domain user account and begins impersonating it
this.impersonationContext = this.Logon().Impersonate();
}


public void Undo()
{
// rever back to original security context which was store in the WindowsImpersonationContext instance
this.impersonationContext.Undo();
}

[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool LogonUser(string lpszUsername,
string lpszDomain,
string lpszPassword,
int dwLogonType,
int dwLogonProvider,
ref IntPtr phToken);

[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
private static extern bool CloseHandle(IntPtr handle);

}

Thursday, April 15, 2010

Sharepoint MOSS 2007: AllUsers vs. SiteUsers vs Users

According WSS SDK's definition:
*******************************

SPWeb.AllUsers – Gets the collection of user objects that represents all users who are either members of the site or who have browsed to the site as authenticated members of a domain group in the site

SPWeb.SiteUsers – Gets the collection of all users that belong to the site collection

SPWeb.Users – Gets the collection of user objects that are explicitly assigned permissions on the Web site

very confusing how microsoft decided to manage users and profile in Sharepoint 2007

Friday, April 02, 2010

Extract Data from MOSS 2007 (Sharepoint)

The following classes shows how easy it can be to extract data from MOSS 2007 (Sharepoint) and fill the values into properties. The class also checks if there are attachments if so, then it will download attached files to a local path.

the sample below assumes that you have created a Web References to your sharepoint list web service: https://your.sharepoint.com/_vti_bin/lists.asmx

please notice that i have copy and pasted methods from various classes into one class without running it, so don't be surprised if you get any compilation error.

the main aim behind it is to extract data from a bug tracker list and import it over the tfs api 2010 into team foundation server.

public class Sharepoint2007Wrapper
{
public string Title { get; set; }
public string Date { get; set; }
public string CreatedBy { get; set; }

[System.Diagnostics.DebuggerStepThrough]
private ICredentials GetCredentials()
{
return new NetworkCredential("username", "password", "domain");
}

private DataRowCollection LoadSharepointData(string viewFields, string listName)
{
sharepoint.Lists sp = new MigrationToolExportImport.sharepoint.Lists();
sp.Url = "http://url.ToYourSiteCollection.com/_vti_bin/Lists.asmx";
sp.Credentials = this.GetCredentials();

// this part is needed to receive the link to document attachments and all specified fields
XmlDocument xmlDoc = new System.Xml.XmlDocument();
XmlNode ndQuery = xmlDoc.CreateNode(XmlNodeType.Element, "Query", "");
XmlNode ndViewFields = xmlDoc.CreateNode(XmlNodeType.Element, "ViewFields", "");
XmlNode ndQueryOptions = xmlDoc.CreateNode(XmlNodeType.Element, "QueryOptions", "");

// receive links to the attachments
ndQueryOptions.InnerXml = "<IncludeAttachmentUrls>TRUE</IncludeAttachmentUrls>";
ndViewFields.InnerXml = viewFields;
ndQuery.InnerXml = ""; // <Query />

XmlNode allLists = sp.GetListCollection();
// ensure the number is big enough because without this value sharepoint returns configured amount which is 100 per view!
// listsgetlistitems method lists only 100
XmlNode lists = sp.GetListItems(listName, "", ndQuery, ndViewFields, "10000", ndQueryOptions, "");

XmlNodeReader r = new XmlNodeReader(lists);
DataSet ds = new DataSet();
ds.ReadXml(r, XmlReadMode.Auto);

return ds.Tables[1].Rows;
}

public void Extract(string listname)
{
if(string.IsNullOrEmpty(listname))
listname = "Your Sharepoint 2007 List Name";
// if nothing is provided then it returns all rows otherwise
// uese fieldRef tags to retrieve only requested columns
// <FieldRef Name="LinkTitle" /> <FieldRef Name="Title" />
string viewFields = "";
DataRowCollection rows = LoadSharepointData(viewFields, listname);

int i = 0;
foreach (DataRow row in rows)
{
try
{
if ((++i % 10) == 0)
Console.Write('.');
this.ParseAndExtractRow(row, GetCredentials());
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}

private List<string> Attachments { get; set; }

private void ParseAndExtractRow(System.Data.DataRow data, ICredentials credentials)
{
// this helps to identify which text we need to retrieve the column value
this.PrintColNames(data);

this.Title = this.GetRowValue(data, "ows_Title");
this.Date = this.GetRowValue(data, "ows_Date");
this.CreatedBy = this.GetRowValue(data, "ows_CreatedBy");
}

private void DownloadAttachments(string urls, ICredentials credentials)
{
this.Attachments = new List<string>();
string[] fileUrls = urls.Split('#');
if (fileUrls != null && fileUrls.Length > 0)
{
foreach (string file in fileUrls)
{
string uri = file.Replace(";", "");
if (!string.IsNullOrEmpty(uri) && uri.Length > 1)
this.Attachments.Add(uri);
}
}

List<string> filepaths = new List<string>();

if (this.Attachments.Count > 0)
{
foreach (string url in this.Attachments)
{
try
{
string file = System.IO.Path.GetFileName(url);
string filepath = new Attchments().DownloadSharepointAttachment(url, file, credentials);
if (System.IO.File.Exists(filepath))
filepaths.Add(filepath);
else
Console.WriteLine("File does not exists!!");
}
catch (Exception ex)
{
Console.WriteLine("Error upon file download: " + ex.Message);
}
}
this.Attachments.Clear();
this.Attachments.AddRange(filepaths);
}
}

private void PrintColNames(System.Data.DataRow data)
{
for (int i = 0; i < data.Table.Columns.Count; ++i)
{
Console.WriteLine(data.Table.Columns[i].ToString());
}
}

private string GetRowValue(System.Data.DataRow data, string columnName)
{
try
{
if (data[columnName] != null)
return data[columnName].ToString();
else
return string.Empty;
}
catch (Exception ex)
{
return string.Empty;
}
}

private class Attchments
{
private static CookieContainer _cookieContainer;
public static CookieContainer CookieContainer
{
get
{
if (_cookieContainer == null)
{
_cookieContainer = new CookieContainer();
}
return _cookieContainer;
}
}

public class CookieAwareWebClient : WebClient
{
protected override WebRequest GetWebRequest(Uri address)
{
WebRequest request = base.GetWebRequest(address);
if (request is HttpWebRequest)
{
(request as HttpWebRequest).CookieContainer = AttchmentHandler.CookieContainer;
(request as HttpWebRequest).KeepAlive = false;
}
return request;
}
}

public string DownloadSharepointAttachment(string url, string filename, ICredentials credentials)
{
string localFolder = @"Z:\\YourRequestedLocationOnYourHardDrive\\";
// ensure we do not overwrite files with the same name.
string uniqueGuid = Guid.NewGuid().ToString();

//now the code that will download the file
try
{
using (WebClient client = new CookieAwareWebClient())
{
client.Credentials = credentials;
// client.DownloadFile("http://address.com/abc.pdf", @"c:\\temp\abc_local.pdf");
client.DownloadFile(url, localFolder + uniqueGuid + "_-_" + filename);
client.Dispose();
}
return localFolder + uniqueGuid + "_-_" + filename;
}
catch (Exception ex)
{
Console.WriteLine("Download Sharepoint Attachment Error: " + ex.Message);
return string.Empty;
}
}
}
}

Thursday, November 12, 2009

TFS WSS extension installation for MOSS 2008 64bit

I found quite a lot of information about this issue around there but I had my problems to figure out where to download the extension. Finally I found them as a download link under "Visual Studio Team System 2008 Team Foundation Server Power Tools - October 2008 Release"

In the download section there is a download button for: WssExt64Bit.msi





Wednesday, July 30, 2008

Lists.GetListItems Method (Lists) - only 100 items returned

An application I'm developing against Sharepoint 2007 (MOSS) is reading from provided WebService data from a list.

http://YourURI.COM/Data/_vti_bin/Lists.asmx

Since the application is growing we get more and more items within lists.

The Method I uses were:
public XmlNode GetListItems ( string listName, string viewName, XmlNode query, XmlNode viewFields, string rowLimit, XmlNode queryOptions, string webID);

I do not add any rowLimit (null) but I were able to handel this over lists defaults.

  • navigate to sharepoint
  • select your list
  • list settings
  • All Items below Views
  • manipulate Item Limit to an approperiate amount

Once I done above steps i got all my 102 entries from the list.

Wednesday, March 14, 2007

surprise: int.TryParse(xx,yy)

I really get surprised about the following behaviour:

when I've tried to use the follwoing line of code:

if(!int.TryParse(row["myRowName"] as string, out myDefinedInt))

tryParse always returned me false and I assinged a default value. After making sure that all my rows have values for myRowName I were confused.

a friend suggested to use row["myRowName"].ToString() and voila it worked like i wanted.

I didn't really figured out why that happens, then in none of my cases the value were empty that my expression as string would return null.

here a bit more code:

DataSet data = DataReader.GetData();
DataTable tab = data.Tables["MyTableName"];
DataView view = tab.DefaultView;

view.RowFilter = "RowNameA LIKE '%" + valA + "%' AND RowNameB LIKE '%" + valB + "%'";

if (view.Count > 0)
{
Data.MyDataObject item;
foreach (DataRowView row in view)
{
item = new Data.MyDataObject();
item.SomeValue1 = row["SomeValue1"] as string;
item.SomeValue2 = row["SomeValue2"] as string;
int outData = -1;
if (!int.TryParse(row["SomeValue3"].ToString(), out outData))
{
item.SomeValue3 = 40;
}
else
{
item.SomeValue3 = outData;
}

etc ... etc ... etc ...

Thanks to richi (Y)

Tuesday, January 16, 2007

install Webpart dll's into your MOSS Server GAC with a simple VS post-build event

after many different tries how to automate that local deployment from the Win XP machine to my MOSS 2007 Development Server instance i figured out my way how to do this:

- Build your solution and your DLL is deployed :-)

that's all. I think that's pretty cool.

so how you do it:

- download PsExec v1.73
- create 2 batch files (*.bat or *.cmd)

- Batch No. 1: run's as post build event of your compilation

- this file should include the following steps:
1. receives as argument the dll full path and just the dll name;
e.g:
Arg 1: C:\MyProjects\VisualStudioSolution\Moss\indexus.net.dll
Arg 1: indexus.net.dll
2. you copy your arg 1 to a share on your server
2. you call your batch no. 2 with arg 2

- Batch No. 2: run's as remote batch file over psExec.

- don't forget that psExec is running like a local command line
on your server, you need to know where you have call it.

- C:\cmd\psExec.exe -d \YourServerName C:\YourServerShare\[arg no.2]

hope this helps!

Thursday, January 11, 2007

Suggestion for Microsoft.SharePoint.dll; just install it into your local XP GAC

open the ".NET Framework SDK Command Prompt" :: c:\Program Files\Microsoft Visual Studio 8\SDK\v2.0>

here you enter the following line: gacutil /i "C:\yourfolder\Microsoft.SharePoint.dll"

Microsoft (R) .NET Global Assembly Cache Utility. Version 2.0.50727.42
Copyright (c) Microsoft Corporation. All rights reserved.

Assembly successfully added to the cache

--

now you can reference your MOSS 2007 assembly into each Visual Studio Project you gone create from the the Assembly Selection.

thats all you need :-)

Development MOSS 2007 Webparts on Windows XP computer

30 min. of wasting time - at least!

The issue. You want to develop components that interact with the SharePoint, lets say a simple Webpart. Here comes the clue, you local machine is a Windows XP machine and you are not able to install MOSS 2007 on it. What a pitty!

So here we go

Surly I tried to find them on the server but had a hard time.

Navigate to your Server like this:

\\SharedServerMitMOSS2007\C$\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI

copy it to your local environment and simply refernece it in your project.

what do you mean, can I send Microsoft a bill for wasting so much time???

Shared Cache - .Net Caching made easy

All information about Shared Cache is available here: http://www.sharedcache.com/. Its free and easy to use, we provide all sources at codeplex.

Facebook Badge