Pages

Jul 29, 2010

Retrieving large number of Items from sharepoint list

If you have to reterive a large number of Items and also need a better performance then you should use one of the methods below :

1. Using SPQuery
2. Using PortalSiteMapProvider Class

Lets see the examples for both the methods :
Our Query - Query to get all the Items in a list where Category is "Sp2007"

SPQuery -


// Get SiteColl
SPSite curSite = new SPSite("http://myPortal");
//Get Web Application
SPWeb curWeb = curSite.OpenWeb();
// Create a SPQuery Object
SPQuery curQry = new SPQuery();
// Write the query
curQry.Query = "
SP2007
";
// Set the Row Limit
curQry.RowLimit = 100;
//Get the List
SPList curList = curWeb.Lists(new Guid("myListGUID"));
//Get the Items using Query
SPListItemCollection curItems = curList.GetItems(curQry);
// Enumerate the resulting items
foreach (SPListItem curItem in curItems)
{
string ResultItemTitle = curItem["Title"].ToString();
}

PortalSiteMapProvider class -
The class includes a method calledGetCachedListItemsByQuery that retrieves data from a list based on an SPQuery object that is provided as a parameter to the method call.
The method then looks in its cache to see if the items already exist. If they do, the method returns the cached results, and if not, it queries the list, stores the results in cache and returns them from the method call.

// Get Current Web
SPWeb curWeb = SPControl.GetContextWeb(HttpContext.Current);
//Create the Query
SPQuery curQry = new SPQuery();
curQry.Query = "SP2007";
// Get Portal Map Provider
PortalSiteMapProvider ps = PortalSiteMapProvider.WebSiteMapProvider;
PortalWebSiteMapNode pNode = TryCast (ps.FindSiteMapNode (curWeb.ServerRelativeUrl), PortalWebSiteMapNode);
// Get the items
pItems = ps.GetCachedListItemsByQuery(pNode, "myListName_NotID", curQry, curWeb);
// Enumerate all resulting Items
foreach (PortalListItemSiteMapNode curItem in pItems)
{
string ResultItemTitle = curItem["Title"].ToString();
}

Cross-list queries with SPSiteDataQuery

Scenario:
You need to query cross-list items across multiple Web sites
Solution:

'SPSiteDataQuery' is more efficent for such a situation.
'SPQuery' should be used to query a particular list

Sample Code:


  1. SPWeb webSite = SPContext.Current.Web;
  2. SPSiteDataQuery query = new SPSiteDataQuery();
  3. query.Lists = "";
  4. query.Query = "" +
  5. "Completed";
  6. System.Data.DataTable items = webSite.GetSiteData(query);
  7. foreach (System.Data.DataRow item in items)
  8. {
  9. Response.Write(SPEncode.HtmlEncode(item["Title"].ToString()) + "
    "
    );
  10. }

Jul 28, 2010

SharePoint Stop Working After Changing Server (Computer) Name

If Microsoft Office SharePoint Server (MOSS) and your database (MS SQL Server) are running together on same physical server, changing the name of the server (computer) using operating system may create non-functional SharePoint website.

When you change the physical server name the SharePoint is already connected to the SQL instance of old computer name (OldServerName/SQLInstance) and on changing the name the SharePoint will not able to connect the SQL Server as now the SQL Server instance will run on new computer name (NewServerName/SQLInstance).

To solve this problem you need to reconfigure the entire Microsoft Office SharePoint Server with SQL Server Instance. Please follow the steps to fix the issue.

1. Open command prompt, change directory to where stsadm.exe exists.

C:\cd C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN

2. To invoke setconfigdb operation we need to use stsadm.exe. Run following command on command prompt

stsadm.exe -o setconfigdb -databaseserver ServerName -farmuser MyUserName - farmpasswordMyPassword

3. Go to IIS, All Programs>>Administrative Tools>>Internet Information Service (IIS) Manager.

4. Right Click SharePoint Central Administration v3, click on delete and re-run the configuration wizard; the web application will be re-created by the configuration wizard.

5. After the above operation has completed successfully, run the SharePoint Products and Technologies Configuration Wizard.

All Programs>>Microsoft Office Server >> SharePoint Product and Technologies Configuration Wizard

6. Complete all the steps of wizard by clicking on Next button.

At the end of this process you will get a success wizard.

A Road to Drive your skills to the SharePoint......!

The people who believe that the SharePoint is becoming the next challenge and passion for them The given link will be an effective tool.

To explore the SharePoint Development Arena you can go to the articlehttp://msdn.microsoft.com/en-us/library/dd203468.aspx . This can be a Door to the Limitless opportunities in the world of SharePoint. But, all this requires to open the Door. Go ahead...

SharePoint Best Practices - Write to EventLog from SharePoint Custom Solutions

Just a quick thing to note, if you’re trying to write to the event log within your custom SharePoint solutions and run across this error:

Cannot open log for source {0}. You may not have write access.

This is definitely permissions related. A quick bit of searching and I found some useful info:

The CustomSD registry value for the Application event log is found under the HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Applicationregistry key. It is a string value which uses Security Descriptor Definition Language (SDDL) to describe which accounts have access to which functions (e.g. read, write, clear) of the event log. By default the application event log will allow any IIS 6 application pool identity write access (either as a service logon or, in the case of custom accounts in the IIS_WPG group, as a batch logon). (reference: http://forums.asp.net/t/1131903.aspx)

So the key in the above paragraph is that the app pool identity already has permission to write to the event log, so instead of mucking around with permissions, I made sure my function for writing to the eventlog is elevated as follows:

public static void LogMessage(string message)
{
    SPSecurity.RunWithElevatedPrivileges(delegate()
    {
        if (!EventLog.SourceExists("SharePoint Custom Solutions"))
        {
            EventLog.CreateEventSource("SharePoint Custom Solutions", "Application");
        }
        EventLog.WriteEntry("SharePoint Custom Solutions",
                                    message,
                                    EventLogEntryType.Error); 
});
}

Remote Debugging SharePoint Code.....!

The other day I ran into a situation where I needed to debug an assembly that I had placed in the GAC of the SharePoint server and did not have Visual Studio installed on the SharePoint machine. I knew there were ways to attach to a process so I did a search to see if there was a way I could remotely attach to the process from Visual Studio running on my machine.

The process is pretty easy:

1. Locate the msvsmon.exe file located in C:\Program Files\Microsoft Visual Studio 8\Common7\IDE\Remote Debugger\x86. This file is located on the machine that has Visual Studio installed on it.

2. Copy this file to the machine that you want to debug the code on (the SharePoint machine).

3. Run the exe. This will create a small window on the server that says the remote debugging server is waiting.

4. In Visual Studio on your machine, select Tools -> Attach to Process.

5. Get the process ID for the SharePoint web app you want to debug. You can do this by running the iisapp command from the SharePoint server command line. This will list the AppIDs and the name of the Web applications running on your server.

6. In the Attach to Process dialog, in the Qualifier drop down select the browse button and browse for the SharePoint machine.

7. Once you have the machine, select the process name (w3wp.exe) and the ID that matches the Web app that you want to debug.

8. Click attach and start debugging.

Life was good when apple and blackberry were fruits!

SharePoint: Newbie? Unable to find Developer Help?

Are you a newbie to SharePoint development? (or) Are you looking for a one place where you can find information about help in SharePoint products and technologies?

Andrew Connell has written an excellent article regarding finding developer help for SharePoint products and technologies. Discover where to find the SDKs, peer-to-peer forums, MSDN developer centers, and Microsoft TechNet resources you need as you develop with Microsoft SharePoint Products and Technologies.

Even if you know SharePoint, the article is quite helpful and worth to be bookmarked.

The ItemUpdating event or the ItemUpdated event occurs two times when you enable the Require Check Out option for a document library in Windows ShareP

For solution please refer to the following KB article.

http://support.microsoft.com/kb/939307

Show/Hide ‘Workspace’ on New/Edit Form in Calendar List

My client asked me about hiding a field called 'Workspace' from Calendar: New Event or Edit existing event.
I was wondering that there should be some easy way to hide any field available on 'New' or 'Edit' page.

I googled around, and I found couple of responses, for example:

  1. Modifying the NewForm.aspx page in SharePoint Designer 2007, hiding existing List Form Web Part, and then adding Custom List Form. Then delete the Workspace row from the form.

    Let me talk about the disadvantages of this option:

    • a. Attach File will NOT work. You need to investigate further to make it work. Still painful process.
    • b. Try to create a 'Recurring' event; it will not work as expected.

    Considering these advantages, I thought that this is very tedious process, and one has to make the changes to all calendar lists. And then this change is required to be done on NewForm.aspx and EditForm.aspx. How about that? So it is really very painful process.

  2. Another option is again, modifying the NewForm.aspx or EditForm.aspx, and add following script (However, it didn’t work for me though), but it is worth adding it here, just in case, if people are trying to solve the problem in this manner.

    <script language='JavaScript' type='text/javascript'>     var toolbar = document.getElementByName("");     toolbar.parentNode.parentNode.parentNode.style.display = 'none';     toolbar.parentNode.parentNode.style.display = 'none'; <script>

    This can be added in asp:content ContentPlaceHolderId="PlaceHolderTitleAreaClass".
    Once again as I said that it didn’t work for me, but it can be done this way too.

  3. Recommended way. First thing is that it is a feature, and can be found (12 Hive folder) at C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\Template\Features\EventsList. Yes, it is event list feature. Now the modifications are required in schema.xml that can be found under Events folder (folder location, once again, is ..\12\TEMPLATE\FEATURES\EventsList\Events). This file can be modified in notepad.exe.

    While looking into the Calendar List Settings in Internet Explorer, I noticed that this field 'Workspace' is of type 'Cross Project Link'. This is important to remember, and search 'CrossProjectLink' in schema.xml file. I noticed there is only one instance of it.

    Secondly, the field is SharePoint field so looked for the corresponding class which is SPField. I looked into SPField Class Members on MSDN and found a couple of interesting properties (and used two of them), for example, ShowInDisplayForm, ShowInEditForm, ShowInListSettings, ShowInNewForm, ShowInVersionHistory, ShowInViewForms. I was interested in ShowInEditForm and ShowInNewForm properties only. So in schema.xml file, for Field of Type="CrossProjectLink", added these two properties as attributes, and set the value="FALSE".

    IMPORTANT: attribute value should be set as ShowInNewForm="FALSE" (case sensitive). If you set the value as ShowInNewForm="false", it will not work, so be careful here.

    My final is looked like:

     ID="{08fc65f9-48eb-4e99-bd61-5946c439e691}" Type="CrossProjectLink"      Name="WorkspaceLink" Format="EventList"      DisplayName="$Resources:core,Workspace;" DisplayImage="mtgicon.gif"      HeaderImage="mtgicnhd.gif" ClassInfo="Icon"      Title="$Resources:core,Meeting_Workspace;" Filterable="TRUE"      Sealed="TRUE" SourceID="http://schemas.microsoft.com/sharepoint/v3"      StaticName="WorkspaceLink" ShowInEditForm="FALSE"     ShowInNewForm="FALSE">

    As mentioned, I added only two attributes. Save the schema.xml file.

Now the task is to publish the feature with changes. And since the feature is already installed and activated, so it is mandatory to de-activate it and then un-install it.

To smoothen the process I wrote two batch files one each for de-activate, un-install and install, activate:

script for uninstallfeature.bat

path="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN" cd \ cd "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN" stsadm.exe -o deactivatefeature -filename EventsList\Feature.xml -url http://moss2007:8551/sites/Demo1 stsadm.exe -o uninstallfeature -filename EventsList\Feature.xml -force cd \

It is straight forward to understand, however, if you want instructions for the same, can send me request.

script for installfeature.bat

path="C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN" cd \ cd "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\BIN" stsadm.exe -o installfeature -filename EventsList\Feature.xml stsadm.exe -o activatefeature -filename EventsList\Feature.xml -url http://moss2007:8551/sites/demo1 cd \

URL is required to install the feature, in this script, I am deploying the feature for a specific website.
Don’t forget to do ISRESET

I am done, and when I tried to create or edit a calendar event, I don't see 'Workspace' option in there. I double checked that attach file is working, and I am able to create a 'Recurring' event too.
It is really very useful tip for me, so thought let me add it here for future reference too.

Deleting a Page Layout or Master Page that is no longer referenced

There is a fairly well known bug that prevents you from deleting both page layouts and master pages even though they are no longer in use. If you do try to delete either a page layout or master page you will receive the following error:

"This item cannot be deleted because it is still referenced by other pages. "

There is a workaround for this problem but it requires SharePoint designer. Here is my similar solution except that no SharePoint designer is required.
  1. Browse to the "Master Page Gallery".
  2. Select "Actions" and "Open with Windows Explorer"
  3. Right click on the white area and select "New" > "Folder"
  4. Drag the page layout or master page into the new folder
  5. Right click on the new folder and select "Delete"
  6. Confirm the box
Done!

Denying User Access At The Site Level

It's a pretty well known fact that SharePoint cannot deny access for a user below the Web Application level as shown in the screenshot below. Sadly there will be no code samples for this one as it's pretty proprietary stuff.



Well, one of my clients had this exact problem. Except that the answer "Sorry, SharePoint doesn't do that." didn't solve the underlying business problem. Here is a scenario and the provided "Out-Of-The-Box Solution".
  1. Users are given access to a site through a single group "SharePoint Users".
  2. This "SharePoint Users" group is used throughout the rest of the site collection so simply modifying it is not an option.
  3. John Doe is a member of this "SharePoint Users" group but because of an "Ethical Wall" (Law Firm jargon for blocking one lawyer from seeing another lawyers documents) John Doe cannot have access to this site.
After talking with a Microsoft Employee at a training session the recommended approach is to either create smaller groups... ie: "SharePoint Users" and "SharePoint Users Without John" and to maintain these at the site collection level or to simply remove the "SharePoint Users" group from the site and add all your users directly.

We chose to do the latter in an automated fashion. What we ended up with is as follows.
  1. A custom SQL table that holds the list of people that should be denied access to a particular site.
  2. A Timer Job that constantly ensures that those people are actually denied.
  3. A configuration panel in Central Administration to maintain which web applications are using the functionality and to hold configuration options.
  4. A data input panel built into each SharePoint site to allow administrators to deny users and to view who is currently denied.
The bulk of the code exists in the Timer Job. The Timer Job is responsible for breaking the inheritance, looping through all of the current security, removing groups and readding users with the proper security, and finally removing all the denied users.

This solution has the following pluses
  • Will loop through both SharePoint Groups and AD Groups no matter how complicated the nested group structure is
  • Makes a manual process somewhat automated to ensure less user error
  • Although it creates an administrative problem for adding new users (users will not have acecss when they should) it does protect against the more dangerous scenario (a user does have access when they shouldn't)

Properly Populating and Retrieving SharePoint Field Data

SharePoint uses a lot of field types that have different underlying schemas, delimiters and formats. I see a lot of people reverse engineer the field information and "hack" the data into the list using a string such as "1;#Title" for a lookup field. Well this isn't exactly best practice so I've put together a reference table below to assist in using the correct data types for populating or retrieving information from a SharePoint list.


Lookup Field


Field Class: SPFieldLookup
Field Value Class: SPFieldLookupValue

Populating Information:

item["FieldName"] = new SPFieldLookupValue("Title"); // SharePoint will do the lookup as long as the LookupValue's are unique
item.Update();
or
item["FieldName"] = new SPFieldLookupValue(1, "Title");
item.Update();

Retrieving Information:

SPFieldLookupValue itemValue = item["FieldName"] as SPFieldLookupValue;
int id = itemValue.LookupId;
string value = itemValue.LookupValue;

Multiple Lookup Field


Field Class: SPFieldLookup
Field Value Class: SPFieldLookupValueCollection

Populating Information:

SPFieldLookupValueCollection itemValues = SPFieldLookupValueCollection();
itemValues.Add(new SPFieldLookupValue(1, "Title"));
item["FieldName"] = itemValues;
item.Update();

Retrieving Information:

SPFieldLookupValueCollection itemValues = item["FieldName"] as SPFieldLookupValueCollection;
foreach (SPFieldLookupValue itemValue in itemValues)
{
int id = itemValue.LookupId;
string value = itemValue.LookupValue;
}

User Field


Field Class: SPFieldUser
Field Value Class: SPFieldUserValue

Populating Information:

web.EnsureUser(@"domain\username");
SPUser user = web.AllUsers[@"domain\username"];
item["FieldName"] = user;
item.Update();

Retrieving Information:

string currentValue = item["FieldName"].ToString();
SPFieldUser userField = list.Fields.GetFieldByInternalName("FieldName");
SPFieldUserValue itemValue = (SPFieldUserValue)userField.GetFieldValue(currentValue);
SPUser user = itemValue.User;

URL Field


Field Class: SPFieldUrl
Field Value Class: SPFieldUrlValue

Populating Information:

SPFieldUrlValue urlValue = new SPFieldUrlValue();
urlValue.Url = "http://www.google.com";
urlValue.Description = "Google";
item["FieldName"] = urlValue;
item.Update();

Retrieving Information:

SPFieldUrlValue urlValue = new SPFieldUrlValue(item["FieldName"].ToString());
string url = urlValue.Url;
string description = urlValue.Description;

Multiple Choice Field


Field Class: SPFieldMultiChoice
Field Value Class: SPFieldMultiChoiceValue

Populating Information:

SPFieldMultiChoiceValue itemValue = new SPFieldMultiChoiceValue();
itemValue.Add("Choice 1");
itemValue.Add("Choice 2");
itemValue.Add("Choice 3");
item["FieldName"] = itemValue;
item.Update();

Retrieving Information:

SPFieldMultiChoiceValue itemValue = new SPFieldMultiChoiceValue(item["FieldName"].ToString());
foreach (string choice in itemValue)
{
// value is in choice
}

Microsoft.Office.Server.UserProfiles

UserProfiles.PersonalSite requires a Dispose() call before leaving scope if you use the property in your code. For addition code optimization information please see my blog posthere.

void PersonalSiteLeak() {     // open a site collection     using (SPSite siteCollection = new SPSite("http://moss"))     {         UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));         UserProfile profile = profileManager.GetUserProfile("domain\\username");         SPSite personalSite = profile.PersonalSite;    // will leak     } } 
void PersonalSiteNoLeak() {     // open a site collection     using (SPSite siteCollection = new SPSite("http://moss"))     {         UserProfileManager profileManager = new UserProfileManager(ServerContext.GetContext(siteCollection));         UserProfile profile = profileManager.GetUserProfile("domain\\username");         using (SPSite personalSite = profile.PersonalSite)         {             // ...         }     } }