Here comes the interesting issue. I want to know any settings makes this difference or any workaround to get it right.
We have different Dynamics 365 CRM online instances but all are identical as they are refreshed from Prod. Recently developed plugin code behaves differently across the environments.
var organizers = (EntityCollection)appointment["organizer"];
Entity record = organizers.Entities[0];
EntityReference organizer = (EntityReference)record["partyid"];
On appointment creation, the post-create async plugin code read the organizer - one of the activity party field but the result is very different. Though systemuserid is identical, the name is coming from that entity reference properly in Dev but coming as null in other environments.
That is a strange problem indeed. If you hadn't refreshed the other orgs from PROD, I would say maybe there's a different image registered in the plugin registration.
Since the code, environment, plugin registrations, and even record ID are the same, this one might be worth a Microsoft support ticket.
In the meantime, a workaround would be to check if Name is null, and if so, retrieve the Name. It's another call to the system, but will allow you to proceed while you see if Microsoft can offer any insight.
MS agreed this as a bug, but actually this context difference is identified between the classic web UI & the UCI. Only for appointment entity, because of some oData response known issue - UCI target entity is missing the formatted values.
I got the plugin profiler log from my QA team so I didn't realize they were testing in UCI but I tested in web, so the quick watch showed the difference while replay/debugging.
Anyway until MS prioritize & fix this bug, I have the below workaround to unblock this issue.
#region Workaround for fixing UCI app EntityReference coming as empty string
if (string.IsNullOrEmpty(organizer.Name))
{
ctLog.Log("organizer.Name is empty");
fetch = string.Format(#"<fetch>
<entity name='systemuser' >
<attribute name='fullname' />
<filter type='and' >
<condition attribute='systemuserid' operator='eq' value='{0}' />
</filter>
</entity>
</fetch>", organizer.Id);
ctLog.Log("fetch built");
results = userOrgService.RetrieveMultiple(new FetchExpression(fetch));
ctLog.Log("results count: " + results.Entities.Count);
if (results.Entities.Count > 0)
{
organizer.Name = results.Entities[0].GetAttributeValue<string>("fullname");
}
}
#endregion
Related
I created application using CRM 2011 SDK.
While retrieving audit record i use recommended code.
My code looks like this:
using (_serviceProxy = ServerConnection.GetOrganizationProxy(serverConfig))
{
_service = (IOrganizationService)_serviceProxy;
RetrieveRecordChangeHistoryRequest changeRequest = new RetrieveRecordChangeHistoryRequest();
changeRequest.Target = new EntityReference(Static.IncidnentsEntityName, new Guid(id));
RetrieveRecordChangeHistoryResponse changeResponse =
(RetrieveRecordChangeHistoryResponse)_service.Execute(changeRequest);
return changeResponse.AuditDetailCollection.AuditDetails.SelectMany(s => createAuditRecord(s)).ToList();
}
where createAuditRecord function just unpacks attributes. There is an attribute called userid, but it always returns system user, under which my app is calling CRM, but not the logged user.
While directly querying SQL ,I've found that there is an information about logged user.
Is there some way to extract this information without directly extracting data from DB?
I prefer to extract information directly from database if it's for external use or reports. It's much faster, you can do complexier queries and you will save a lot of time. There no plus value of using the SDK to read data other than being sure it gonna be supported in the next version and supported online.
Background
I am working on a RESTful API written in C#/.NET and need to switch between the production database and dev database for testing new API calls. The previous lead developer's API made no sense, so we are replacing the most important parts of it before rebuilding the application from scratch.
The Goal
I need to switch to the SqlMembershipProvider for the dev database server on the fly to test CRUD operations on user accounts.
The Problem
The MSDN "documentation" says that the Membership.CreateUser method calls SqlMembershipProvider.CreateUser, but calling this underlying method directly returns null and sets the status output to invalidAnswer.
Configuration
I have the connection string and provider definition configured in Web.config:
<connectionStrings>
<add name="ConnString" connectionString="server=prodblahblah">
<add name="DevConnString" connectionString="server=devblahblah">
...
<membership defaultProvider="SQLDBMembershipProvider">
<providers>
<add name="SQLDBMembershipProvider" connectionStringName="ConnString" requiresQuestionAndAnswer="false" ...>
<add name="DevSQLDBMembershipProvider" connectionStringName="DevConnString" requiresQuestionAndAnswer="false" ...>
Code
Based upon the bits of advice I found scattered across the internets, I came up with and attempted the following:
SqlMembershipProvider p = (SqlMembershipProvider)Membership.Providers["DevSQLDBMembershipProvider"];
MembershipCreateStatus status;
string question = "";
string answer = "";
MembershipUser mu = p.CreateUser(username, password, email, question, answer, true, Guid.NewGuid(), out status);
Result
The call returns null and sets the output status variable to invalidAnswer. This perplexes me because requiresQuestionAndAnswer is set to false in the configuration, and calling Membership.CreateUser results in null values in the aspnet_Membership table.
Strangely, I get the same outcome when using Membership.Providers["SQLDBMembershipProvider"] instead of ["DevSQLDBMembershipProvider"], so there must be some difference between the way that Membership.CreateUser and SqlMembershipProvider.CreateUser handle password questions/answers.
Small Rant About MSDN "Documentation"
The code example given in the MSDN documentation for SqlMembershipProvider.CreateUser does not even actually show how to use SqlMembershipProvider.CreateUser -- it instead calls Membership.CreateUser and does not mention how to access the non-default providers configured in the Web.config file. The code example in the documentation for a method specifically does not show how to use that method. I think it is fair to say that MSDN has the most infuriatingly unhelpful documentation I have ever seen.
Question
Why does Membership.CreateUser work with empty password question/answer values while SqlMembershipProvider.CreateUser does not? How do I work around this?
I figured out the answer while writing this question. Since it is difficult to find documentation for this stuff anywhere, I decided to post the question and answer it with my findings.
The Answer
It turns out that "" is not accepted while null is. An empty string is invalid while a null is acceptable. This makes perfect sense to everyone, of course. It is inherently intuitive that an empty string is unacceptable while a null string is acceptable. Obvious.
It is definitely a good thing that Microsoft in their infinite[simal] wisdom decided to not show examples of how to use their code in their code examples. They are professionals, after all, and that is just how documentation works.
I'm usinng skybrud social to allow users to log into my site via Facebook, but am having a problem.
For some reason, the response never contains anything other than the Name and Id of the user... everything else is null.
var url = client.GetAuthorizationUrl(state, "public_profile", "email");
var service = FacebookService.CreateFromAccessToken(userAccessToken);
FacebookMeResponse user = service.Methods.Me();
Has anyone experienced this before? What could be the problem?
Facebook has multiple versions of their Graph API. In the most recent version (2.4), less fields are returned by default, and you instead have to tell the API to return the fields that you need. What version of the API you're using depends on the time you registered your app with Facebook.
Based on your code, it seems that you're using an older version of Skybrud.Social. If you update to the most recent version (0.9.4.1), you can do something like this:
// Declare the options for the call to the API
FacebookGetUserOptions options = new FacebookGetUserOptions("me") {
Fields = "name,email,gender"
};
// Make the call to the API
FacebookUserResponse response = service.Users.GetUser(options);
Hope this answers your questions ;)
This is my problem:
all I want to do is update a "contact" entity in Crm 4 using the webservice.
This is my code:
CrmService eatupCrmService = CrmInteraction.InitializeCrmService();
contact updatedDelegate = new contact();
CeatupCrmService.Key contactPrimaryKey = new CeatupCrmService.Key();
contactPrimaryKey.Value = delegateId;
updatedDelegate.contactid = contactPrimaryKey;
updatedDelegate.address2_postalcode = delegateDetails.ContactDetailsPhysicalAddressCode;
eatupCrmService.Update(updatedDelegate);
I use the InitializeCrmService() to also retrieve and it works.
When updating the address2_postalcode attribute, I get the following error:
"Server was unable to process request."
with the exception Detail\InnerText :
"0x80040216 An unexpected error occurred. Platform".
If I change the code to update another attribute, say I try to update the mobilephone attribute
instead of address2_postalcode it works without any exceptions thrown.
As soon as I try to update address2_postalcode then I get that error. The address2_postalcode data type in Crm is nvarchar, and the value it is being assigned (delegateDetails.ContactDetailsPhysicalAddressCode) is of c#'s string type.
Anyone have any idea why this could be happening?
This same error and situation happened to me because I did an SSIS dts to load contacts in CRM from a flat file, in unsopported way, and I forgot to fill the CustomerAddressBase table. After filling this table "correctly" (two rows for each contact) the attributes of the View CustomerAddress(address1_addressid and address2_addressid) became not null. If you don't know how to fill this table (CustomerAddressBase) just create one new contact directly with address fields filled in CRM and then go to SQL Server management studio and by query you can see and know how the fields are filled.
Hope it helps somebody,
Alex
After many attempts at trying to understand why this error was occurring, I finally succeeded.
When I started working on this project, the client instructed me to test using only a specific contact, because we were working directly on the production environment. (the client does not have a development environment yet)
After doing some database queries to compare this contact to others (updates were failing only for the test contact) I noticed that my contact's address2_addressid attribute was NULL.
I then went to CRM under Customization\Customize Entities and opened up the contact entity. Under attributes, I ordered by type and saw that the contact has 3 primarykey attributes: contactid, address1_addressid and address2_addressid.
The test contact's address1_addressid and address2_addressid fields were NULL and this caused the CRM web service to throw the 0x80040216 An unexpected error occurred. Platform error upon me trying to update any of the address fields.
I don't know why this contact had those IDs set to NULL, I asked and the person that created the contact had no explanation of how this could have happened. I guess this will remain a mystery, but at least I now have an answer to the error I was getting and I can cater for this in my code.
I don´t know ho it can work...
I think you have to do CrmService.Create(contact) and then with the returned Guid you can perform updates...
Update is not going to work since the record with the Id you are setting on your contact entity doesn´t exist in the db...
contact updatedDelegate = new contact();
CeatupCrmService.Key contactPrimaryKey = new CeatupCrmService.Key();
You could do something like:
crmService eatupCrmService = CrmInteraction.InitializeCrmService();
contact updatedDelegate = new contact();
updatedDelegate.address2_postalcode = delegateDetails.ContactDetailsPhysicalAddressCode;
Guid cId = eatupCrmService.Create(updatedDelegate);
updatedDelegate.contactid = new Key(cId);
//set more fields if you want
eatupCrmService.Update(updatedDelegate);//update record
Wish I have helped you.
Im having some trouble with Dynamics CRM 4. Im trying to update prices and availability with the crm-service in a WPF-app but it takes forever. Up to half an hour with about 6000 products. Should it take so long? Can I do this in some other quicker way?
QueryExpression query = new QueryExpression();
query.EntityName = EntityName.product.ToString();
BusinessEntityCollection entities = crmService.RetrieveMultiple(query);
foreach (product crmProduct in entities.BusinessEntities.OfType<product>())
{
crmProduct.price = new CrmMoney() { Value = 123M };
crmProduct.stock = new CrmNumber() { Value = 123 };
crmService.Update(crmProduct);
}
To improve performance, try to update only the fields that you really wan to update. Your code is updating every attribute, because you are using the product that comes from CRM. When you are doing that every plugins are fired and because product is a core CRM entity, more CRM logic can be fired when updating this entity.
Try to get only the primary key of product (productid) and set both fields and call the update statement. With this, you should achieve about 100 requests per second on standard hardware when using a sequential process.
To achieve more updates, try running the process on the CRM server or using parallel processing.
Try setting this on your CRM Service object:
crmService.UnsafeAuthenticatedConnectionSharing = true;
This makes the service only authenticate once, then uses the same credentials. This would be a bad thing if the code were in a web site where multiple people were going to be using the same CRM Service, as future users could get access to records they shouldn't, however, in a WPF app where there's just one user, this isn't a concern.
Here's an article with more metrics and some more things to think about tweaking. It originally applies to CRM 3, but we've found the same settings in 4 still boost performance.