I have a workflow that reassigns the owner based on a field called "QuoteWerks Prepared by".
I cannot seem to post a screenshot in StackOverflow, so please see screenshot in my post in another forum here: https://community.dynamics.com/crm/f/117/p/358168/941269#941269
The "KED365" step is a custom workflow activity, and uses the code below.
The "Set properties" portion of this step sets the field to "QuoteWerks Sales Rep".
Next, the record gets assigned to the user that was returned in the previous step.
However, the workflow has suddenly stopped working. I receive the error below:
The Owner was not provided.
Plugin Trace:
[Microsoft.Xrm.Sdk.Workflow: Microsoft.Xrm.Sdk.Workflow.Activities.AssignEntity]
[Microsoft.Xrm.Sdk.Workflow (9.0.0.0): Microsoft.Xrm.Sdk.Workflow.Activities.AssignEntity]
Error Message:
Unhandled exception:
Exception type: System.ArgumentException
Message: The Owner was not provided
-- End stack trace --
Exception type: Microsoft.Crm.CrmArgumentException
Message: The Owner was not provided
at Microsoft.Crm.Workflow.Services.AssignActivityService.Execute(ActivityContext executionContext, AssignEntity assignEntity)
at System.Activities.CodeActivity.InternalExecute(ActivityInstance instance, ActivityExecutor executor, BookmarkManager bookmarkManager)
at System.Activities.Runtime.ActivityExecutor.ExecuteActivityWorkItem.ExecuteBody(ActivityExecutor executor, BookmarkManager bookmarkManager, Location resultLocation)
-- End stack trace --
I see the error says "The owner was not provided", but I cannot figure out why it has suddenly stopped working or how to fix it. The workflow worked fine until about a week ago. Any help fixing this would be greatly appreciated.
Thank you!
namespace KED365.Workflows
{
using System;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using Microsoft.Xrm.Sdk.Query;
using System.Linq;
public sealed class GetUserByFullName : WorkFlowActivityBase
{
[Input("User Full Name")]
public InArgument<string> UserFullName { get; set; }
[Output("Prepared By")]
[ReferenceTarget("systemuser")]
public OutArgument<EntityReference> PreparedBy { get; set; }
[Output("IsSuccess")]
public OutArgument<bool> IsSuccess { get; set; }
[Output("Message")]
public OutArgument<string> Message { get; set; }
protected override void Execute(CodeActivityContext activityContext,
IWorkflowContext workflowContext, IOrganizationService CrmService,
ITracingService trace)
{
try
{
string userName = UserFullName.Get(activityContext);
if (string.IsNullOrWhiteSpace(userName))
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "User's Full Name is not provided");
return;
}
var QEsystemuser = new QueryExpression("systemuser");
QEsystemuser.ColumnSet.AddColumns("fullname");
QEsystemuser.Criteria.AddCondition("fullname", ConditionOperator.Equal,
userName);
var results = CrmService.RetrieveMultiple(QEsystemuser);
if (results == null || !results.Entities.Any())
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "User with " + userName + " not found") ;
return;
}
if (results.Entities.Count > 1)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "Multiple users found with same name : " +
userName);
return;
}
(activityContext, true);
PreparedBy.Set(activityContext,
results.Entities.Single().ToEntityReference());
}
catch (Exception ex)
{
IsSuccess.Set(activityContext, false);
Message.Set(activityContext, "An error occurred trying to find user : " +
ex.Message);
}
}
}
}
--------------
I would check my Nuget version: https://www.nuget.org/packages/Microsoft.CrmSdk.Workflow/
Related
I tried making an addon using the existing selenium addon codes and resources.
I was able to make an addon with just one command (for testing) to open Flipkart.
I used the selenium.open command code and edited it slightly by entering default value of URL argument as (flipkart.com).
I was successfully able to build my solution (I made sure to add all the nuget packages and other necessities)
Now when I try to load the addon in my studio, I'm getting an error mentioning that it expected command postfix for the FlipkartOpen command.
Can anyone please let me know the reason for this error and maybe a possible solution to fix it?
Here's the error image: G1ANT Studio Error for New Addon.
And here's my code sample:
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Linq;
using System.Text;
using G1ANT.Language;
using OpenQA.Selenium;
namespace G1ANT.Addon.Flipkart.Commands
{
[Command(Name = "Flipkart.Open", Tooltip = "This command opens flipkart in a web browser provided in the Argument.")]
public class FlipkartOpen : Command
{
public FlipkartOpen(AbstractScripter scripter) : base(scripter)
{
}
public class Arguments : CommandArguments
{
// Enter all arguments you need
[Argument(Required = true, Tooltip = "Name of a web browser")]
public TextStructure Type { get; set; } = new TextStructure(string.Empty);
[Argument(DefaultVariable ="Url", Tooltip = "Website Url")]
public TextStructure Url { get; set; } = new TextStructure("www.flipkart.com");
[Argument(DefaultVariable = "timeoutselenium", Tooltip = "Specifies time in milliseconds for G1ANT.Robot to wait for the command to be executed")]
public override TimeSpanStructure Timeout { get; set; } = new TimeSpanStructure(SeleniumSettings.SeleniumTimeout);
[Argument(Tooltip = "By default, waits until the webpage fully loads")]
public BooleanStructure NoWait { get; set; } = new BooleanStructure(false);
[Argument(Tooltip = "Result variable")]
public VariableStructure Result { get; set; } = new VariableStructure("result");
}
// Implement this method
public void Execute(Arguments arguments)
{
try
{
SeleniumWrapper wrapper = SeleniumManager.CreateWrapper(
arguments.Type.Value,
arguments.Url?.Value,
arguments.Timeout.Value,
arguments.NoWait.Value,
Scripter.Log,
Scripter.Settings.UserDocsAddonFolder.FullName);
int wrapperId = wrapper.Id;
OnScriptEnd = () =>
{
SeleniumManager.DisposeAllOpenedDrivers();
SeleniumManager.RemoveWrapper(wrapperId);
SeleniumManager.CleanUp();
};
Scripter.Variables.SetVariableValue(arguments.Result.Value, new IntegerStructure(wrapper.Id));
}
catch (DriverServiceNotFoundException ex)
{
throw new ApplicationException("Driver not found", ex);
}
catch (Exception ex)
{
throw new ApplicationException($"Error occured while opening new selenium instance. Url '{arguments.Url.Value}'. Message: {ex.Message}", ex);
}
}
}
}
To remove this error, when you add new class, write Command.cs at the end while adding. Try FlipkartopenCommand.cs
This should remove your error.
I am working on a Dynamics CRM CWA that updates the "Modified By" field based on a text field called "Prepared By". I currently have 3 errors that I need some help debugging (see below). They may be pretty easy fixes but I am fairly new to coding. Any help de-bugging would be greatly appreciated. Thanks!
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Globalization;
using System.Linq;
using System.Text;
using System.ServiceModel;
using System.Threading.Tasks;
using System.Activities;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Workflow;
using System.Runtime.Serialization;
namespace KED365.Workflows
{
/// </summary>
public class ModifiedBy : WorkFlowActivityBase
{
private Guid contactid;
[Input("User Full Name")]
public InArgument<string> UserFullName { get; set; }
/// <summary>
/// Executes the WorkFlow.
/// </summary>
/// <param name="crmWorkflowContext">The <see cref="LocalWorkflowContext"/> which contains the
/// <param name="executionContext" > <see cref="CodeActivityContext"/>
/// </param>
/// <remarks>
/// For improved performance, Microsoft Dynamics 365 caches WorkFlow instances.
/// The WorkFlow's Execute method should be written to be stateless as the constructor
/// is not called for every invocation of the WorkFlow. Also, multiple system threads
/// could execute the WorkFlow at the same time. All per invocation state information
/// is stored in the context. This means that you should not use global variables in WorkFlows.
/// </remarks>
protected override void Execute(CodeActivityContext activityContext, IWorkflowContext workflowContext, IOrganizationService orgService, ITracingService tracingService)
{
//get entity record for which plugin was fired
Entity _target = (Entity)workflowContext.InputParameters["Target"];
//check if portaluser name is to be obtained from custom createby or from custom modifiedby
if (workflowContext.MessageName.ToUpper() == "CREATE")
{
contactid = _target.Attributes.Contains("new_createdby") ? _target.GetAttributeValue<EntityReference>("new_createdby").Id : Guid.Empty;
}
else
{
contactid = _target.Attributes.Contains("new_modifiedby") ? _target.GetAttributeValue<EntityReference>("new_modifiedby").Id : Guid.Empty;
}
//retrieve contact fullname from contactid
var _contact = activityContext.CreateQuery("contact").Where(c => c.GetAttributeValue<Guid>("contactid").Equals(contactid)).FirstOrDefault();
if (_contact != null)
{
if (_contact.Attributes.Contains("fullname"))
{
fullname = _contact.GetAttributeValue<string>("fullname");
}
//retrieve Systemuser that has same name as that of new_portalcreatedby/ //new_portalmodifiedby
Entity _user = context.CreateQuery("systemuser").Where(e => e.GetAttributeValue<string>("fullname").Equals(fullname)).FirstOrDefault();
if (_user != null)
{
//check if we need to update createdby or modifiedby
if (workflowContext.MessageName.ToUpper() == "CREATE")
{
_target["createdby"] = _user.ToEntityReference();
}
else
{
_target["modifiedby"] = _user.ToEntityReference();
}
//assign new target to plugin executioncontext
workflowContext.InputParameters["Target"] = _target;
}
}
}
}
}
Error 1 :
Severity Code Description Project File Line Suppression State
Error CS1061 'CodeActivityContext' does not contain a definition for 'CreateQuery' and no extension method 'CreateQuery' accepting a first argument of type 'CodeActivityContext' could be found (are you missing a using directive or an assembly reference?) Workflows C:\Users\tgiard\Downloads\GetUserByName-master\GetUserByName-master\Workflows\ModifiedBy.cs 68 Active
Error 2 :
Severity Code Description Project File Line Suppression State
Error CS0103 The name 'fullname' does not exist in the current context Workflows C:\Users\tgiard\Downloads\GetUserByName-master\GetUserByName-master\Workflows\ModifiedBy.cs 75 Active
Error 3 :
Severity Code Description Project File Line Suppression State
Error CS0103 The name 'context' does not exist in the current context Workflows C:\Users\tgiard\Downloads\GetUserByName-master\GetUserByName-master\Workflows\ModifiedBy.cs 79 Active
Here is some feedback on your issues:
Error 1 - 'CodeActivityContext' does not contain a definition for 'CreateQuery'
This issue is related to the lines:
var _contact = activityContext.CreateQuery("contact").Where(c => c.GetAttributeValue<Guid>("contactid").Equals(contactid)).FirstOrDefault();
and
Entity _user = context.CreateQuery("systemuser").Where(e => e.GetAttributeValue<string>("fullname").Equals(fullname)).FirstOrDefault();
I don't know what that method is but you have better options; for the contact you already have the guid, so you can simply use a Retrieve():
var _contact = orgService.Retrieve("contact", contactid, new ColumnSet("fullname"));
And for the system user write a QueryExpression filtering by fullname:
var query = new QueryExpression("systemuser"):
query.Criteria.AddCondition("fullname", ConditionOperator.Equal, fullname);
var _user = orgService.RetrieveMultiple(query).Entities.FirstOrDefault();
Error 2: The name 'fullname' does not exist in the current contex
This is basic C#, you must instantiate your variable before you use it:
string fullname;
Error 3: The name 'context' does not exist in the current context
Ironic and true. This should be activityContext, but we have already fixed this issue in the change we made for Error 1.
Entity _user = context.CreateQuery("systemuser").Where(e => e.GetAttributeValue<string>("fullname").Equals(fullname)).FirstOrDefault();
As Zach Mast correctly pointed out, using a Pre-Operation is recommended. It also seems an odd case where you retrieve a contacts name and match it with a user. Instead, You could change the type of the field to a user reference, add a user field to the contact you retrieve or add a code to match the Contact to the User. This way, you won't have issues with users with the same name or typo's.
Please find below your workflow activity converted to a Pre-Operation plugin.
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Linq;
namespace KED365.Plugins
{
public class CreateUpdateContact : IPlugin
{
public void Execute(IServiceProvider serviceProvider)
{
var tracingService = (ITracingService)serviceProvider.GetService(typeof(ITracingService));
var context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
var factory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
var service = factory.CreateOrganizationService(context.UserId);
tracingService.Trace("Start plugin");
tracingService.Trace("Validate Target");
if (!context.InputParameters.Contains("Target") || !(context.InputParameters["Target"] is Entity))
return;
tracingService.Trace("Retrieve Target");
var target = (Entity)context.InputParameters["Target"];
String message = context.MessageName.ToLower();
SetCreatedByAndModifiedBy(tracingService, service, target, message);
}
private void SetCreatedByAndModifiedBy(ITracingService tracingService, IOrganizationService service, Entity target, string message)
{
tracingService.Trace("Start SetPriceList");
tracingService.Trace("Validate Message is Create or Update");
if (!message.Equals("create", StringComparison.OrdinalIgnoreCase) && !message.Equals("update", StringComparison.OrdinalIgnoreCase))
return;
tracingService.Trace("Retrieve Attributes");
var createdByReference = target.GetAttributeValue<EntityReference>("new_createdby");
var modifiedByReference = target.GetAttributeValue<EntityReference>("new_modifiedby");
tracingService.Trace("Retrieve And Set User for Created By");
RetrieveAndSetUser(tracingService, service, target, createdByReference, "createdby");
tracingService.Trace("Retrieve And Set User for Modified By");
RetrieveAndSetUser(tracingService, service, target, modifiedByReference, "modifiedby");
}
private void RetrieveAndSetUser(ITracingService tracingService, IOrganizationService service, Entity target, EntityReference reference, string targetAttribute)
{
tracingService.Trace("Validating Reference");
if (reference == null)
return;
tracingService.Trace("Retrieving and Validating User");
var user = RetrieveUserByName(service, reference.Name, new ColumnSet(false));
if (user == null)
return;
tracingService.Trace("Setting Target Attribute");
target[targetAttribute] = user.ToEntityReference();
}
private Entity RetrieveUserByName(IOrganizationService service, string name, ColumnSet columns)
{
var query = new QueryExpression
{
EntityName = "systemuser",
ColumnSet = columns,
Criteria = new FilterExpression
{
FilterOperator = LogicalOperator.And,
Conditions =
{
new ConditionExpression
{
AttributeName = "fullname",
Operator = ConditionOperator.Equal,
Values = { name }
}
}
}
};
var retrieveResponse = service.RetrieveMultiple(query);
if (retrieveResponse.Entities.Count == 1)
{
return retrieveResponse.Entities.FirstOrDefault();
}
else
{
// Alternatively you can thrown an error as you have unexpectedly multiple matches
return null;
}
}
}
}
I would ask about how to get current date in workflows.?
For example:-
I have field called (Inspection Date) I would like to compare this filed if it equal current date then go into the process.
I will create Wait Condition waiting until current date = Inspection date then will do my process .
How to get current date in workflow.?
To answer the OP's question about how to get the current date in the workflow, the short answer is that you can't. As Henk van Boeijen has described, it is possible to get the current date in some of the individual steps however.
Where I work we have implemented a very basic custom workflow activity that simply returns the current date and time.
public class CurrentDateWorkflow : CodeActivity
{
protected override void Execute(CodeActivityContext executionContext)
{
try
{
// Create the context and tracing service
IExecutionContext context = executionContext.GetExtension<IExecutionContext>();
IOrganizationServiceFactory serviceFactory = executionContext.GetExtension<IOrganizationServiceFactory>();
IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
ITracingService tracingService = executionContext.GetExtension<ITracingService>();
if (tracingService == null)
throw new InvalidPluginExecutionException("Failed to retrieve tracing service.");
tracingService.Trace("Entered CurrentDateWorkflow.Execute(), Activity Instance Id: {0}, Workflow Instance Id: {1}",
executionContext.ActivityInstanceId,
executionContext.WorkflowInstanceId);
var DatePartOnly = InputDatePartOnly.Get(executionContext);
// Set output parameters
if (DatePartOnly)
CurrentDate.Set(executionContext, DateTime.UtcNow.Date);
else
CurrentDate.Set(executionContext, DateTime.UtcNow);
// All done
tracingService.Trace("CurrentDateWorkflow.Execute() Complete. Activity Instance Id: {0}, Workflow Instance Id: {1}",
executionContext.ActivityInstanceId,
executionContext.WorkflowInstanceId);
}
catch (Exception ex)
{
throw new InvalidPluginExecutionException(String.Format("An error occurred in the {0} plug-in.",
this.GetType().ToString()),
ex);
}
}
[Output("Current Date")]
public OutArgument<DateTime> CurrentDate { get; set; }
[Input("Date Only")]
[Default("False")]
public InArgument<bool> InputDatePartOnly { get; set; }
}
In window "Specify Condition" select field "Inspection Date" with condition "Is Greater Than or Equal To". In the Form Assistant expand picklist "Look for", select under "Local Values" the option "Process". In the box below the picklist "Execution Time" is displayed. Select it and you are done.
I get an exception
The specified table does not exist [Limits]
while I'm trying saving new item
(App.Current as App).context.Limits.InsertOnSubmit(new Limit() { Date = DateTime.Now, Value = inputLimit });//this works
(App.Current as App).context.SubmitChanges();//here I get exception
Also I get an error on this line:
var currentLimit = (App.Current as App).context.Limits.Where(l => l.Date.Date == DateTime.Now.Date).FirstOrDefault();
Here is a "model"
public class CalCounterContext:DataContext
{
public CalCounterContext(string connstring):base(connstring)
{
}
public Table<Limit> Limits;
public Table<Meal> Meals;
}
[Table]
public class Limit
{
[Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "Int NOT NULL IDENTITY", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
public int Id { get; set; }
[Column]
public DateTime Date { get; set; }
[Column]
public int Value { get; set; }
}
Sometimes it works, sometimes, doesn't. What could be a reson of my problem?
This normally happens when you add a table in a later version of the database then what is being used. When you create your database context, check to see if it is up to date, and if not, update the database using the DatabaseSchemaUpdater class as described here. If it is just while you are creating the app, uninstall and re-install the app.
Also, I ran into a strange issue where intermittently I would get this error even once the app was in production without any reasoning. Often is occured when I would launch the app and then hit the home or back button to end it quickly. I ended up re-implementing the GetTable<> function used to instantiate my ITable variable in a base database class so that it would do a hard check to see if the table actually existed:
public Table<TEntity> VerifyTable<TEntity>() where TEntity : class
{
var table = GetTable<TEntity>();
try
{
// can call any function against the table to verify it exists
table.Any();
}
catch (DbException exception)
{
if (exception.Message.StartsWith("The specified table does not exist."))
{
var databaseSchemaUpdater = this.CreateDatabaseSchemaUpdater();
databaseSchemaUpdater.AddTable<TEntity>();
databaseSchemaUpdater.Execute();
}
else
{
throw;
}
}
return table;
}
I had the same intermittent error you had. Try removing the database from the device and installing the app again. I found my issue was being caused because I was making changes to the model and when I re-ran the app, I would get this error.
I have a custom workflow activity that does get registered. However, when I go to add it to a workflow, I get a "The requested record was not found or you do not have permission sufficient permission to view it" error. I'm an admin and it was registered using the same user account. There is no information in the trace file. What could be causing this?
UPDATE: Please note that this is occurring not at runtime, but at design time. I.e. I can't actually add this activity to a workflow. When I try I get the above error.
UPDATE 2: I simplified my code to this and still get the same message:
using System;
using System.Workflow.ComponentModel;
using Microsoft.Crm.Sdk;
using Microsoft.Crm.Workflow;
using MicroFour.StrataFrame.Data;
namespace Fox.Crm.CustomWorkflowActivities
{
[CrmWorkflowActivity( "Get Entity Link", "Fox Tools" )]
public class GetEntityLinkActivity
: Activity
{
public static readonly DependencyProperty FullNameProperty = DependencyProperty.Register( "FullName"
, typeof( string )
, typeof( GetEntityLinkActivity ) );
[CrmInput( "FullName" )]
public string FullName
{
get { return (string)GetValue( FullNameProperty ); }
set { SetValue( FullNameProperty, value ); }
}
public static readonly DependencyProperty MessageProperty = DependencyProperty.Register( "Message"
, typeof( string )
, typeof( GetEntityLinkActivity ) );
[CrmOutput( "Message" )]
public string Message
{
get { return (string)GetValue( MessageProperty ); }
set { SetValue( MessageProperty, value ); }
}
protected override ActivityExecutionStatus Execute( ActivityExecutionContext executionContext )
{
this.Message = string.Format( "Hellow {0}", this.FullName );
//-- Return that we successfully determined URL and link.
return ActivityExecutionStatus.Closed;
}
}
}