Friday, August 7, 2009

70-541 WSS 3.0 Application Development

Today I passed the WSS 3.0 application development exam. Stay tuned I will blog some nice tips and pointers.

Tuesday, June 9, 2009

Custom Calculated List Column













No I'm not talking about creating a regular calculated column here. Recently I was asked whether we can have a custom column in our list which displays a icon image and hyperlinks to a web part page with querystring.
Calculated column seemed to be the best choice. Below are the steps I followed:
  • Create a calculated column in the list.
  • In the formula section add
    ="http://servername/site/doclib/mywebpartpage.aspx?item=/site/doclib/"&[ColumnName]&".docx"

** Url and querystring should be modified according to your needs**

  • Select Single line of text for section "The data type returned from this formula is"
  • Open FldTypes.xml located in \Template\XML\ .
  • Navigate to the node <field name="TypeName">Calculated</field>
  • Navigate to <renderpattern name="DisplayPattern">node
  • Now either add a new case statement or add this code to Default node.Refer to the first image above. Add the html in the default node.
  • Save and Close the file.
  • RESET IIS
  • Refer to the second image above of how the output displays. "View in SharePoint" column has a icon which contains the hyperlink

Friday, April 10, 2009

Workflow Errors - Contd

1)
"The security validation for this page is invalid. Click Back in your Web browser, refresh the page, and try your operation again"

Set

SPWebObject.AllowUnsafeUpdates = true;

This should work as a breeze


2)
"New instances of this workflow template are currently disallowed"

This is probably the easiest one:

Go to Doc library settings --> workflow settings--> Remove workflows --> select "Allow New Instances"

Workflow Errors

Although you can get lot of wierd errors but I am here describing the ones I got and spent almosta day figuring out:

"Operation is not valid due to the current state of the object"
and
"Exception from HRESULT: 0x8102009B"

The funny part is that these are really not errors which halt your progress. These
errors can occur when you try to start a workflow that is

--------------------------------------------------------------
a) already running

or

b) errored

and therefore cannot be started again.
The stack trace will look something like:
Microsoft.SharePoint.SPException: Exception from HRESULT: 0x8102009B ---> System.Runtime.InteropServices.COMException (0x8102009B): Exception from HRESULT: 0x8102009B
at Microsoft.SharePoint.Library.SPRequestInternalClass.AddWorkflowToListItem(String bstrUrl, String bstrListName, Int32 .....


-----------------------------------------------------------------

So I would suggest you to check the item or wait for few mins before workflow shows up in the "View Workflow history" pane. For some reason when you kick start the workflow through the code it takes few mins to actually start.

Fixes for SharePoint Timer Service

If you are looking for options to speed up the response time of the SharePoint Timer Service so that you can get your emails out faster or for anything else, try the following (at your own risk)

The following steps can improve the accuracy of the delay action:

* Ensure Windows 2003 SP 2 is installed
* Install hotfix available here http://support.microsoft.com/default.aspx?scid=kb;en-us;932394
* Run the following stsadm command, replacing server with your servername.

PLEASE NOTE: the full impact of increasing the frequency of the workflow timer job is not known.

stsadm -o setproperty -propertyname "job-workflow" -propertyvalue "every 1 minutes between 0 and 59" -url http://server

Also, some additions have been made and incorporated in the Windows SharePoint Services 3.0 post-Service Pack 1 hotfix package that could help the Timer Service work a bit better.

Tuesday, March 17, 2009

MOSS : Enable Incoming Emails

The procedure for incoming emails is very similar to the outgoing emails i.e. changing settings in the central administration. But to enable incoming emails to be delivered to document libraries I had to take the following steps described on msdn:
Especially if you see your incoming mails sitting in the Queue folder

--------------------------------------------------------------------------
Practical experience in setting this up in a Windows Enterprise Server 2008/IIS 7.0/Exchange Server 2007 farm environment showed that there is one more step required to get Incoming e-mails delivered to the actual Drop folder on the SharePoint SMTP server so that SharePoint can then pick them up from there. This applies if you choose Automatic mode under Configure incoming e-mail settings>Step 4. and can even apply if you choose Advanced mode as well (if you are still using the SMTP server in IIS).

The step is that you need to tell the SMTP Service that it is the destination for the domain specified in the e-mail address that you configure in Central Administration. E.g. if you set the e-mail address domain for recieving SharePoint e-mail destined for Lists and Libraries to say sharepoint.somecompany.com (which would result in an e-mail address that could look like
somelist@sharepoint.somecompany.com for a list), then you will need to set the SMTP Service up to recognise that it is the endpoint for mail destined for this domain so that it moves the received mail into the Drop folder for SharePoint to pick up. Otherwise mail will sit in the Queue folder on the SMTP Service machine forever, as it won't know where to send it next. When SharePoint is in Automatic mode, it gets the folder to pick mail up from, from the SMTP Service, which by default tells it to look in C:\inetpub\mailroot\Drop.

To do this, on the Web Front End Server running the SMTP Service under IIS

* Go to Administrative Tools>Internet Information Services (IIS) 6.0 Manager (NOT the IIS 7.0 Manager which is listed as Internet Information services (IIS) Manager).
* Once the IIS 6.0 manager dialogue has opened, expand your server, and
then expand the SMTP Virtual Server node.
* You should see a node called Domains. right click on it and select New Domain...
* In the New SMTP Domain Wizard select Alias as the domain type and click the Next button.
* Enter the domain name exactly as entered in Step 4. of Configure DNS Manager (and as in Step 5 b. of Configure incoming e-mail settings)
* Click Finish.
If you have e-mails sitting in the Queue folder from previous tests, restart the SMTP Service and it will process them and park them in the Drop folder, ready for SharePoint's timer service to pick them up on it's next run.Assuming that you have got everything else set up properly, you should see messages landing in the Drop folder, and then being picked up by SharePoint for loading into the appropriate List or Library

Tuesday, March 10, 2009

MOSS : Outgoing Emails

To enable outgoing emails from MOSS in the workflows:
All the articles or msdn will tell you to setup your smtp server name in the central administration site and setup in the workflow section
BUT we also need to make sure port 25 is open and NOT blocked by any antivirus software for eg McAfee.
Once you follow the steps described above the emails will start flowing out from your server.

Friday, February 20, 2009

Ajax SPGridview

So here I am after building and deploying the custom web services in WSS 3.0 looking to build ajax web parts to display data from the external system.

So I create a new SPGridview web part and ready to deploy to the web application, but what I get is an error Woo!!

Unable to add selected web part(s):

Site News: The web part you attempted to add no longer exists in the Closed Web Parts Gallery . Refresh your browser to update the web part page and the Gallery.






DO NOT trust error messages coming from SharePoint ! Not a surprise as you must have seen multiple times messages like "Error" while working on sharepoint.
The resolution was to install ASP.NET Ajax on the machine... wooo! How is it that sharepoint could'nt explain it clearly?

Anyways I installed asp.net ajax and went ahead and readded the web parts to the zone, and I see another error

Request for the permission of type Microsoft.SharePoint.Security.SharePointPermission


Now this is telling you to change the access level in the web.config file of the web application. So open the config file from root\wss\virtualdirectories\application port\
and change the following line:
<trust level="WSS_Minimal" originUrl="" />
to
<trust level="WSS_Medium" originUrl="" />

and bang your'e done !!

Hurray I was able to load the web parts and display as expected. Kudos to the SharePoint team for great explanatory error messages

Wednesday, February 18, 2009

MOSS Custom Web Services

Alright, MOSS Web services is the least talked about topic.

So here I am blogging about getting custom web services work in the sharepoint environment. That means writing your own web services and deploying the the MOSS environment so its accessible like other WSS and MOSS services e.g. lists, Usergroup etc

1. The first step is to create an ASP.NET web service project in Visual Studio 2005. If you don't find a web service project template in visual studio, that means that you are still running an old version of Visual Studio 2005, the one without the service pack. You will have to download and install the Visual Studio 2005 Service Pack 1 Beta from Microsoft here.

2. In the Project Types box, select Visual C#.

3. In the Templates box, select ASP.NET Web Service Application.

4. In the Name box, type UploadService. In the Location box, type the following path: Local File System Folder:\WebService.

5. Click OK.

6. In the Solution Explorer, right-click Service1.asmx and rename the file CustomWS.asmx and then right click CustomWS.asmx and click View Code.

7. Add a reference to the assembly for Microsoft Office SharePoint Server 2007 (Microsoft.SharePoint.dll). This assembly is located in the following directory: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\ISAPI. Please note that if you are developing on a machine that does not have SharePoint installed then you can copy the required files from the SharePoint machine to your development machine.

8. Make sure following using directives are included at the top:

using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Net;


9. Change your class name from Service1 to CustomWS.

public class CustomWS: System.Web.Services.WebService


10. Comment out the web method definition. The commented out web method code will look like as follows:

//[WebMethod]
//public string HelloWorld()
//{
//return "Hello World";
//}


11. Add following code (web method) in the class:
/// Code here

12. Open CustomWS.asmx markup page. In Solution Explorer, right-click CustomWS.asmx and select View Markup. You will notice that the markup page has following line:

<%@ WebService Language="C#" CodeBehind="CustomWS.asmx.cs" Class="CustomService.CustomWS" %>


Change it to the following line:

<%@ WebService Language="C#" Class="CustomService.CustomWS" %>


13. Create a strong name for the class library. In Solution Explorer, right-click the web service project, and in the Properties dialog box, click Signing, select Sign the assembly, and select in the box for choosing a strong name key file.

14. In the Create Strong Name Key dialog box, provide a file name for the key, deselect Protect my key file with a password, and click OK.
15. Compile the web service project.

16. Now once you have signed and installed assembly in the GAC , open asmx file and change the markup to the following line:

<%@ WebService Language="C#" Class="Namespace.ClassName, AssemblyName, Version=1.0.0.0, Culture=neutral, PublicKeyToken=8cee0c73157976c7" %>

This is the line I forgot to modify(including the publickeytoken and version number) and it bothered me for days.... duh!

17. As we are developing this web service on a machine that does not host SharePoint, therefore, we need to create a virtual directory in IIS. Click Start, point to Administrative Tools (You may have to go to the Control Panel first to select Administrative Tools), and then click Internet Information Services (IIS) Manager.
a. Expand the branch for the server computer to which you want to add a virtual directory. Under the server computer branch, expand the Web Sites folder, and right-click the Default Web Site and select New and then Virtual Directory.... If you don't want to use Default Web Site, you can create a new web site.

b. Click Next and enter an alias in the text box, for example, for this service you can enter UploadService.

c. Click Next and then click Browse... button to browse to the project folder (containing the .asmx file) and click Next.

d. Click Next again and then click Finish.


Note: In case you are developing the service on a SharePoint server,use following instructions:

18. Copy the Files.asmx to the following folder: C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS

19. Run disco.exe at the command prompt from the LAYOUTS directory to generate .disco and .wsdl files.

Run a command in the following format to generate the files in LAYOUTS:

disco http://Site:port/_layouts/Files.asmx

Make sure you have entered the correct path in the command above otherwise you will get an error. If you created a virtual directory on a port other than the port 80, then you must mention the port number in the path (For example, http://localhost:8080/uploadservice/Files.asmx). This will generate the .disco and .wsdl files.

20. To register namespaces of the Windows SharePoint Services object model, open both the .disco and .wsdl files and replace the opening XML processing instruction -- -- with instructions such as the following:

<%@ Page Language="C#" Inherits="System.Web.UI.Page" %>
<%@ Assembly Name="Microsoft.SharePoint, Version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c" %>
<%@ Import Namespace="Microsoft.SharePoint.Utilities" %>
<%@ Import Namespace="Microsoft.SharePoint" %>
<% Response.ContentType = "text/xml"; %>

21. In the .disco file, modify the contract reference and SOAP address tags to be like the following example, which replaces literal paths with code generated paths through use of the Microsoft.SharePoint.Utilities.SPHttpUtility class, and which replaces the method name that is specified in the binding attribute:

<contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request) + "?wsdl"),Response.Output); %> docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %>xmlns="http://schemas.xmlsoap.org/disco/scl/" /><soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns:q1="http://tempuri.org/" binding="q1:HelloWorld" xmlns="http://schemas.xmlsoap.org/disco/soap/" /><soap address=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> xmlns:q2="http://tempuri.org/" binding="q2:ServiceSoap12" xmlns="http://schemas.xmlsoap.org/disco/soap/" />

23. In the .wsdl file, make the following similar substitution for the SOAP address that is specified:

<soap:address location=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(SPWeb.OriginalBaseUrl(Request)),Response.Output); %> />

24. Rename both files in the respective formats CustomWSdisco.aspx and CustomWSwsdl.aspx so that your service is discoverable through Windows SharePoint Services.

Now let's copy the files to _vit_bin directory
25. The _vti_bin virtual directory maps physically to the Local_Drive:\Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI directory, which contains the default Web service files used in Windows SharePoint Services. Copy the new CustomWSwsdl.aspx and CustomWSdisco.aspx files, and also the CustomWS.asmx file, to the ISAPI folder.
From the _vti_bin directory, a Web service offers its functionality to the site that is specified when adding a Web reference for the service.
To verify that your custom Web service is discoverable, navigate to http://Server/_vti_bin/CustomWS.asmx

Now we need to list our web service files in the spdisco.aspx file for it to be available to applications:
26. To make your Web service discoverable in Visual Studio as a Web service alongside the default Windows SharePoint Services Web services, open the spdisco.aspx file located in \Program Files\Common Files\Microsoft Shared\Web Server Extensions\12\ISAPI and add the following code, specifying the .asmx file for your Web service.

<contractRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + "/_vti_bin/MyCustomWebService.asmx?wsdl"), Response.Output); %>>
docRef=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + "/_vti_bin/MyCustomWebService.asmx"), Response.Output); %>
xmlns=" http://schemas.xmlsoap.org/disco/scl/ " />
<discoveryRef ref=<% SPHttpUtility.AddQuote(SPHttpUtility.HtmlEncode(spWeb.Url + "/_vti_bin/MyCustomWebService.asmx?disco"),Response.Output); %>
xmlns="http://schemas.xmlsoap.org/disco/" />


WOO HOO and you'r done ! Just create a sample application to consume this web service just like you do to comsume other sharepoint web services

Happy web servicing !

Sunday, January 25, 2009

Custom Feature - Content Type

Everyone has built a simple feature either for event handling purposes or site action menu but how about creating and deploying custom feature on ECB menu and based on content types.
Here is a simple feature manifest:

<?xml version="1.0" encoding="utf-8" ?>
<Feature xmlns="http://schemas.microsoft.com/sharepoint/"
Id="5DFD12AF-D0AA-4c63-8FB8-C49DB1191083"
Title="My Site Content Type Feature"
Description="Adds my Content Types."
Scope="Site"
Version="1.0.0.0">
<ElementManifests>
<ElementManifest Location="ContentTypes.xml"/>
</ElementManifests>
</Feature>

Here is a elements manifest which adds ECB menu for a infopath form content type:

<?xml version="1.0" encoding="utf-8"?>
<Elements xmlns="http://schemas.microsoft.com/sharepoint/">
<CustomAction
Id="NIBR.NimbusStatusReport"
Location="EditControlBlock"
Title="(Nimbus) Display in SharePoint...."
Sequence="10"
RegistrationType="ContentType"
RegistrationId="0x010100AF717F1A25C33E438J00D81D31F0A176">
<UrlAction Url="{SiteUrl}/Pages/StatusReportViewer.aspx?item={ItemUrl}"/>
</CustomAction>
</Elements>


The stuff worth noticing here is the RegistrationType and RegistrationId attributes
RegisterationType should be set to ContentType and RegisterationId should be set to the document content type or the parent contenttype if you want to enable the ECB menu for all items deriving from the parent Content Type.
To create a new ID for a content type you can follow one of two possible conventions:

[parent content type ID] + two hexadecimal values (different from "00")
[parent content type ID] + "00" + hexadecimal GUID
Usually the first convention is used by SharePoint for the default content types included in SharePoint.

Example:

0x (System)
0x01 (Item Content Type)
0x0101 (Document Content Type, child of Item Content Type)
0x0120 (Folder Content Type, child of Item Content Type)

Once we are done with building the feature it's time installing and activating. Follow the following stsadm commands to get it in place.

installfeature:
stsadm.exe -o installfeature
{-filename |
-name }
[-force]

activatefeature:
stsadm.exe -o activatefeature
{-filename |
-name |
-id }
[-url ]
[-force]

uninstallfeature:
stsadm.exe -o uninstallfeature
{-filename |
-name |
-id }
[-force]


It's all done !! Enjoy your first feature