You've probably read a bunch of stuff about using COLUMNS_UPDATED, and if you've ended up here, it's not working for you properly.
Here's a snippet from an APRESS book on using COLUMNS_UPDATED()
SELECT ColumnName = [column_name]
FROM INFORMATION_SCHEMA.COLUMNS
WHERE [TABLE_NAME] = & -
TableName AND ORDINAL_POSITION = @bitmaskpower + 1
Note they get the column name from INFORMATION_SCHEMA.COLUMNS based on table name and ordinal position.
Now below is "Columns_Updated", "Ordinal Position", "Field Name", and the calculation of the position based on the columns_updated value for a table I was having trouble with.
Not only do the positions not match after the first column (primary key), but the offset is not fixed along the list of columns. I haven't found a solution yet, but I'm working on it.
0x010000000000 1 Membership ID - Right
0x080000000000 2 Address1 - OFF BY 2 (4)
0x800000000000 6 MembershipTypeID - OFF BY 2
0x000100000000 7 SubscriptionClassID - OFF BY 2
0x000200000000 8 AreaID - OFF BY 2
0x000800000000 10 Comment - OFF BY 2
0x004000000000 13 ZIP - OFF BY 2 (15)
0x000008000000 18 Subscription - OFF BY 2 (20)
0x000020000000 20 DateBilled - OFF BY 2 (22)
0x000040000000 21 Billed - OFF BY 2 (23)
0x000000020000 22 MobilePhone - OFF BY 4 (26)
0x000000080000 23 EmailAddress - OFF BY 5 (28)
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?
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.
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] | RAAQUKzDsAAA5RAAriVlgoAAA | AAAAAA== |
| IPM.Appointment: fghfhdfghdfghdfgh
|
| EXPANDED / CONTRACT / MOVE WITHIN CALENDAR |
| ModifiedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5RAAriVlgpQAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| CreatedEvent | [ModifiedEventType] | RAAQUKzDsAAA5RAAriVlgoQAA | DwAAAA== |
| IPM.Appointment: fghfhdfghdfghdfgh |
| ModifiedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5RAAriVlgpQAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| SOFT DELETE |
| ModifiedEvent | [MovedCopiedEventType] | RAAQUK0ABgAA5RAAriVlwzQAA | AAAAAA== |
| IPM.Appointment: fghfhdfghdfghdfgh |
| === OUTLOOK === |
| CREATE |
| ModifiedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| EXPANDED / CONTRACT / MOVE WITHIN CALENDAR |
| ModifiedEvent | [ModifiedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEAwAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE |
| ModifiedEvent | [MovedCopiedEventType] | eAAriVgADAAA5jp9kS9UdUCKFiIaz2NQeAAriVgSAQAA | AAAAAA== |
| IPM.Appointment: TEST 5 |
| COPIED WITHIN CALENDAR |
| ModifiedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| HARD DELETE |
| ModifiedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgEBAAA | DwAAAA== |
| 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/RAArjVW2JgAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| CreatedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2JwAA | DwAAAA== |
| IPM.Appointment: TEST 6 |
| DeletedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2JgAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| EXPANDED / CONTRACT / MOVE WITHIN CALENDAR |
| CreatedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2KAAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| ModifiedEvent | [ModifiedEventType] | GRlvYJ3GL/RAArjVW2JwAA | DwAAAA== |
| IPM.Appointment: TEST 6 |
| DeletedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2KAAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| SOFT DELETE |
| MovedEvent | [MovedCopiedEventType] | GRlvYJ3GL/RAArjVXWTQAA | AAAAAA== |
| IPM.Appointment: TEST 6 |
| SOFT DELETE RESTORE |
| CreatedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2KwAA | AAAAAA== |
| IPM.SchedulePlus.FreeBusy.BinaryData: |
| MovedEvent | [MovedCopiedEventType]: | GRlvYJ3GL/RAArjVW2LAAA | AAAAAA== |
| IPM.Appointment: TEST 6 |
| DeletedEvent | [BaseObjectChangedEventType] | GRlvYJ3GL/RAArjVW2KwAA | AAAAAA== |
| No Messages Matched: ErrorItemNotFound |
| === OUTLOOK === |
| CREATE |
| CreatedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| EXPANDED / CONTRACT / MOVE WITHIN CALENDAR |
| ModifiedEvent | [ModifiedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECQAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| MOVED FOLDER / SOFT DELETE / SOFT DELETE RESTORE |
| MovedEvent | [MovedCopiedEventType] | RAAQUK0ABgAA5jp9kS9UdUCKFiIaz2NQeAAriVgUBAAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| COPIED WITHIN CALENDAR |
| CreatedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAA | DwAAAA== |
| IPM.Appointment: TEST 5 |
| HARD DELETE |
| DeletedEvent | [BaseObjectChangedEventType] | RAAQUKzDsAAA5jp9kS9UdUCKFiIaz2NQeAAriVgECgAA | DwAAAA== |
| 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.
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.
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*
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).
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?
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.
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
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 :)
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.
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.
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.
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