CRM 2011 - 字典中不存在给定密钥 - 更新联系人插件

发布于 2024-11-10 12:28:24 字数 2430 浏览 3 评论 0原文

我正在尝试将插件绑定到 Microsoft Dynamics CRM 2011 中的更新联系人事件。 我已经制作了一个插件,并且已经为我的组织注册了程序集和步骤。

屏幕截图: CRM 注册工具

目前,我正在使用示例代码插件。

public class Plugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)
        serviceProvider.GetService(typeof(IPluginExecutionContext));

    Entity entity;

    // Check if the input parameters property bag contains a target
    // of the create operation and that target is of type Entity.
    if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
    {
        // Obtain the target business entity from the input parameters.
        entity = (Entity)context.InputParameters["Target"];

        // Verify that the entity represents a contact.
        if (entity.LogicalName != "contact") { return; }
    }
    else
    {
        return;
    }

    try
    {
        IOrganizationServiceFactory serviceFactory =
            (IOrganizationServiceFactory)serviceProvider.GetService(
        typeof(IOrganizationServiceFactory));
        IOrganizationService service =
        serviceFactory.CreateOrganizationService(context.UserId);

        var id = (Guid)context.OutputParameters["id"];

        AddNoteToContact(service, id);
    }
    catch (FaultException<OrganizationServiceFault> ex)
    {
        throw new InvalidPluginExecutionException(
        "An error occurred in the plug-in.", ex);
    }
}

private static void AddNoteToContact(IOrganizationService service, Guid id)
{
    using (var crm = new XrmServiceContext(service))
    {

        var contact = crm.ContactSet.Where(
        c => c.ContactId == id).First();
        Debug.Write(contact.FirstName);

        var note = new Annotation
        {
            Subject = "Created with plugin",
            NoteText = "This Note was created by the example plug-in",
            ObjectId = contact.ToEntityReference(),
            ObjectTypeCode = contact.LogicalName
        };

        crm.AddObject(note);
        crm.SaveChanges();
    }

}
}

但每次我修改联系表单并保存它时,我都会收到此错误:

The given key was not present in the dictionary

我已经寻找答案一周了。我希望这里有人可以指导我解决这个问题。我可以提供您需要的所有代码或信息。但现在,我想不出更多可以帮助您查看我的错误所在的内容。非常感谢任何帮助。

谢谢!

I'm trying to bind a plugin to the update contact event in Microsoft Dynamics CRM 2011.
I've made a plugin and i already registered the assembly and step for my organisation.

screenshot: CRM registration tool

For this moment, i'm using sample code for my plugin.

public class Plugin : IPlugin
{
    public void Execute(IServiceProvider serviceProvider)
    {
        IPluginExecutionContext context = (IPluginExecutionContext)
        serviceProvider.GetService(typeof(IPluginExecutionContext));

    Entity entity;

    // Check if the input parameters property bag contains a target
    // of the create operation and that target is of type Entity.
    if (context.InputParameters.Contains("Target") &&
    context.InputParameters["Target"] is Entity)
    {
        // Obtain the target business entity from the input parameters.
        entity = (Entity)context.InputParameters["Target"];

        // Verify that the entity represents a contact.
        if (entity.LogicalName != "contact") { return; }
    }
    else
    {
        return;
    }

    try
    {
        IOrganizationServiceFactory serviceFactory =
            (IOrganizationServiceFactory)serviceProvider.GetService(
        typeof(IOrganizationServiceFactory));
        IOrganizationService service =
        serviceFactory.CreateOrganizationService(context.UserId);

        var id = (Guid)context.OutputParameters["id"];

        AddNoteToContact(service, id);
    }
    catch (FaultException<OrganizationServiceFault> ex)
    {
        throw new InvalidPluginExecutionException(
        "An error occurred in the plug-in.", ex);
    }
}

private static void AddNoteToContact(IOrganizationService service, Guid id)
{
    using (var crm = new XrmServiceContext(service))
    {

        var contact = crm.ContactSet.Where(
        c => c.ContactId == id).First();
        Debug.Write(contact.FirstName);

        var note = new Annotation
        {
            Subject = "Created with plugin",
            NoteText = "This Note was created by the example plug-in",
            ObjectId = contact.ToEntityReference(),
            ObjectTypeCode = contact.LogicalName
        };

        crm.AddObject(note);
        crm.SaveChanges();
    }

}
}

But every time i modify a contact form and save it, i get this error:

The given key was not present in the dictionary

I've been looking for answers for a week now. I hope there is someone here who can guide me to the sollution for this problem. I can give every code or information you need. But for now, i can't think of anything more that maybe can help you to see where my error is located. Any help is very much appreciated.

Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

勿挽旧人 2024-11-17 12:28:24

如果插件注册为前置步骤,OutputParameters 将不包含键“id”,并且会抛出该错误。

If the plugin is registered as a pre step, OutputParameters will not contain the key "id" and it will throw that error.

嘿看小鸭子会跑 2024-11-17 12:28:24

M.Medhat 是绝对正确的,但让我们进一步扩展一下,以便您理解。

您需要了解的第一件事是输入参数与输出参数之间的区别。快速阅读这篇描述 InputParameters 和 OutputParameters 之间差异的 MSDN 文章

请务必注意此声明:

如果为预事件注册了插件,则 OutputParameters 属性包将不包含“id”键的值,因为核心操作尚未发生。

因此,这段代码会中断:

var id = (Guid)context.OutputParameters["id"];

由于您已经创建了一个实体(通过将其从 InputParameters 中转换出来),您可以删除该行并执行如下操作:

AddNoteToContact(service, entity.id);

不要忘记跟踪,它是您最好的朋友。它可以在抛出异常时显示信息。这是一个很好的链接:跟踪

M.Medhat is absolutely correct, but let's expand on it a bit more so you understand.

The first thing that you need to know is the difference between InputParameters vrs OutputParameters. A quick read at this MSDN article describing the difference between InputParameters and OutputParameters.

Make sure to note this statement:

If a plug-in is registered for a pre-event, the OutputParameters property bag would not contain a value for the "id" key because the core operation would not yet have occurred.

Hence, this code would break:

var id = (Guid)context.OutputParameters["id"];

Since you've already created an entity (by casting it off of InputParameters) you could delete that line and do something like this:

AddNoteToContact(service, entity.id);

Don't forget about tracing, it's your best friend. It can show information when an exception is thrown. Here's a good link on it: tracing

爱情眠于流年 2024-11-17 12:28:24

这是我用来帮助显示插件在为给定消息和目标实体注册时接收的所有参数的一些代码,使用它来找出存在的键

如果您不太愿意深入研究文档来查看“应该”存在什么,而只是尝试看看实际发生的情况,只需将其放入您的插件中,注册您打算使用的步骤,它就会准确地显示哪些参数为该步骤提供了。

var propertiesList = String.Join("\n", 
        context.InputParameters.Select((p,i)=>ParamSelector(p,i,"Input")).Union(
        context.InputParameters.Select((p,i)=>ParamSelector(p,i,"Output"))));

//send the list to the tracing service.
context.Trace("Listing Inputput and Output Parameters for the plugin.\n" + propertiesList);

// throw an exception to see the trace values pop-up (in a synchronous plugin).
throw new InvalidPluginExecutionException("Check the trace for a listing of parameters.");

支持代表格式化:

private string ParamSelector(KeyValuePair<string, object> p, int index, string inOut) 
{  
    return String.Format("{2} \tKey:'{0}'\tValue:{1}\n{3}", p.Key, p.Value, inOut, EntityToTraceStrings(p.Value as Entity));    
}

private string EntityToTraceStrings(Entity entity)
{
    return entity == null ? String.Empty : String.Concat(
        String.Format("- Entity: {0} Id: {1}\n\t", entity.LogicalName, entity.Id),
        String.Join("\n\t", entity.FormattedValues.Select((p, j) => String.Format("Attribute: {0} \t Value: {1}", p.Key, p.Value))));
}

Here is some code I use to help show all the parameters the plugin receives when registered for a given message and target entity, use it to find out what keys are present.

If you are less inclined to dig through documentation to see what "should" be there, than to just try and see what actually happens, simply put this in your plugin, register the step you intend to use and it will show you exactly what params were provided for that step.

var propertiesList = String.Join("\n", 
        context.InputParameters.Select((p,i)=>ParamSelector(p,i,"Input")).Union(
        context.InputParameters.Select((p,i)=>ParamSelector(p,i,"Output"))));

//send the list to the tracing service.
context.Trace("Listing Inputput and Output Parameters for the plugin.\n" + propertiesList);

// throw an exception to see the trace values pop-up (in a synchronous plugin).
throw new InvalidPluginExecutionException("Check the trace for a listing of parameters.");

supporting delegates for formatting:

private string ParamSelector(KeyValuePair<string, object> p, int index, string inOut) 
{  
    return String.Format("{2} \tKey:'{0}'\tValue:{1}\n{3}", p.Key, p.Value, inOut, EntityToTraceStrings(p.Value as Entity));    
}

private string EntityToTraceStrings(Entity entity)
{
    return entity == null ? String.Empty : String.Concat(
        String.Format("- Entity: {0} Id: {1}\n\t", entity.LogicalName, entity.Id),
        String.Join("\n\t", entity.FormattedValues.Select((p, j) => String.Format("Attribute: {0} \t Value: {1}", p.Key, p.Value))));
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文