Sunday, July 19, 2009

SharePoint document and picture rating features/webparts

Hi all,

I had requirement where users have to rate a picture and document. Each user can rate only once picture in different categories. Same applies documents as well.

I just searched and find an awesome toolkit which has on codeplex.
You can find it here.

Here are features of this toolkit:
- New "Show Ratings" webpart showing all the ratings of a given site/site collection
- New site collection report
- Using rating comments with blogs is now possible
- Custom stsadm rating commands have been added to ease the activation/deactivation of the rating features and to collect some rating reports accross webs/site collections/web applications
- Bug fixing in both Forms Designer and the rating solution
- The rating manual has been updated, make sure to download it*



It also comes with detailed documentation and 2 screencasts.

Cheers,
--aaroh

How to: Regional Settings for Central Administration

Hi All,

I was recently looking for regional settings for Central Administration and really could not find it. In fact, for site collection or sites we can easily set the regional settings using Site Actions -> Site Settings -> Regional Settings.

But you can access using this link: /_layouts/regionalsetng.aspx on the Central Administration.

Cheers,
--aaroh

How to: combine multiple projects in one WSPBuilder Solution

Hi all,

We frequently use WSPBuilder to package the WSP solutions. We may need multiple projects but we need to just one WSP solution. After reading WSPBuilder documentation, I found a that "BuildSolution" command doesn't work. (or may be I have not used it properly). But I have user an alternative approach.

For an illustration, I two WSPBuilder projects and already complied:
1) SimpleWorkflow
2) SimpleEventHandler

To combine multiple projects into one WSPBuidler solution (i.e. single WSP), we have to follow these steps:

STEP1: Choose any base project such as SimpleWorkflow.
Right-click on "Solution" and choose "Add Existing Project".














STEP2: View both the projects as shown:













STEP3: Add a new deployment project. Its better to add a completely new project just for the deployment.
Right-click on "Solution" and choose "Add New Project".
































STEP4: Right click on _Deployment project, "Add New Item" >> Choose XML template and name is WSPBuilder.exe.config. (Its there from WSPBuilder documentation)

Just copy this code in WSPBuilder.exe.config


<?xml version="1.0" encoding="utf-8" ?>

<configuration>

<appSettings>

<!-- EXISTING SETTINGS -->

<!-- As in C:\Program Files\WSPTools\WSPBuilderExtensions\WSPBuilder.exe.config -->

<!--<add key="BuildDDF" value="true" /> -->

<!-- As in C:\Program Files\WSPTools\WSPBuilderExtensions\WSPBuilder.exe.config, but value changed from 3 to 4 for more feedback -->

<add key="TraceLevel" value="4" />

<!-- MIKE'S EXTRA SETTINGS -->

<!-- The following key will ensure we build in debug mode. -->

<!--<add key="BuildMode" value="Debug" /> -->

<!-- The following key will override the wsp default of files in dev GAC dir going to the gac, and those in the bin dir going to the iis site bin directory. -->

<!--<add key="DeploymentTarget" value="GAC" /> -->

<!-- The following key will create a full 12 hive in your projects, so use only if you need all deployable folders -->

<!--<add key="Createfolders" value="True" /> -->

<!-- Don't delete intermediate files such as the manifest.xml (don't add these files to source control) -->

<!--<add key="Cleanup" value="False" /> -->

<!-- New name proposed for current BuildSolution key -->

<!--<add key="BuildMultipleProjects" value="True" /> -->

<!-- Build all projects into one solution -->

<add key="BuildSolution" value="True" />

<!-- Solution path - this tells WSP builder to step back one level for the master (startup/build) project to the main 'wsp solution'

folder, and build all projects within that folder to one wsp (cab). By default this wsp will take the name of the folder it sits

in, or use the WSPName key (see below) to give your own name. Unfortunately this dictates a rigid project folder structure, so it

is advised that projects used in more than one wsp solution solutions are subsequently 'referenced/linked' in source control to

match this client build structure rather than physically copied. They can then be 'project referenced' in Visual Studio, which

leaves the option of branching them completely if required. Although this promotes re-use, care should be taken as it often

indicates a new wsp is required to prevent inadvertent upgrades or clashes with already installed features in other solutions.

If it is a variation, consider branching or copying files (especially feature.xml to ensure guid is used), dll referencing of base

feature and inheritance. -->

<add key="SolutionPath" value="..\" />

<add key="OutputPath" value="..\" />

<add key="ExcludePaths" value="..\_Deployment\"/>

</appSettings>

</configuration>

I have also added a key "ExcludePaths" and have value of "..\_Deployment".

STEP5: Build "_Deployment", compile it, and then use this command WSPBuilder >> Build WSP.

Your ONE WSP solution with two projects included.
The only small problem is in "_Deploy" does not an option for "Deploy" using WSPBuilder.







So, we have to use STSADM commands to add solution and deploy solution.

Cheers,
--aaroh

How to: fixing Out of box Approval Workflow issue and solution - Part 1

Hi All,

I came across an interesting behavior of SharePoint out of the box "Approval Workflow".

PROBLEM:
Apparently, when an item is attached to Approval workflow to control content approval for a user with contribute permissions, they can approve their own major version of an item through the approve button in the workflow.

There a no way to configure the workflow so the site members (contribute permission level) can not approve their own major versions of an item. Its really a MAJOR drawback of out of the box Approval Workflow.

For e.g.

>> Create a new team site such as Document Repository
>> Under "People and Group" section, configure site permissions for groups as follows:
i) Document Authors - with Contribute permission.
ii) Approvers - with Approvers permission.
iii) Visitors - with Read-Only permission.


>> Configure Shared Documents Library

Versioning Settings:

Require content approval for submitted items? Yes
Create a version each time you edit a file in this document library? Create major and minor (draft) versions
Who should see draft items in this document library? Only users who can edit items
Require documents to be checked out before they can be edited? Yes

Workflow Settings:

Start this workflow to approve publishing a major version of an item.
Allow this workflow to be manually started by an authenticated user with Edit Items Permissions
After the workflow is completed: Update the approval status (use this workflow to control content approval)

TESTING:

>>Login as Doucment Author
>> upload a new document and check in
publish a major version - Approval workflow will start
Enter the an Approver.
Use Approve/reject from the item drop down - will receive Error Access Denied. EXPECTED BEHAVIOR.
Go to task list and approve task - workflow will be completed and version 1.0 approval status approved. NOT EXPECTED BEHAVIOR.

Therefore, document author who has contributor permissions can approve his own document and its counter-intuitive.


SOLUTION:

Though we should not touch out of the box behavior, but can certainly change TASK list's behavior. Here is easy workaround.

These are the steps: (obviously, a coding effort is required!)

>> You need an event handler which is associated with TASK list.
>> Get the role definition for "Contributor" permission. (i.e. Document Author)
>> Check the role of user. If it’s a Contributor then throw an error. If it’s an approver then don’t take any action.
Here is the code. Though it needs some improvements but it works properly. I have not touched OOTB workflow, just modified its behavior using TASK list.



MY EVENT HANDLER CODE

public override void ItemUpdating(SPItemEventProperties properties)
{
base.ItemUpdating(properties);

this.DisableEventFiring();

using (SPWeb currentTeamSite = properties.OpenWeb())
{
SPListItem currentItem = properties.ListItem;

// A role definition is required to represent a permission level in SharePoint site
SPRoleDefinition roledefinition = currentTeamSite.RoleDefinitions.GetByType(SPRoleType.Contributor);

bool isContributor = currentItem.AllRolesForCurrentUser.Contains(roledefinition);

if (isContributor)
{
properties.Cancel = true;
properties.ErrorMessage = "You dont have access to this operation because of your access rights.";
}
}


this.EnableEventFiring();
}


In the elements.xml, use ListTemplateId=107 which is base list template id. Tt worked perfectly fine for our case.

Hope it will work fine for others too,

Cheers,
--aaroh

Sunday, March 29, 2009

Earth hour in Singapore

We observed earth hour in our own special way in Singapore. We did our bit for the environment by switching off our lights and heading out to East Coast Park.
As we lay on the beach and looked at the stars we thought to ourselves that until humanity realizes the consequences of not being prudent about saving our resources it could become too late.

Monday, January 26, 2009

CAML and DateTime issues and the solution.

Hi Friends,

During one of my projects, I had to work on SPQuery objects, SPList, SPListItemCollection, CAML and date time formats. Let me introduce me business case:

Business case:
Its for the team calendar. If a team member apply for vacations and public holiday falls during his/her vacations then system should deduct that number of public holidays.

Roadblocks:
1) there is no straight forward method for filtering date time functions.
2) SharePoint includes date and time parts. But my case just needs date and not time.

My Solution:
I created a function called as GetBankHolidays with 3 parameters:
1) Start Date for team member (date1)
2) End date for team member (i.e. End date - Start date = total number of days for his vacation) (date2)
3) SPItemEventProperties


4) Firstly, get date range for SPQuery.
It can easily defined like this:

Start date of team member
End date of team member

>> query.Query = "<Where><And><Geq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>" + date1 + " </Value></Geq><Leq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>" + date2 + "</Value></Leq></And></Where>";


5) Secondly, we need to use SharePoint function. But we need to include one more namespace: using Microsoft.SharePoint.Utilities;
SPUtility.CreateISO8601DateTimeFromSystemDateTime(date1) and
SPUtility.CreateISO8601DateTimeFromSystemDateTime(date2).

>> query.Query = String.Format("<Where><And><Geq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{0}</Value></Geq><Leq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{1}</Value></Leq></And></Where>", SPUtility.CreateISO8601DateTimeFromSystemDateTime(date1), SPUtility.CreateISO8601DateTimeFromSystemDateTime(date2));

6) Thirdly, we also need to ignore the time part. This can be done by "IncludeTimeValue" attribute.

>> query.Query = String.Format("<Where><And><Geq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{0}</Value></Geq><Leq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{1}</Value></Leq></And></Where>", SPUtility.CreateISO8601DateTimeFromSystemDateTime(date1), SPUtility.CreateISO8601DateTimeFromSystemDateTime(date2));

The final function be obtained by GetBankHolidays.





/// <summary>

/// Computes no. of bank holidays during user's vacation and return an INT ( = number of bank holidays)

/// </summary>

/// <param name="date1"></param>

/// <param name="date2"></param>

/// <returns></returns>

public static int GetBankHolidays(DateTime date1, DateTime date2, SPItemEventProperties properties)

{
using (SPWeb web = properties.OpenWeb())
{
// counter for bank holidays

int count = 0;


SPListItemCollection items = null;
SPList holidaysList = web.Lists["Bank Holidays"];



SPQuery query = new SPQuery();



query.Query = String.Format("<Where><And><Geq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{0}</Value></Geq><Leq><FieldRef Name='Day' /><Value Type='DateTime' IncludeTimeValue='FALSE'>{1}</Value></Leq></And></Where>", SPUtility.CreateISO8601DateTimeFromSystemDateTime(date1), SPUtility.CreateISO8601DateTimeFromSystemDateTime(date2));




while (date1.Date <= date2.Date)

{
items = holidaysList.GetItems(query);



foreach (SPListItem item in items)
{
if (Convert.ToDateTime(date1.Date) == Convert.ToDateTime(item["Day"]))
count++;
}
date1 = date1.AddDays(1);

}

return count;

}



Happy programming!

Cheers,
Aroh

Sunday, January 18, 2009

How to: Creating a SharePoint 2007 feature

In this tutorial,I will show, how to develop a feature for SharePoint 2007 from the scratch. In our case, I will use item event handler and calendar list. What I will be showing is that SharePoint users can add, modify their entries but if they delete an calendar item then they could not delete.

Prerequisite:

1) Download WSPBUILDER, get it here
2) Download SharePoint Utility, get it here

Steps:

1) Create the class library.

>> Open Visual Studio 2008 >> create new class library



Project Name: CalendarEventHandler and click OK.

>> Add Reference to SharePoint services assembly.



>> Locate Sharepoint.dll and click OK.



>> Rename Class1.cs to CalendarEventHandler.cs




2) Writing the event handler code


>> Code the event handler.



We be using WSS API and in CalendarAction.cs file, we inherit from SPItemEventReceiver.

Now, we are creating ItemDeleting method and override the our own custom code. In fact, we are creating a very simple event handler but we can really enhance the event handler and manipulate one list with update another lists. I would be writing a blog about more enhance ItemEventReceiver in few days time.

The ItemDeleting method can be called and the properties parameter contains detailed information about fired that event.

>> When in user deletes an item, then ItemDeleting event is fired asynchroneously i.e. before an item is deleted.


3) Sign the assembly


>> Once when done with the coding, we need to compile and sign the assembly.
>> Follow these steps:
>> Solutions Explorer >> Properties >> Signing >> New.



>> Create a new strong name.



>> Now, we use WSPBuilder to "Copy to GAC".
Right click on Solutions Explorer >> WSPBuilder >> Copy to GAC.




>> We double check if the assembly is successfully installed.

C:\WINDOWS\assembly





4) Creating the resource files


>> SharePoint feature besides compiled dll, requires some other files on the server too. The folder structure (called as "12" hive) and just add into this folder structure.

>> Right click on Solutions Explorer >> Add this folder structure.



>> There 2 xml files in the folder structure.
>> feature.xml and code is as follows:




Create GUID can be obtained from Tools >> Create GUID





>> elements.xml

This file will attach the event handler (CalendarAction.cs code) to a particular list ("Calendar List")

This is the code:



Some important points to be noted:

i) ListTemplateId="106". 106 corresponds to "calendar event". Complete list ListTemplateId could be found here.

ii) In our case we have added just one Receiver i.e. ItemDeleting. But in real buisness solutions we may need more than one receiver like ItemAdding, ItemAdded ItemUpdating, ItemUpdating etc for e.g.




iii) There is one more SharePoint Utility package. Its for ItemDeleting code with corresponding lists. In our case its Calendar list.

5) Building wsp and deploying to server


Once xml files have been done, we need to building wsp (What is WSP?? A solution is a deployable, reusable package that can contain a set of Features,web parts site definitions, and assemblies that apply to sites, and that you can enable or disable individually.It allows the SharePoint administrators to easily deploy the customizations, even scheduled deployments and multi front-end-webserver deployments are supported.)

>> Right click on Solutions Explorer >> WSPBuilder >> Build WSP



>> When WSP has been done, we just need to deploy to server
>> Right click on Solutions Explorer >> WSPBuilder >> Deploy



>> Now, check in Central Administration if WSP has been successfully installed.



>> We go to SharePoint site, and activate the feature.






6) Testing the feature.


>> we can add a new Calendar item and try to delete the same to test our new feature.






CONGRATS!! we have developed a simple Calendar event handler successfully.

These are some other tips for event handlers.

>> If you want to add more one more item event handler like ItemAdding, ItemAdded, ItemUpdating, ItemUpdated to existing Calendar event handler (like we did on this walk through), then we have to follow steps steps:

i) Uninstall CalendarEventHandler.dll (c:\WINDOWS\assembly)
ii) In Central Administration, Retract the CalendarEventHandler.wsp and Delete the solution.
iii) In CalanderAction.cs file, code new event handlers (new methods) like ItemAdding, ItemAdded, ItemUpdating etc.

iv) compile it and copy to GAC using WSPBuilder.
v) Build WSP and deploy to server.

THATS IT!

Happy programming!

Low Code Reimagined with AI + Copilot Pitch Deck - Copy Copilot day (Virtual) - 2023

 Hi All,  I presneded a session at Pune UG on Low Code Reimagined with AI + Copilot Pitch Deck.  Video is at this address  https://www.youtu...