Wednesday, August 29, 2007

Web Services on SharePoint - making F5 Work

I was getting many questions on best practices to write custom web services for sharepoint, and I wanted to write an article about it for some time now. Also, I just had a chance to fiddle around with making F5 (run from visual studio into debug mode) work for a web service I am testing on a sharepoint site. This involved a few tricks, so I am documenting them:

Note - only do this on your development box!

Note - code lines marked in red means that you will need to change the values to your environment values.


I hold that the best practice is not to use the web service as a web application template (that is the default with visual studio) because when deploying to sharepoint, you'r web service usualy needs to sit in the layouts folder, and you do not want to deploy your code files there. You also don't want to use the visual studio publishing mechanism that uses the frontpage server extensions.
The alternative is creating a web service that is deployed as an asmx file to the layouts folder, pointing to a DLL that is deployed to the GAC. That makes it safe and secure, and easier to deploy and track versions.



Step 1 - Create a Web Service (DLL) Project

To create the web service, use Visual Studio 2005, and click "File-New-Project" and select ASP.NET Web Service Application.



If you don't have that project type installed, you may need to change the installed features of Visual Studio on your machine. The good think about this project type is that it creates a web service as a DLL and an asmx and not as a web site.



After the project is created, change the file names, namespace and assembly names as needed (make sure the namespace of the webservice attribute is changed - you don't want "http://tempuri.org/" as your namespace...) and most importantly - sign the assembly as strong name (right click the project, properties, signing tab, sign the assembly).




Now we have to find out the key that was given to the assembly when it was signed. To do that you must first build the web service (I use ctrl-shft-B, or right click the project and select build) and then either drag and drop the DLL to the assembly folder, right click and get the key:



Or you can run a command line from the visual studio SDK (start-programs-visual studio 2005-visual studio tools-Visual Studio 2005 Command Prompt) and type

sn -T "c:\temp\WebService1\WebService1\bin\WebService1.dll"



Once we have the public key token, we can change the web service's asmx file to use the DLL that will be deployed to the gac. Right click the service1.asmx file and choose "View Markup". You need to change the markup to point to the DLL that will be in the GAC, so this is the format you need to use:



<%@ WebService Language="C#" Class="WebService1.Service1, WebService1, Version=1.0.0.0, Culture=Neutral, PublicKeyToken=db33ac6baa259170" %>

Expalantion:

  1. The "WebService1.Service1" part is the "namespace dot classname" of your code. To get that, you will need to open your .cs file, and copy the namespace you are using, add a dot after it, and add the class name.

  2. The "WebService1" (after the comma) is the name of the DLL that you may have set in the project properties under the "application" tab (the "assembly name")

  3. The public key token is the key we got earlier.





Note - I am not sure if this is needed, but I also registered my web service as a safe control in the web.config, before I used any sharepoint code. It's worth checking if this is required or not, and I will update if I have time to test.



Step 2 - Setting up the Build Events

While in the project's properties, switch to the "Build Events" tab. Paste the following in the "post-build event command line" box:


"c:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\gacutil.exe" /i "$(TargetPath)" /f

copy "$(ProjectDir)\*.asmx" "C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS"

"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\bin\RecycleAppPools.vbs"

"c:\Program Files\Microsoft Visual Studio 8\SDK\v2.0\Bin\disco" http://localhost/_layouts/service1.asmx /o:"C:\Program Files\Common Files\Microsoft Shared\web server extensions\12\TEMPLATE\LAYOUTS"




Explanation:


  1. The first line puts the DLL in the GAC.


  2. The second line copies the web service asmx file to the layouts folder. You should make sure your projects do not create same names for asmx files, or they will overwrite eachother!


  3. The third line recycles the application pools. I am doing this with a vbs file that I have written, and placed in the 12 hive's "\bin" folder for my comfort. Here are the contents of the file:


    Set locator = CreateObject("WbemScripting.SWbemLocator")

    Set Service = locator.connectserver(strServer, "root/MicrosoftIISv2")

    Set APCollection = Service.InstancesOf("IISApplicationPool")

    For Each APInstance In APCollection

    APInstance.Recycle

    Next

    echo "Recycle Complete."


  4. The last line build a discovery file for the web service in the layouts folder. if you installed your visual studio 2005 in a different location, you will need to change the folder path to the disco.exe file, and if you changed the name of the asmx (or if you have more than one) you will need to modify that as well. You will also want to change the url to point to a sharepoint site on your machine if you are not using the "localhost" header. In my case, I use the header "portal", so I change is to "http://portal".



Step 3- Change the F5 behavior

To change what happens when you press F5, switch to the "Web" tab, and change the start url to the url to the web service (I use http://portal/_layouts/service1.asmx), then change the "use IIS web server" and change the project url to the rool sharepoint url (I use "http://portal") and tick the "override application root URL and type the same url as the project url:





Last Step - set up your web.config to allow debugging

If you want F5 to work, and have visual studio debug the web service when you press it, the sharepoint web.config should be changed to allow debugging. To do that, you will need to open the web.config file for the virtual server you are using (in my case "http://portal" - which means the web.config is under "c:\Inetpub\wwwroot\wss\VirtualDirectories\portal80\web.config") and find the "<compilation>" tag, and set the attribute "debug" to true:




This is it!

If you didn't miss anything, you should be able now to press F5 and the web service will launch in the sharepoint context, with debugging in the visual studio! You can set breakpoints and debug the web service.







Tuesday, August 28, 2007

Passed another exam

Hi all,
I had passed yet another MSCTS 70-631 Windows SharePoint Services 3.0, Configuring. This completes the set, and now I have all four sharepoint exams under my belt.
I have to say that this one was the most difficult one for me, since it had many questions about topics I try not to touch - for example load balancing. I really don't understand why a sharepoint expert needs to know load balancing and what is the difference between multicast and unicast, and how you should configure the network adapters. On the other hand, some of the questions were easy for me because they had more to do with development (for example, if a custom web part gets installed and crashes with an unhandled error - what should the administrator do? The answer was easy for me, because I am a developer - but is it fair for an admin to get asked that?)
So all in all I am happy about this, and I plan to promptly forget everything I know about WSS and MOSS configuration and installation. Heck, people keep asking me questions about this - "Ishai, how do I configure forms authentication?" or "Ishai, I configured anonymous and it doesn't work" - and I am sick of it. My answer from now on will be "I don't know, but I will write you a web part to make it all better!".

Speaking of webparts, I didn't get any complaints about my enhanced content query webpart, so I am moving on and will start thinking of my next open source project. It is still in infancy, but I hope to let you know about it soon.

On an unrelated matter, I will be speaking at the Israeli SharePoint user group next month (19/9) about features and templates (hebrew web site) so if you are in Israel, come over and say hello.

While I am there, there is a Canberra user group without me, and I am still looking for presenters. I will keep you updated if you want to know who will talk. Last month we had Anthony Woodward from my company talk about sharepoint record managment compliance in general and with Australian-specific notes. It was quite interesting. If you want to present, give me a buzz (my contact form is on this blog - look for it!)

Sunday, August 26, 2007

What's good and what's missing from WSS Visual Studio Extensions 1.1?


The Windows SharePoint Services 3.0 Tools: Visual Studio 2005 Extensions, Version 1.1 CTP were released, with
"Support for 'Web Solution Package' editing, List Instance item template ,List Event Handler item template,Bug fixes", so I decided to take a quick look at what's in the web part project template.


First, I liked the fact that now by default when you create a web part project you don't get the "Render" event that you used to get in the past. This caused many developers to start writing html in the Render event, and then be puzzled when the events on controls didn't work (see Server side controls and data binding in web parts in this blog).



I am still looking into it, but one thing that I would expect from a webpart project template is a wizard when creating the project that asks:


  1. Do you want the web part to support connections? (add stubs for connection interface)

  2. Do you want the web part to connect to a specific list? (add properties and functions to connect to a list)

  3. Do you want a custom toolpane?



What do you think? what else would you want from a template?






Wednesday, August 22, 2007

New SDK, with a tool for BDC

Hey!

A new MOSS SDK is available, and it comes with a free tool to create BDC definitions (is this the end of MetaMan? I wonder...).
The new tool is called "Business Data Catalog Definition Editor"

MSDN already have articles on how to use the tool with web services and other systems.


Installing requires you to install SQL server 2005, so don't install on your production server (duh!), and be prepared for some drastic changes to your system when you install on your dev box.



The good news is that it can be installed on windows XP, proving that Microsoft are listening to us developers, and to our gripes about developing on a server...

I tried installing by running the MSI directly, but that didn't work (didn't install the SQL express, and the installation failed when it couldn't find SQL express).







Monday, August 20, 2007

Slides from Tech.Ed Australia 2007 - Templates and Features

Here are the slides I did in my presentation with Milan Gross (his slides are not included here, as they are his to publish):


I start we had the Tech.Ed image:




Next, our names and titles:





Some links and referances:








The agenda of the session (Milan covered that):





Here I spoke about the difference between templates (save as template for a list or a site) and definitions (file system xml and aspx files that allow developers and administrators have more control over the sites after deployment)




A quick explanation of how a solution package is built. For example I showed the package of the "print list" feature as it was done by Scott Hillier.



Next I discussed what are DDF files and why we need them (we need them to let makecab.exe know how to build our cab file - using folders), as well as giving some alternatives such as cabarc that allows you to build a cab file with folders in it - no need for a definition file. I also mentioned a tool I never used - WSPBuilder




Now to my part of the demo - I showed how to create a feature for a webpart and how to package it. I used my own Enhanced Content Query WebPart solution package to demonstrate this, and you can download that from codeplex!









After that Milan took over and showed a scenario that used the Solution Generator (part of the WSS extensions for Visual Studio) to create a site definition, with lists that are connected to workflows and have BDC fields and all. It was pretty complex, and I felt we needed more time to really explain it all.


And that was my first presentation. I will let you know about the second one soon.






How to remove farm administrators permissions from a site?

A friend asked me how can we remove farm administrators from having permissions on a specific site. Removing the permissions from the site collection and the site itself just did not work - the users who were farm admins could still browse the site and do whatever they want to it.
The answer was that in central admin, under "applications" there is a link: "Policy for web application" which allows you to set permissions at the web application level. It turns out that the farm admins have full permissions there for the application, and until you remove them from there, they will be able to go into any site in the web application.

Hotfix lets you store WSS data outside of SQL

If you missed this, give the following KB article a read. It is short, and to the point - a new hotfix is out that lets you store WSS data on external storage- out of SQL.
KB938499

Saturday, August 11, 2007

My mark @ Tech.Ed

Ok, I am back, and boy, do I have some stories...

On the first day I had a presentation about templates and features with US consultant and trainer Milan Gross. I was not very satisfied with our presentation, and I think we should have kept the scenario simpler.
I showed how I built the wsp solution and features for the Enhanced Content Query Web Part and for the Print List feature.



My next presentation was with Gayan Peiris, who left my company to join Microsoft just a month ago. We did a presentation on upgrade and migration from sharepoint 2003 to 2007.
Now, before people start asking me how to upgrade I have to say that that was Gayan's part of the presentation. My part was warning about the customization upgrade (custom webparts, event handlers etc.), and about what is different in the new version that requires re-thinking on the information architecture.
That Session went very well, if a bit tight on time, and we got good reviews (7.62) even if we didn't get to the top ten.



After our presentation we left with all of tech.ed to Movie World, where I went, for the first time in my life, on a roller coaster - Lethal Weapon. I have been told by people with more experience that this is the most frightening ride ever, everywhere. I can now believe it.
The only reason I was brave enough to go on the ride was that it was night - I couldn't see the ride. I was sure that a "lethal weapon" ride would be a video game with shooting in it.

Here is a picture of me on the ride:




Here is a movie of what the ride looks like:









Friday, August 10, 2007

MCTS in MOSS configuration

Well, Tech.ED Australia 2007 is over (I will post some details soon) and I am happy to let you know that I took the "Configuring Microsoft Office SharePoint Server 2007" exam (70-630) and passed! I only got 3 questions (out of 51) wrong, so I am pretty happy with myself right now.
Now I only have to do the WSS configuration exam to have the entire set!

Sunday, August 05, 2007

Off to teched

So this is it - the moment I have been waiting for and the reason I didnt write anything in the last month. I am flying to the goldcoast tomorrow and will be presenting there this week. I will also be at the meet the experts dinner (as a self proclaimed expert) and at the influencer party (as an MVP).
See you there!
p.s. I released today a technical refresh to the content query web part project. more features, less bugs!

Wednesday, August 01, 2007

Modifying Search to Add a Send Link By Email link


My customer wanted a "send link by email" next to each search result item. "Easy", I thought and went ahead to edit the xslt for the search results. But I found out a problem with links that had spaces in them - the link in outlook would appear broken. To solve this, I had to write some simple javascript, and the process is described below.




Problem:


If you want a mailto link (href="mailto") that has in the body a link to a file, you may get a link like this:


href="mailto:body=http://server/site/library/this is my file.doc"



This is a problem, because the file name contains spaces. The email will open with a broken link in it's body:




Solution:

Luckily, SharePoint has a javascript functions that solves that for us. They are "escapeProperly" and "navigateMailToLink". What I did is create a function of my own in the page:


function SendEmailWithLink(link)
{
var link = "mailto:?body=" + escapeProperly(link);
navigateMailToLink(link);
return false;
}



And my link is:

href="#nowhere" onclick="javascript:SendEmailWithLink('');"




This article would'nt be complete if I didn't explain why I did this - this if for the search results xslt - the idea was to add a "send link by email" button next to each search result. The solution - change the xslt to include the script above, and a button like this:



<a title="E-mail a Link" href="#nowhere">
<xsl:attribute name="onclick">
javascript:SendEmailWithLink('<xsl:value-of select="$url"></xsl:value-of>');
</xsl:attribute>
<img border="0" src="/_layouts/images/ICMSG.GIF"/> 
</a>





We also added other actions (I will try to get them published) and came up with the following for each result item: