Dynamics CRM Getting Account Details - dynamics-crm

I'm having a problem with the following thing.
In Dynamics CRM I have a Custom Button that created a new Order, the button works great, however, I wanted to make it work as the OOB one and prefilled some of the Account information such as Account Name and Price List (form example).
example
In Ribbon Workbench I've added the following parameter for my button
ribbon settins
The next thing that I've done was to create a new Jscript web resource and add the following code.
references: https://learn.microsoft.com/en-us/dynamics365/customerengagement/on-premises/developer/customize-dev/pass-dynamics-365-data-page-parameter-ribbon-actions
Web resource name: new_getorder
Code: function XrmCore.Commands.Open.openNewRecord(primaryControl) {
var formContext = primaryControl;
}
I've then added the web resource on the Order form where is supposed to trigger when clicking on the custom button from the account form, but I'm getting a script error (which is not a surprise for me)
form properies
I've also enabled Pass execution context as first parameter
Web resource method does not exist: XrmCore.Commands.Open.openNewRecord
new order button from account ribbon
Error when loading the Order form: Web resource method does not exist: XrmCore.Commands.Open.openNewRecord

Instead of custom code, why don't you try Map Entity Field feature?
You can map attributes between entities that have an entity
relationship. This lets you set default values for a record that is
created in the context of another record.
In your scenario, after mapping Account and Price list fields between Account and Order tables, when you will go to the Related > Orders section and try to create an Order from there, those two fields should be pre-filled on the new Order form.
And I think this feature would work also when you have a Orders sub grid on account form and try to create Order from new button on the sub grid.
You may go through the documentation to understand this concept and to check steps to create mapping.

Anyway, I've managed to find my solution by using this script in a custom web resource
enter code here
var entityFormOptions = {};
entityFormOptions["entityName"] = "salesorder";
entityFormOptions["createFromEntity"] = currentRecordRef;;
// Open the form.
Xrm.Navigation.openForm(entityFormOptions).then(
function (success) {
console.log(success);
},
function (error) {
console.log(error);
});

Related

Retrieve Plugin not getting triggered

We are on Dynamics CRM 2016 On-Premise. Using a plugin I'm trying to automatically update a field when a user open the CRM Account form, in this example to value "5". Here's my code:
var targetEntity = (Entity)context.OutputParameters["BusinessEntity"];
if (targetEntity == null)
throw new InvalidPluginExecutionException(OperationStatus.Failed, "Target Entity cannot be null");
var serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = serviceFactory.CreateOrganizationService(context.UserId);
if (targetEntity.Attributes.Contains("MyField"))
fedTaxId = targetEntity.Attributes["MyField"].ToString();
targetEntity.Attributes.Add("MyField"d, "5");
targetEntity["MyField"] = "5";
service.Update(targetEntity);
I list this in message type 10 (Before Main Operation Outside Transaction).
In Plugin Registration I list this as Post Operation stage and Synchronous.
However when I open the Account form, the page blinks once but the value did not get automatically populated. There is no javascript that would've manipulated this form or value either.
Any suggestion? Thanks.
Two options:
Add a script on the form setting the field value on load. Keep in mind this script should only do its thing if the form type = 2.
(Not recommended) Register a plugin on the synchronous post retrieve message for the entity. Make sure this step sets the field value on the entity object in the OutputParameters collection. Now, keep in mind your form will not be aware of the fact that this field has been modified, so it will not be flagged dirty and it will not automatically be submitted when record changes are being saved. So, in this scenario you would still need to add some JavaScript OR you would need an extra plugin registered on the pre update message of the entity setting the field as desired.

Dynamics CRM limit "regarding" lookup field for only 1 entity on Appointment form and set default view for "Look in"

I am trying to limit entities that the user can select from on "Regarding" field on Appointment form and set some default views used by these lookup fields.
The big idea is that when user is entering data in the field itself, the results should be provided from default view for this lookup, e.g. "Contacts I follow", but when user enters "Lookup more records" pop-up the default view should be swapped to "All contacts".
This field can look up in many entities, e.g. Account, Contact, Billing, etc., and I want to limit it strictly to Accounts only.
So far I've found two ways of doing it:
1) Add filters to lookup fields, so that any records not fulfilling given criteria will not be shown. This is done using addPreSearch JS function from Xrm lib, like this:
var addEventHandler = function (defaultView) {
Xrm.Page.getControl("contactid").addPreSearch(function () {
addFilter("contactid", defaultView)
});
}
var addFilter = function (entityName, defaultView) {
var filterXml = "<filter type = 'and'>" +
"<condition attribute='contactid' operator='null'/>" +
"</filter>";
Xrm.Page.getControl("contactid").addCustomFilter(filterXml, "contact");
Xrm.Page.getControl("contactid").setDefaultView(defaultView);
}
(This is just sample code, not actually applied to the Regarding field)
2) Second option is to use undocumented solution by using setLookupTypes function on the field itself, like this:
var limitLookupEntities = function () {
Xrm.Page.getAttribute("contactid").setLookupTypes(["contact"]);
}
var changeDefaultViewForLookup = function(viewGuid){
Xrm.Page.getControl("contactid").setDefaultView(viewGuid);
}
The issue:
The problem is that as mentioned earlier, "Regarding" field can look up in many entities. Limiting them using the solution 1) is tedious, having to create as many filters as there are entities and applying them one by one to the field doesn't seem the right way to go. However, the way I implement this, the default view behaviour works as intended - the look-in value is only changed for the pop-up window.
Solution 2) is way easier to implement, and won't require any changes in the future if any new entities would be added to relationship with "Regarding" field, but the default view is applied to both "in-field" and "pop-up" default view.
The solution I'm looking for needs to do the following:
It should limit the search to specified entity only
It shouldn't require any maintaining after being implemented, e.g.
in case new entities are introduced to "Regarding" field.
It should be generic - I might want to be able to parametrize it and use it on other forms
It should apply the default view change only when user opens the pop-up search window
Is it even possible?
The CRM version I'm implementing this on is 8.2 on-prem.

CRM SDK OrganizationServiceContext null navigation properties on entity

Trying to migrate an existing solution away from the deprecated Microsoft.Xrm.Client namespace to just use the generated service context from CrmSvcUtil using CrmSDK 9.0.0.5.
Previously we were using Microsoft.Xrm.Client.CodeGeneration.CodeCustomization to get a lazily loaded context.
I have two copies of the same solution and have been working through some of the API changes.
I have enabled Proxy Types
client.OrganizationServiceProxy.EnableProxyTypes();
Which to my understanding switched it to act in a lazily-loaded manner. However, none of the navigation properties are loading as expected.
The few blog posts that I've found around this shift to CrmServiceClient etc suggest that even without lazy loading I should be able to load the property manually with a call to Entity.LoadProperty() which will either load the property or refresh the data. However, after doing that the navigation property is still null (specifically I'm trying to use a Contact navigation property). When I look through the RelatedEntities collection it is also empty.
I know that the entity has a related contact item as if I use a context generated with Microsoft.Xrm.Client.CodeGeneration.CodeCustomization it returns it and I can also see it in CRM itself using an advanced search.
var connectionUri = ConfigurationManager.ConnectionStrings["Xrm"].ConnectionString;
var client = new CrmServiceClient(connectionUri);
client.OrganizationServiceProxy.EnableProxyTypes();
var context = new XrmServiceContext(client);
var result = context.new_applicationSet.FirstOrDefault(x => x.new_applicantid.Id == CurrentUserId);
//result.Contact is null
context.LoadProperty(result, "Contact");
//result.Contact is still null
//result.RelatedEntities is empty

Filter records based on current user in PowerApps

I want to filter records on my browse screen with email of current user.I used Office 365 Users Connection. 
Logic Which I have written on items property of browse screen:
SortByColumns(Search(Filter('Time Entries', User().Email= Office365Users.MyProfile().Mail) , TextSearchBox1.Text, "cf_name"), "createdon", If(SortDescending1, Ascending,Descending))
Error:
Part of this filter cannot be evaluated remotely due to service limitations.The local evaluation may produce suboptimal or partial results.
Try changing the Onstart of your app to Set(CurrentUser,User()) and then instead of User().Email = Office365Users.Myprofile().Mail use CurrentUser.Email = Office365Users.Myprofile()

should a validation function access the repository directly?

I have the following in my application:
Action Orm entity (From telerik open access)
Repository(Of Action)
AppService(Holds an instance of the repository)
when I need to save an instance, I send the instance to the AppService. the AppService then calls a validator to validate the instance to save. the validator is based on http://codeinsanity.com/archive/2008/12/02/a-framework-for-validation-and-business-rules.aspx
(full code on https://github.com/riteshrao/ncommon)
so basically my save function in the AppService looks like this
Public Sub AddAction(ByVal Item As Data.Model.Action)
Contract.Requires(Of ArgumentNullException)(Item IsNot Nothing, "Item is nothing.")
Dim validateResult As Rules.ValidationResult = _ActionValidator.Validate(Item)
If Not validateResult.IsValid Then
Throw New Validation.ValidationException(validateResult)
End If
Try
_ActionRepository.Add(Item)
_unitOfWork.SaveChanges()
Catch ex As Exception
_unitOfWork.ClearChanges()
Throw New DataServiceException(ex.Message, ex)
End Try
End Sub
for checking properties of the Action item the sample code works great. my question begins when i need to make sure that the same action is not added twice to the DB for the same customer (ie. id is difference, name is the same and customer is the same)
as I see it I have a few options:
option 1: check for a duplicate action using something like
function(validatedItem) item.Customer.Actions.Any(function(item) item.id<>validatedItem.id andalso item.name=validatedItem.name))
basically I go from the action being saved back to the customer and then back to all his actions and check if any action exists with a different id and same name
the down sides are:
a. for this to work, when accessing the customer property of the item, the entire customer object is read from DB which is redundant in this case
b. the Any function is being evaluated on the client as item.Customer.Actions returns IList(Of Action)
Option 2: let the validation class have access to the action repository. then i could simply do something like
'assume I already have validatedItem
repository.Any(function(item) item.id<>validatedItem.id and item.customerid=validatedItem.customerid and item.name=validatedItem.name)
this will result in an Exists query being sent to the DB but the downside(?) is that the validation framework should not access the repository directly (as far as I have seen in the very few examples i could find that do use validation and ORM)
Option 3: let the validation class have access to the AppService and use the AppService to check for existence of a duplicate.
problems:
a. I create a circular reference (AppService->Validation Class->AppService)
b. I need to create a lot of useless functions in the AppService for loading items based on criteria that is only relevant for the validation
Any ideas what is the best course here?
The simplest is not to check duplicates in the database from your domain.
When a collection of entities is part of you aggregate then it is a non-issue since you would not permit the duplicate to be added to the collection. Since the aggregate is stored as a whole you would never run into the problem.
For scenarios where you do not want a duplicate, say, e-mail address and no collection of the entities is represented by an aggregate (such as the Users in a system) you can just let the database enforce the uniqueness. Simply pick up the exception and report back. In many instances your validation would not be able to enforce the uniqueness simply because it doesn't have/implement the required locks that a database system would have.
So I'd simply leave that up to the database.

Resources