Thursday, September 25, 2008

Enable Silverlight in MOSS - web.config changes

I know there are numerous articles on this, but here are the web.config changes I made to enable Silverlight in Microsoft Office SharePoint Server 2007 (modified parent node names in bold):

configuration/configSections

<sectionGroup name="system.web.extensions" type="System.Web.Configuration.SystemWebExtensionsSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<sectionGroup name="scripting" type="System.Web.Configuration.ScriptingSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="scriptResourceHandler" type="System.Web.Configuration.ScriptingScriptResourceHandlerSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<sectionGroup name="webServices" type="System.Web.Configuration.ScriptingWebServicesSectionGroup, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35">
<section name="authenticationService" type="System.Web.Configuration.ScriptingAuthenticationServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="jsonSerialization" type="System.Web.Configuration.ScriptingJsonSerializationSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="Everywhere" />
<section name="profileService" type="System.Web.Configuration.ScriptingProfileServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
<section name="roleService" type="System.Web.Configuration.ScriptingRoleServiceSection, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" requirePermission="false" allowDefinition="MachineToApplication" />
</sectionGroup>
</sectionGroup>
</sectionGroup>

configuration/system.web/httpHandlers

<remove verb="*" path="*.asmx" />
<add verb="*" path="*.asmx" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add verb="*" path="*_AppService.axd" validate="false" type="System.Web.Script.Services.ScriptHandlerFactory, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add verb="GET,HEAD" path="ScriptResource.axd" type="System.Web.Handlers.ScriptResourceHandler, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" validate="false" />

configuration/system.web/httpModules

<add name="ScriptModule" type="System.Web.Handlers.ScriptModule, System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add name="Session" type="System.Web.SessionState.SessionStateModule" />

configuration/system.web/compilation/assemblies

<add assembly="System.Core, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add assembly="System.Data.DataSetExtensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
<add assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Web.Silverlight, Version=2.0.5.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add assembly="System.Xml.Linq, Version=3.5.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />

configuration/system.web/pages

<controls>
<add tagPrefix="asp" namespace="System.Web.UI.WebControls" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
<add tagPrefix="asp" namespace="System.Web.UI" assembly="System.Web.Extensions, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" />
</controls>

configuration

<system.web.extensions>
<scripting>
<webServices />
</scripting>
</system.web.extensions>

Thursday, September 11, 2008

Customing Microsoft Dynamics CRM 4.0 menus and toolbars

I've been embarking on a new adventure of staging Microsoft Dynamics CRM 4.0 for my company to replace a home-grown, ad-hoc CRM system. As part of this, I have needed to customize some of its menus and toolbars.

The basic mechanism for doing this is to:

1. Enable ISV Config. You do this by navigating to Settings | Administration | System Settings | Customization tab, then choosing one of the client options under "Custom menus and toolbars:"
2. Once done, export the ISV Config and change it. To get a copy of it, go to Settings | Customization | Export Customizations, select the ISV Config item, and click the Export Selected Customizations button.

You should either keep a copy of this file for reference before changing it, as it contains many sample objects, or at least refer to this MSDN article which references possibly the same sample.

You may wonder how to get rid of all the default customizations present in the initial sample--it's chock full of menus, toolbars, etc. Here is the minimal ISV Config XML structure without any of the sample objects. Add your own objects to this minimal file, and then...

3. Re-import your modified ISV.config.xml file (Settings | Customization | Import Customizations). MS CRM validates the XML upon upload, not upon import, so you will receive a notice of any validation errors immediately upon clicking the Upload button. Don't forget to click the Import Selected Customizations button after you have a successful upload. :)

Monday, September 08, 2008

Silverlight web part - Code Access Security and Startup Permissions

I built a web part based upon the Silverlight 2 beta 2 guidance and encountered an interesting situation. If a user that did not have administrative privileges on the web server was the first to browse the portal hosting the web part, the user would simply receive a 403 (Forbidden) error page.

I had been working with a web part installer based upon the SharePoint Solution Installer (an excellent project to simplify installation of web part packages), and my WSP specified a custom code access security policy. Additionally, my web part referenced Enterprise Library 4.0 assemblies that I had built and signed. So my troubleshooting initially focused around the following:
  • Changing the custom code access security policy to grant unrestricted access to the web part (no effect);
  • Changing the trust level for the entire WSS site to Full (no effect);
  • Registering the Ent Lib assemblies via InstallUtil (no effect);
  • Adding the Ent Lib assemblies to the GAC (they were running in bin before--no effect);
  • Removing all reference to Ent Lib from my web part assembly (no effect).
Finally, I added System.Web.Silverlight.dll to the GAC, and voila--the site started working. I backed out all other changes and it continued working.

In case it helps, I believe this is the minimal CAS policy for a web part that hosts an application via Silverlight:

<CodeAccessSecurity>
<PolicyItem>
<PermissionSet Name="Web Part Permission Set" class="NamedPermissionSet" version="1" Description="Permission set for Silverlight-hosting web part">
<IPermission class="AspNetHostingPermission" version="1" Level="Medium" />
<IPermission class="SecurityPermission" version="1" Flags="Execution" />
<IPermission class="Microsoft.SharePoint.Security.SharePointPermission, Microsoft.SharePoint.Security, version=12.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c"
version="1" ObjectModel="True" />
</PermissionSet>
<Assemblies>
<Assembly Name="My.WebPart" Version="1.0.0.0" PublicKeyBlob="---insert long encoded public key blob extracted with sn -Tp here ---" />
</Assemblies>
</PolicyItem>
</CodeAccessSecurity>

Thursday, September 04, 2008

Windows Desktop Search 4.0 + TrueCrypt = crash?

I used TrueCrypt to encrypt the entire system disk for a Vista x64 installation. Everything was running fine on this, until suddenly I started having frequent (every 40-50 minutes) crashes. I had just installed Visual Studio 2008, so I thought perhaps the SQL Express instance it installed was causing some incompatibility... but after disabling those services, and in fact removing every piece of VS 2008, I was still suffering the crashes.

Finally I waded through the recent updates and noticed that Windows Desktop Search 4.0 had been recently applied. I can't prove this, but I think I may have rebooted (and hence the service got started) during my application updates. Regardless, I stopped and disabled the service and have had no crashes since.

I did set Vista to record crash dumps, but it always fails to load the crash dump driver, and so I was not able to capture any data about the crashes I experienced. Has anyone else experienced problems with this combination of applications? The system drive has a single partition and is NTFS-formatted within the TrueCrypt container, for what it's worth.

Wednesday, September 03, 2008

WCF web service setup with integrated security

I found setting up a WCF web service to use Windows integrated security to be a somewhat less-than-transparent process, so I thought I'd publish the steps I used to make it work.

Set IIS to allow Negotiate authentication in addition to NTLM

To do this, you need to find the web site identifier. In IIS 6.0, run IIS Manager and choose the Web Sites node and note the identifier of the web site that will host your web service:

Once done, drop to a command prompt and execute the following:
cscript C:\inetpub\AdminScripts adsutil.vbs GET w3svc/<identifier from above>/root/NTAuthenticationProviders
For example:
cscript C:\inetpub\AdminScripts adsutil.vbs GET w3svc/174926873/root/NTAuthenticationProviders

This will report output like the following:
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.

NTAuthenticationProviders : (STRING) "Negotiate,NTLM"
If the NTAuthenticationProviders node reads "Negotiate,NTLM" you need make no changes. If it reads simply "NTLM" you must set it as follows:
cscript C:\inetpub\AdminScripts adsutil.vbs SET w3svc/<identifier from above>/root/NTAuthenticationProviders "Negotiate,NTLM"
Use at most one host header

There are workarounds, but out of the box you will get errors if you have more than one host header configured on the IIS web.

Set Windows integrated security, except for the .svc file


In IIS Manager's Directory Security tab for the web site (accessed via right-click | Properties), click Edit in the Authentication and access control section. At the web site level, Enable anonymous access should be unchecked and Integrated Windows authentication should be checked.

Now click on your web site to view its files. You should see the .svc file listed. Right-click this file and go to Properties:
This time, go to the File Security tab and click the Edit button in the Authentication and access control section. This file should have both anonymous access and integrated Windows authentication checked:
Use an integrated security binding

Lastly, you need to use an integrated security web service binding in web.config. Here is an example:
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="IntegratedBinding" maxBufferSize="2147483647" maxReceivedMessageSize="2147483647">
<readerQuotas maxArrayLength="2147483647" maxStringContentLength="2147483647" />
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Windows" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<behaviors>
<serviceBehaviors>
<behavior name="serviceBehavior">
<serviceMetadata httpGetEnabled="true" httpGetUrl="" />
<serviceDebug includeExceptionDetailInFaults="true" />
<!--<serviceAuthorization impersonateCallerForAllOperations="true" />-->
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service name="My.Service.OrderService" behaviorConfiguration="serviceBehavior">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="IntegratedBinding" name="integratedBasicHttpEndpoint" contract="My.Service.IOrderService" />
<endpoint address="mex" binding="mexHttpBinding" name="mexEndpoint" contract="IMetadataExchange" />
</service>
</services>
<serviceHostingEnvironment aspNetCompatibilityEnabled="false" />
</system.serviceModel>