Day of the Developer

Living the life of a developer. What is development work really like?

<August 2008>
SuMoTuWeThFrSa
272829303112
3456789
10111213141516
17181920212223
24252627282930
31123456

Post Categories

Article Categories

News

I'm a dad :) Welcome to a new life.

Navigation

Software Business Tips

My Sites

Subscriptions



Importing User Controls into WSS 3.0

This is insane.

I have a user control test.ascx. It is a valid user control, containing nothing but a string of text to display. In an ASPX page derived from the Sharepoint base page type, it displays perfectly happily as a web part.

I put a copy in the sharepoint root, and try to upload the following web part file for it (and yes, I've done all the SafeControl, etc settings for it.

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type src="~/Test.ascx" />
<importErrorMessage>
Error: Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">
TEST</property>
<property name="Description" type="string">
TEST</property>
</properties>
</data>
</webPart>
</webParts>

And when I try to preview the webpart I get: The element is required. Add this element to the Web Part file (.webpart), and then try to import the Web Part. at Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart(Boolean

When I put it in a virtual directory and change the webpart file to this:

<?xml version="1.0" encoding="utf-8" ?>
<webParts>
<webPart xmlns="http://schemas.microsoft.com/WebPart/v3">
<metaData>
<type src="~/_customcontrols/Test.ascx" />
<importErrorMessage>
Error: Cannot import this Web Part.</importErrorMessage>
</metaData>
<data>
<properties>
<property name="Title" type="string">
TEST</property>
<property name="Description" type="string">
TEST</property>
</properties>
</data>
</webPart>
</webParts>

I now get: Exception of type 'Microsoft.SharePoint.WebPartPages.WebPartPageUserException' was thrown. at Microsoft.SharePoint.WebPartPages.WebPartImporter.CreateWebPart

Now, both files validate, and point to a real location, etc, etc, but the second file matches what I really want to do, and the error message is completely meaningless. There are about 14 places in CreateWebPart that exception might be thrown, but they should all have a message to display.

I run SharePoint in full trust to remove any security issues, still the same problem. I log / write info from a static constructor, never happens. This tells me it is something to do with the webpart file. But how do I find out?

posted Wednesday, April 30, 2008 10:47 AM by admin with 0 Comments

Fun with Access 2003 Runtime and Digital Signing

So, I have this customer upgrading from Access 97 runtime to Access 2003 runtime for an application I support. After a few days of dev and testing, we sign it with a self signed certificate, generate the MDE file, and get ready to put it on a production machine.

I install the Access 2003 runtime, and set up the shortcuts, etc. for the new version. Fire it up, and everything is working fine.

BUT. Had to be a but, or I wouldn't be making this post, right?

We open the MDE a second time, it magically inflates from 35MB to 78MB, and Access tells me the MDE is no longer signed because it has been opened in an earlier version of Access.

Point to note: It hasn't. Access 97 runtime is installed, but has not been used to open the file. In fact, it has not been used to open ANY file since installing the Access 2003 runtime.

So, I take the files back to the office, and build a clean machine with only the Access 2003 runtime to check. And everything is happy. No issues at all.

Now all I have to do is work out if it means uninstalling Access 97, and/or reinstalling the Access 2003 runtime, or getting the PCs rebuilt. Which would be a no-go.

posted Thursday, April 24, 2008 2:54 PM by admin with 0 Comments

Fun with Exchange 2007 Push Notifications

Now, you would think this should be pretty straight forward by now. But it's not.

Scenario: I am subscribed to a users calendar as follows:

BaseFolderIdType[] folders = new BaseFolderIdType[1];
DistinguishedFolderIdType folderId = new DistinguishedFolderIdType();
folderId.Id = DistinguishedFolderIdNameType.calendar;
folders[0] = folderId;
pushSubscription.FolderIds = folders;


// Subscribe to all events.
NotificationEventTypeType[] eventTypes = new NotificationEventTypeType[5];
eventTypes[0] = NotificationEventTypeType.CopiedEvent;
eventTypes[1] = NotificationEventTypeType.CreatedEvent;
eventTypes[2] = NotificationEventTypeType.DeletedEvent;
eventTypes[3] = NotificationEventTypeType.ModifiedEvent;
eventTypes[4] = NotificationEventTypeType.MovedEvent; pushSubscription.EventTypes = eventTypes;

In the notification function, I check as follows for each item I am notified of as per PushNotificationClient.cs in the SDK:

int i = 0;
// Cast the notification event to the proper type
foreach (BaseNotificationEventType bnet in notification.Items)
{
    // Get the event name
    string eventName = notification.ItemsElementName[i].ToString();
    BaseObjectChangedEventType it = bnet as BaseObjectChangedEventType;
    if (it == null)
    {
        continue;
    }
    if (!(it.Item is ItemIdType))
    {
        continue;
    }
// Code to display details about the event
ItemIdType item = it.Item as ItemIdType;
Debug.WriteLine(eventName.PadRight(20) + "[" + (bnet.GetType().ToString() + "]:").PadLeft(35, ' ') + item.Id + "\t\t" + item.ChangeKey);

Now, you would think that when you create an appointment, you would get a CreatedEvent, when you do a permanent delete you would get a DeletedEvent, and so on. But this is what you really get:

===== OWA =====
CREATE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgoAAAAAAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgpQAAAAAAAA==
No Messages Matched: ErrorItemNotFound
CreatedEvent[ModifiedEventType]RAAQUKzDsAAA5RAAriVlgoQAADwAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5RAAriVlgpQAAAAAAAA==
No Messages Matched: ErrorItemNotFound
SOFT DELETE
ModifiedEvent[MovedCopiedEventType]RAAQUK0ABgAA5RAAriVlwzQAAAAAAAA==
IPM.Appointment: fghfhdfghdfghdfgh
=== OUTLOOK ===
CREATE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAADwAAAA==
IPM.Appointment: TEST 5
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[ModifiedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAADwAAAA==
IPM.Appointment: TEST 5
MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE
ModifiedEvent[MovedCopiedEventType]eAAriVgADAAA5jp9kS9UdUCKFiIaz2NQeAAriVgSAQAAAAAAAA==
IPM.Appointment: TEST 5
COPIED WITHIN CALENDAR
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAADwAAAA==
IPM.Appointment: TEST 5
HARD DELETE
ModifiedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAADwAAAA==
No Messages Matched: ErrorItemNotFound

Not exactly sensible. but I think I've found the problem.

for (int i = 0;i < notification.Items.Length; i++)
{
    BaseNotificationEventType bnet = notification.Items[i];
    // Get the event name
    string eventName = notification.ItemsElementName[i].ToString();
    BaseObjectChangedEventType it = bnet as BaseObjectChangedEventType;
    if (it == null)
    {
        continue;
    }
    if (!(it.Item is ItemIdType))
    {
        continue;
    }
    // Code to display details about the event
    ItemIdType item = it.Item as ItemIdType;
    Debug.WriteLine(eventName.PadRight(20) + "[" + (bnet.GetType().ToString() + "]:").PadLeft(35, ' ') + item.Id + "\t\t" + item.ChangeKey);

If you replace the foreach with a for loop instead, so you can make sure the item and the event name line up, you get:

===== OWA =====
CREATE
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JgAAAAAAAA==
No Messages Matched: ErrorItemNotFound
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JwAADwAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2JgAAAAAAAA==
No Messages Matched: ErrorItemNotFound
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KAAAAAAAAA==
No Messages Matched: ErrorItemNotFound
ModifiedEvent[ModifiedEventType]GRlvYJ3GL/RAArjVW2JwAADwAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KAAAAAAAAA==
No Messages Matched: ErrorItemNotFound
SOFT DELETE
MovedEvent[MovedCopiedEventType]GRlvYJ3GL/RAArjVXWTQAAAAAAAA==
IPM.Appointment: TEST 6
SOFT DELETE RESTORE
CreatedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KwAAAAAAAA==
IPM.SchedulePlus.FreeBusy.BinaryData:
MovedEvent [MovedCopiedEventType]:GRlvYJ3GL/RAArjVW2LAAAAAAAAA==
IPM.Appointment: TEST 6
DeletedEvent[BaseObjectChangedEventType]GRlvYJ3GL/RAArjVW2KwAAAAAAAA==
No Messages Matched: ErrorItemNotFound
=== OUTLOOK ===
CREATE
CreatedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAADwAAAA==
IPM.Appointment: TEST 5
EXPANDED / CONTRACT / MOVE WITHIN CALENDAR
ModifiedEvent[ModifiedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAADwAAAA==
IPM.Appointment: TEST 5
MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE
MovedEvent[MovedCopiedEventType]RAAQUK0ABgAA5jp9kS9UdUCKFiIaz2NQeAAriVgUBAAADwAAAA==
IPM.Appointment: TEST 5
COPIED WITHIN CALENDAR
CreatedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAADwAAAA==
IPM.Appointment: TEST 5
HARD DELETE
DeletedEvent[BaseObjectChangedEventType]RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAADwAAAA==
No Messages Matched: ErrorItemNotFound

It looks like OWA is still quite different from Outlook, but now at least the event types and event names go together much more sensibly.

posted Wednesday, April 02, 2008 10:49 AM by admin with 1 Comments

How to Make your CRM Service Appointments pretty colors

1.  Enable ISV.Config in your web.config file

2.  Modify _Resources/isv.config.xml

3.  Modify <Install path>\SM\Gantt\style\GanttControl.css to include your new styles

4.  Recycle the CRM AppPool

For point 2.

In isv.config.xml find the <TimeBlock> section.

Add additional sections for your service appointment status codes.

Also:  You should trim out the "test" elements included in the isv.config file or you will find some extra menus and buttons showing up.

posted Friday, March 28, 2008 6:39 PM by admin with 1 Comments

The ALL-NEW CRM SDK 4.0.3 What fun
Version 4.0.3 of the Microsoft Dynamics CRM 4.0 SDK is now available for download! This version contains lots of great new information, including the 1st phase of the Report Writers Guide and a vastly improved Plug-in registration tool. Also included in this release:

A full sample showing how to create a Custom Workflow Activity

Yay! Maybe we’ll now be able to work out how to do what we’ve been trying to do for a couple of weeks—installing a new custom workflow!

*opens up the folder*

*opens the install project and eagerly reads through the code*

static void Deploy()
{
try {
//Create the custom activity string assemblyPath = @"C:\main\src\QA\SdkSamples\Walkthroughs\Workflow\Code\CreateLead\CreateLead\bin\Debug\CreateLead.dll";
string typeName = "CreateLead.AmysActivity";
Assembly assembly = Assembly.LoadFile(assemblyPath);
// ToDo: Fix this code.

*cries*

posted Wednesday, March 19, 2008 1:57 PM by admin with 0 Comments

CRM Certified Developer

Well, after a year of working with CRM 3.0, and some not too infrequent arguments with Microsoft about the vagaries of its internal workings, I finally decided to get my CRM Certification in the week or so before Christmas.

I managed it, but it wasn't easy. Firstly, I wanted to go with Pearson instead of Prometric, but I was told Pearson were out of the picture. The Prometric site died when I tried to book a second exam. Repeatedly. Plus there were only 5 days over 4 centres that exams could be sat, and the nearest was over 35 minutes away, instead of the 8 minute walk to the nearest Pearson centre.

Turned out Pearson was still available until December 31, so I cancelled my Prometric exam, sucked up the risk of not having the free resit offer (which DID NOT say it was Prometric only until after you requested a voucher number). And rebooked MB2-421 and MB2-422 with Pearson. Which was always was a breeze.

Then I sat those and passed. so I booked MB2-498 for a few days later. Fortunately in between times I rechecked my certification planner (which I hadn't done in several months) before the exam, and found the requirements had changed, and I needed to sit MB2-498 instead. So I cancelled and rebooked the correct exam. Which I also passed, so I am now CRM certified (my sister says that means CRM has made me certifiable, and she should know as she's been working on it too).

posted Tuesday, January 22, 2008 2:11 PM by admin with 0 Comments

CRM4 - Am I missing something?

I've just started working with CRM4 plugins.

And I've got a couple of questions.

1. SdkTypeProxy seems to support the "standard" entities and their standard properties. But is there a way to work with custom properties and entities without reverting to using DynamicEntity? Otherwise I may have to write myself a "converter".

2. Given that IPlugin has a single Execute method. And inside that I have to handle checking for entit type, mode, etc. Why does a user have to MANUALLY pick the options for it when installing, or why do I have to write an installer? Surely a "Register" method, or an "AllowedConfigurations" collection would have simplified this? I'm the one who knows what the plugin should handle, and if it should be async, etc. Why let someone else mess with that later?

posted Monday, January 21, 2008 1:46 PM by admin with 0 Comments

Cannot convert local time to universal time

I have this game I play. It's called "Make blog posts for error messages no-one else has ever seen".

This is the latest for MS CRM 3.0.

There is an error in XML document (1, 1523). ---> Microsoft.Crm.CrmException: Cannot convert local time to universal time;

There is ONE user in the CRM instance who cannot view their service calendar, and this is the message she gets in the CRM log

Config: Server set to NZ time. User time zone is Brazil (GMT -3) when it fails. It works if she sets her time zone to NZ (GMT+13) AND if she sets it to Buenos Aires also (GMT-3). SO I'm guessing there is a time zone /daylight savings issue.

posted Monday, November 05, 2007 1:10 PM by admin with 1 Comments

Determining the PrivUserGroup CRM is using.

This was a fun little exercise.

As it turns out,

SELECT [OrganizationId] ,[UserGroupId] ,[PrivilegeUserGroupId] FROM [dbo].[OrganizationBase]

Will get you the information you need.

We needed to find this out due to a couple of aborted installs on the same machine, since CRM creates the PrivUserGroup each time it installs unless told to use a specific existing group.

The group name includes the GUID you find in OrganisationID. The PrivilegeUserGroupId is the objectGUID in the AD.

As an interesting aside, the binary vs string formatting of GUIDs is a little weird

{01020304-0506-0708-090A-0B0C0D0E0F00} in binary format is: 04030201060508070A09000D0E0D0C0B

posted Monday, November 05, 2007 12:10 PM by admin with 0 Comments

SPAM of the day.

I'm starting to wonder if I'm getting SPAM based on the content of my website.

This one got me because I thought someone was asking me for help.

=============================================

Subject: Public Readonly Property ParentBalance() As Double.

H,E.R_E WE GO AGA,IN!

T*H*E B-I_G O N+E B,EFORE T,H.E

SEPTEMBE_R.RALLY!

=============================================

As you can see, my SPAM is now arriving in VB.NET code :)

posted Monday, August 20, 2007 2:52 PM by admin with 0 Comments

Wonders and Weirdness of Web Services

I just spent 3 hours trying to work out why one of two methods on a web service was failing with a NullReferenceException when both methods accepted the same first 3 parameters (one of which was apparently null) from the same 3 variables, and the other method was perfectly happy.

I'm not sure how it happened, maybe a global replace, or something, altough that doesn't match up really.

Anyway:

BeginMethod1(string About, string My, string Method)

Method1(string About, string My, string Method)

BeginMethod2(string About, string My, string Method)

Method2(string about, string My, string Method)

Calling Method 1 succeeds

Calling Method 2 fails

Did you spot the cause?

In the first 3 definitions, About started with a capital, in the last it started with a lower case.

The actual method parameter on the web service started with a capital.

The end result is that somewhere in the serialization or deserialization, the value is not transferred across, so that the web service, the parameter value is null.

posted Wednesday, July 25, 2007 12:09 PM by admin with 0 Comments

ASP.AJAX CollapsiblePanelExtender in IE 6

In IE 7, this control works beautifully.

In IE 6, it animates the collapse of the panel, then reverts to the full size of the panel.

As far as I can determine, the cause is these two functions in the BLOCKED SCRIPT

get_TargetHeight : function() {
return this.get_element().offsetHeight;
}
set_TargetHeight : function(value) {
this.get_element().style.height = value + "px";
this.raisePropertyChanged('TargetHeight');
}

You will no doubt notice that get_TargetHeight uses the element offsetHeight, but set_TargetHeight uses style.height instead. Well in IE 7, offsetHeight becomes 0, but in IE 6, it stays at the full height of the DIV.

I'd post this on the AJAX site, but since that page just asks me repeatedly for a windows login, it kind of makes it impossible.

posted Wednesday, July 04, 2007 1:31 PM by admin with 0 Comments

The type or namespace name 'ProfileCommon' could not be found

What the hell does that mean?

That was my initial response.

I uploaded a new version of my .NET 2.0 website.  In the process I had changed it from a File based web site, to an ASP.NET web application (same as for .NET 1.1)

After uploading it, I got that error while my site was compiling.

Eventually I tracked it down.  I replaced my files instead of deleting the site clean and starting over.

As part of that, I left behind the PrecompiledApp.config file from the old version.

When I deleted it, suddenly everything started working again.

 

posted Monday, May 07, 2007 11:44 PM by admin with 0 Comments

When is a CRM tracing token not a tracking token?

Yet another fun instance of CRM doing strange things.

Ok.  I need to create an email (no problem, done it in a workflow, and a scheduled task).

Then I need to "Send" it (not really sent, just marked as sent, I'm actually using it to record an SMS)

No problem, works in the scheduled task I've already done.

Started on the workflow and I get:

System.Web.Services.Protocols.SoapException: Server was unable to
process request. --->

System.Reflection.TargetInvocationException:
Exception has been thrown by the target of an invocation. --->

Unexpected type for the property.
Schema error: property trackingtokenid does not have the expected type.

 

Well, that doesn't make sense.  In both cases I was setting trackingtoken = ""  Which is supposed to tell CRM to assign one for you. By the way, don't leave it = NULL, that crashes.

After much hunting I managed to track this back to the real cause.

The scheduled task was running as ME, and I'm a CRM user, no problem.

The workflow runs as Network Service.  Not a CRM user, but a member of "PrivUserGroup" in the AD.

What does that mean?

What it means is that if you set CallerID.CallerGuidValue to a systemuserid guid, it is allowed to impersonate that user.

No set the ID, no valid user.  This really should have been an authentication error.

By the way, if you set the caller ID every time, the situation reverses, the workflow runs, and the scheduled task bombs out with a security error.  Like what we should have had.

So, the solution is to set the caller ID, and to set the scheduled tasks to run as a custom user with membership in PrivUserGroup.  Of course that opens a whole set of other issues which we don't want to go into here.

Now, why?

Because of the tracking token format.

  • Standard Prefix
  • Location ID
  • User ID
  • Unique ID

Note the user ID?  No CRM user = no CRM user ID, hence no valid tracking token.


Web Service call from the log



http://schemas.xmlsoap.org/soap/envelope/"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">

http://schemas.microsoft.com/crm/2006/WebServices">
xmlns="http://schemas.microsoft.com/crm/2006/CoreTypes">00000000-0000-00
00-0000-000000000000



xmlns="http://schemas.microsoft.com/crm/2006/WebServices">
1534e1d4-29a0-db11-bac3-000c29f05e38
false





posted Tuesday, January 16, 2007 7:14 PM by admin with 0 Comments

Microsoft CRM: The parent object is invalid or missing
Welcome to one of the least mentioned errors you can get with CRM 3.0. "Unexpected error occurred" is worse, but at least it has web pages. When I wrote this post, the only references to this error were the two Microsoft pages that list the CRM error codes. Since I'm about to call Microsoft Gold support, I'll put what they tell me here.

posted Thursday, December 14, 2006 1:49 PM by admin with 1 Comments

Powered by Community Server, by Telligent Systems