Hi guys,
Just want to share how we can modify the View Filter Criteria/Condition dynamically.
Introduction
Recently I have requirement that I need to create a View in CRM that there is no way to construct it from Advanced Find and make it dynamic.
For example,
I need to have query that:
1. The Date parameter is must be changed accodingly based on the today date and
2. Another parameter must get the value from a Configuration Entity
Ok, for number 1, we can force the users to always go to the View and change the date accordingly, but how about number 2?
So, my use case:
Show me the list of Customers that due date is in the next 21 days?
Meanwhile,
21 here is must be dynamically obtained from another Configuration entity.
So, this is nearly impossible, because even we use Advanced Find there is no way to use variable as parameter in the filter criteria that we need to query from another entity that is NOT related at all!
As we know that Advanced Find Query, only has limited operator and also it cannot Query from another entity, only limited to the related entities.
Use Case
So, to go to the code, I need to tell the scenario first, and to make it simpler, I just use this use Case:
I want to get all Active Customers that birthday is this Month.
This month is May for example.
So, I have a custom field = Birthday Month
Which I have auto-populated this field before with the Date Birth component (in another plugin).
So, now I need to always update the View to always Query to the:
Status = Active and Birthday Month = 5
And for the Next Month (June) should be:
Status = Active and Birthday Month = 6
Which last Month for April
Status = Active and Birthday Month = 4
Those number 5, 6, and 4 are supposed to be generated dynamically.
And I can’t use the
This-Month operator because I dont have May 2016 Data, since I save the DOB, not updating every customer BOD every year plus 1 year.
You can also add another requirement, such as must be a Member Customer with Annual Income more than X, which X is you taken from Configuration entity.
What you need is just a new fetch XML or Query Expression that you can just convert use this request!
QueryExpressionToFetchXmlRequest req = new QueryExpressionToFetchXmlRequest();
req.Query = qenew;
QueryExpressionToFetchXmlResponse resp = (QueryExpressionToFetchXmlResponse)service.Execute(req);
But, for this use case, my point is jut to point out to you how to modify the Query just as per you wish (sorry as per Users’ whish
)
The Current View
So, for the post here, I just need to replace the Query from the Existing View (in your case, you might need to create a new View)
Then I got the savedqueryid from this view
The Code
public void Execute(IServiceProvider serviceProvider)
{
#region must have
IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
// Create service with context of current user
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
//create tracing service
ITracingService tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
#endregion
if (context.OutputParameters.Contains("BusinessEntity"))
{
var retrievedResult = (Entity)context.OutputParameters["BusinessEntity"];
Entity entity = retrievedResult;
string fetch = string.Empty;
//the below GUID, you can do advance query to make this as non-hardcoded one, you can find by name as well, for example
//just for my use case here, I post here as final GUID of the 'Active Customer' view GUID
//in ACTUAL case, do not use harcoded one because it will change in different environment unless for Out of The Box Entities View
if ((Guid)entity["savedqueryid"] == new Guid("00000000-0000-0000-00AA-000010001004"))
{
QueryExpression qenew = new QueryExpression("contact");
ConditionExpression activeCon = new ConditionExpression()
{
AttributeName = "statecode",
Operator = ConditionOperator.Equal,
Values = { 1 }
};
int currentMonth = DateTime.Now.Month; //this is the variable that dynamically you need to insert in
ConditionExpression birthdayCon = new ConditionExpression()
{
AttributeName = "ags_birthdaymonth",
Operator = ConditionOperator.Equal,
Values = { currentMonth }
};
qenew.Criteria.Conditions.Add(activeCon);
qenew.Criteria.Conditions.Add(birthdayCon);
//for easy fetch XML I use the Query Expression then convert to FetchXML
//but you can always use the directly generated fetchXML and also can get from Advanced Find as well
QueryExpressionToFetchXmlRequest req = new QueryExpressionToFetchXmlRequest();
req.Query = qenew;
QueryExpressionToFetchXmlResponse resp = (QueryExpressionToFetchXmlResponse)service.Execute(req);
//work with newly formed fetch string
string myfetch = resp.FetchXml;
//change the existing
entity["name"] = "Active Customer Birthday this Month";
entity["fetchxml"] = myfetch;
}
}
}
Code Explanation
*For the GUID of savedqueryid section, I got the ID and I implement in my code
*In your case, you need to do query, do not hardcode, please see my comment in the code as well.
For the Query Expresison, this is the place for you to change the logic as per your current requirement
Then for the Fetch XML
As the title mentioned, Then you need to register as POST event for RETRIEVE message, entity = savedquery.
Refresh the Advanced Find or View to see the result.
Result
As we can see that now, the Active Customer View (The View that we just now changed the fetchXML dynamically), now has this Query
You can also try to tweak your code, by just add additional conditional over the existing view by retrieving the fetch xml
string baseFetchXML = enSavedQuery["fetchxml"].ToString();
Then use this request to convert to Query Expression easily
FetchXmlToQueryExpressionResponse
Example of what I Did:
Remember, you can also add another Parameters.
So use this method for Querying:
1. Query that different from the static query from the View
2. Query that requires dynamic Date/Datetime variables
3. Query that needs condition obtained from another non-related entity
4. Query with variable from another Entity, let’s say Configuration Entity
5. Another Impossible Query using standard static Advanced Find
6. Also can do query that involving Current User, Security Role, or Team Query
7. Query requires Operator like “Does-Not-Equal Today” then you can utilize the “ON-OR-BEFORE” or “ON-ON-AFTER”
8. Query for “NOT IN”, then this one you can utilize the “DOES NOT EQUAL” function
But remember, you still need to use FetchXML in the End.
Hope this helps!
Thanks