Dynamics C# 插件在 运行 时失败,但在调试时成功
Dynamics C# Plugin fails when run, but succeeds when Debugging
概述
我在本地使用 Dynamics 2016。
我在 Microsoft Dynamics 中有一个业务流程来处理新客户端的创建。该过程完成后,我将附加一个工作流,该工作流启动一个调用插件进行一些自定义处理的操作。我正在关注 this 文章来设置此过程。当此插件在 Dynamics 中被触发时,它似乎 运行 成功,但没有创建我期望它创建的记录。但是,当我通过插件注册 Tool/Visual Studio 分析插件并 运行 它时,会创建我希望看到的记录。
当我将跟踪日志添加到我的插件时,我注意到当我调用 Web API 时似乎收到了来自 Dynamics 的 401 - Unauthorized
错误。当我在调试时查看网络流量时,我似乎收到了初始 401
错误,但随后重试成功获取了我试图获取的记录。
代码
这是我认为 401-Unauthorized
错误来自
的代码部分
private void GetGlobalFieldNameMapsAsync(String url = "ccseq_globalfieldnamemaps?$select=ccseq_system,ccseq_entitytype,ccseq_fieldtype,ccseq_name,ccseq_datatype")
{
HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential("admin", "password", "domain") });
HttpResponseMessage responseMessage = new HttpResponseMessage();
try
{
client.BaseAddress = new Uri(Helpers.GetSystemUrl(APIConnector.Application.Dynamics));
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
responseMessage = client.GetAsync(url).Result;
JObject responseData = JObject.Parse(responseMessage.Content.ReadAsStringAsync().Result);
if (responseData["@odata.nextLink"] != null)
{
GetGlobalFieldNameMapsAsync(Convert.ToString(responseData["@odata.nextLink"]));
}
foreach (var v in responseData["value"])
{
GlobalFieldNameMap newGFNM = new GlobalFieldNameMap();
newGFNM.System.Value = Convert.ToInt32(v["ccseq_system"]);
newGFNM.EntityType.Value = Convert.ToInt32(v["ccseq_entitytype"]);
newGFNM.FieldType.Value = Convert.ToInt32(v["ccseq_fieldtype"]);
newGFNM.FieldName.Value = Convert.ToString(v["ccseq_name"]);
newGFNM.DataType.Value = Convert.ToInt32(v["ccseq_datatype"]);
FieldNameMap.Add(newGFNM);
}
}
catch (Exception e)
{
throw new Exception(e.Message + " - " + responseMessage.Content.ReadAsStringAsync().Result);
}
}
网络流量
我似乎无法理解我是如何在调试过程中看到插件成功 运行,但是当直接在动态中 运行ning 时看到它失败。该插件似乎 运行ning 在同一用户下,无论它是 运行ning 在 Dynamics 中还是在我的本地计算机上。我正在传递管理员凭据,因此他们应该拥有在系统中执行任何操作的完全权限。有什么想法吗?
我问了 question and 个可能相关的问题,但没有完全涵盖这个问题。
更新
我在跟踪日志中注意到这条错误消息
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 8.5 Detailed Error - 401.1 - Unauthorized</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 5px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;word-break:break-all;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px;
font-weight:bold;font-size:1em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif;
color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF;
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal;
font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;}
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;}
-->
</style>
</head>
<body>
<div id="content">
<div class="content-container">
<h3>HTTP Error 401.1 - Unauthorized</h3>
<h4>You do not have permission to view this directory or page using the credentials that you supplied.</h4>
</div>
<div class="content-container">
<fieldset><h4>Most likely causes:</h4>
<ul> <li>The username supplied to IIS is invalid.</li> <li>The password supplied to IIS was not typed correctly. </li> <li>Incorrect credentials were cached by the browser.</li> <li>IIS could not verify the identity of the username and password provided.</li> <li>The resource is configured for Anonymous authentication, but the configured anonymous account either has an invalid password or was disabled.</li> <li>The server is configured to deny login privileges to the authenticating user or the group in which the user is a member.</li> <li>Invalid Kerberos configuration may be the cause if all of the following are true:</li> <ul> <li>Integrated authentication was used.</li> <li>the application pool identity is a custom account.</li> <li>the server is a member of a domain.</li> </ul> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Things you can try:</h4>
<ul> <li>Verify that the username and password are correct, and are not cached by the browser.</li> <li>Use a different username and password.</li> <li>If you are using a custom anonymous account, verify that the password has not expired.</li> <li>Verify that the authenticating user or the user's group, has not been denied login access to the server.</li> <li>Verify that the account was not locked out due to numerous failed login attempts.</li> <li>If you are using authentication and the server is a member of a domain, verify that you have configured the application pool identity using the utility SETSPN.exe, or changed the configuration so that NTLM is the favored authentication type.</li> <li>Create a tracing rule to track failed requests for this HTTP status code. For more information about creating a tracing rule for failed requests, click <a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>. </li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Detailed Error Information:</h4>
<div id="details-left">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Module</th><td> WindowsAuthenticationModule</td></tr>
<tr><th>Notification</th><td> AuthenticateRequest</td></tr>
<tr class="alt"><th>Handler</th><td> ExtensionlessUrlHandler-Integrated-4.0</td></tr>
<tr><th>Error Code</th><td> 0xc000006d</td></tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Requested URL</th><td> https://crminternal.cohencpa.com:443/COHEN/api/data/v8.2/ccseq_globalfieldnamemaps?$select=ccseq_system,ccseq_entitytype,ccseq_fieldtype,ccseq_name,ccseq_datatype</td></tr>
<tr><th>Physical Path</th><td> C:\Program Files\Microsoft Dynamics CRM\CRMWeb\COHEN\api\data\v8.2\ccseq_globalfieldnamemaps</td></tr>
<tr class="alt"><th>Logon Method</th><td> Not yet determined</td></tr>
<tr><th>Logon User</th><td> Not yet determined</td></tr>
</table>
<div class="clear"></div>
</div>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>More Information:</h4>
This error occurs when either the username or password supplied to IIS is invalid, or when IIS cannot use the username and password to authenticate the user.
<p><a href="http://go.microsoft.com/fwlink/?LinkID=62293&IIS70Error=401,1,0xc000006d,9600">View more information »</a></p>
<p>Microsoft Knowledge Base Articles:</p>
<ul><li>907273</li><li>871179</li><li>896861</li></ul>
</fieldset>
</div>
</div>
</body>
</html>
我认为这里的答案是不要在插件中使用 Web API。
Web API
Use the Web API for any projects that access Dynamics 365 data with
code that doesn’t run on the server, including requests from web
resources and form scripts that run in Dynamics 365 application
clients. At this time you can’t easily use the Web API for code that
runs on the server, such as in plug-ins or workflow assemblies.
Organization service
Business logic that runs in plug-ins or workflow assemblies on the server expect to use the Organization service.
至于为什么您的插件跟踪日志中出现 401 - Unauthorized
。我怀疑这可能是因为您正在尝试让 CRM 自行调用,而它根本无法进行身份验证。无论如何,插件 Web Access 在这方面非常有限。
The following web access restrictions apply to this sandbox capability.
- Anonymous authentication is supported and recommended.
关于插件在调试时工作的原因,我猜是因为 HTTP 请求现在是从您的本地计算机而不是服务器发送的。我假设 Fiddler 日志来自您的机器。
终于调试成功了,最初的401接着就是成功;我相信 401 是一种凭据挑战,在许多身份验证方案中 common。
在调查 401.1 Unauthorized
错误时,我看到了 this 文章。这是相关的文章:
When you use the fully qualified domain name (FQDN) or a custom host header to browse a local Web site that is hosted on a computer that is running Microsoft Internet Information Services (IIS) 5.1 or a later version, you may receive an error message that resembles the following:
HTTP 401.1 - Unauthorized: Logon Failed
This issue occurs when the Web site uses Integrated Authentication and has a name that is mapped to the local loopback address.
Note You only receive this error message if you try to browse the Web site directly on the server. If you browse the Web site from a client computer, the Web site works as expected.
文章提供了几种解决问题的方法,但这里是对我们有用的方法(必须在服务器上完成):
- 使用 regedit 导航到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters 并添加名为 DisableStrictNameChecking(REG-DWORD,十进制)的值为 1
- 使用 regedit 导航至 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 并添加名为 BackConnectionHostNames 的多字符串值,其值为您的网络主机名 api 端点
- 打开命令行并输入 iisreset(必须 运行 作为管理员)
- 重启服务器
概述
我在本地使用 Dynamics 2016。
我在 Microsoft Dynamics 中有一个业务流程来处理新客户端的创建。该过程完成后,我将附加一个工作流,该工作流启动一个调用插件进行一些自定义处理的操作。我正在关注 this 文章来设置此过程。当此插件在 Dynamics 中被触发时,它似乎 运行 成功,但没有创建我期望它创建的记录。但是,当我通过插件注册 Tool/Visual Studio 分析插件并 运行 它时,会创建我希望看到的记录。
当我将跟踪日志添加到我的插件时,我注意到当我调用 Web API 时似乎收到了来自 Dynamics 的 401 - Unauthorized
错误。当我在调试时查看网络流量时,我似乎收到了初始 401
错误,但随后重试成功获取了我试图获取的记录。
代码
这是我认为 401-Unauthorized
错误来自
private void GetGlobalFieldNameMapsAsync(String url = "ccseq_globalfieldnamemaps?$select=ccseq_system,ccseq_entitytype,ccseq_fieldtype,ccseq_name,ccseq_datatype")
{
HttpClient client = new HttpClient(new HttpClientHandler() { Credentials = new NetworkCredential("admin", "password", "domain") });
HttpResponseMessage responseMessage = new HttpResponseMessage();
try
{
client.BaseAddress = new Uri(Helpers.GetSystemUrl(APIConnector.Application.Dynamics));
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Add("OData-MaxVersion", "4.0");
client.DefaultRequestHeaders.Add("OData-Version", "4.0");
responseMessage = client.GetAsync(url).Result;
JObject responseData = JObject.Parse(responseMessage.Content.ReadAsStringAsync().Result);
if (responseData["@odata.nextLink"] != null)
{
GetGlobalFieldNameMapsAsync(Convert.ToString(responseData["@odata.nextLink"]));
}
foreach (var v in responseData["value"])
{
GlobalFieldNameMap newGFNM = new GlobalFieldNameMap();
newGFNM.System.Value = Convert.ToInt32(v["ccseq_system"]);
newGFNM.EntityType.Value = Convert.ToInt32(v["ccseq_entitytype"]);
newGFNM.FieldType.Value = Convert.ToInt32(v["ccseq_fieldtype"]);
newGFNM.FieldName.Value = Convert.ToString(v["ccseq_name"]);
newGFNM.DataType.Value = Convert.ToInt32(v["ccseq_datatype"]);
FieldNameMap.Add(newGFNM);
}
}
catch (Exception e)
{
throw new Exception(e.Message + " - " + responseMessage.Content.ReadAsStringAsync().Result);
}
}
网络流量
我似乎无法理解我是如何在调试过程中看到插件成功 运行,但是当直接在动态中 运行ning 时看到它失败。该插件似乎 运行ning 在同一用户下,无论它是 运行ning 在 Dynamics 中还是在我的本地计算机上。我正在传递管理员凭据,因此他们应该拥有在系统中执行任何操作的完全权限。有什么想法吗?
我问了
更新
我在跟踪日志中注意到这条错误消息
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>IIS 8.5 Detailed Error - 401.1 - Unauthorized</title>
<style type="text/css">
<!--
body{margin:0;font-size:.7em;font-family:Verdana,Arial,Helvetica,sans-serif;}
code{margin:0;color:#006600;font-size:1.1em;font-weight:bold;}
.config_source code{font-size:.8em;color:#000000;}
pre{margin:0;font-size:1.4em;word-wrap:break-word;}
ul,ol{margin:10px 0 10px 5px;}
ul.first,ol.first{margin-top:5px;}
fieldset{padding:0 15px 10px 15px;word-break:break-all;}
.summary-container fieldset{padding-bottom:5px;margin-top:4px;}
legend.no-expand-all{padding:2px 15px 4px 10px;margin:0 0 0 -12px;}
legend{color:#333333;;margin:4px 0 8px -12px;_margin-top:0px;
font-weight:bold;font-size:1em;}
a:link,a:visited{color:#007EFF;font-weight:bold;}
a:hover{text-decoration:none;}
h1{font-size:2.4em;margin:0;color:#FFF;}
h2{font-size:1.7em;margin:0;color:#CC0000;}
h3{font-size:1.4em;margin:10px 0 0 0;color:#CC0000;}
h4{font-size:1.2em;margin:10px 0 5px 0;
}#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:"trebuchet MS",Verdana,sans-serif;
color:#FFF;background-color:#5C87B2;
}#content{margin:0 0 0 2%;position:relative;}
.summary-container,.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}
.content-container p{margin:0 0 10px 0;
}#details-left{width:35%;float:left;margin-right:2%;
}#details-right{width:63%;float:left;overflow:hidden;
}#server_version{width:96%;_height:1px;min-height:1px;margin:0 0 5px 0;padding:11px 2% 8px 2%;color:#FFFFFF;
background-color:#5A7FA5;border-bottom:1px solid #C1CFDD;border-top:1px solid #4A6C8E;font-weight:normal;
font-size:1em;color:#FFF;text-align:right;
}#server_version p{margin:5px 0;}
table{margin:4px 0 4px 0;width:100%;border:none;}
td,th{vertical-align:top;padding:3px 0;text-align:left;font-weight:normal;border:none;}
th{width:30%;text-align:right;padding-right:2%;font-weight:bold;}
thead th{background-color:#ebebeb;width:25%;
}#details-right th{width:20%;}
table tr.alt td,table tr.alt th{}
.highlight-code{color:#CC0000;font-weight:bold;font-style:italic;}
.clear{clear:both;}
.preferred{padding:0 5px 2px 5px;font-weight:normal;background:#006633;color:#FFF;font-size:.8em;}
-->
</style>
</head>
<body>
<div id="content">
<div class="content-container">
<h3>HTTP Error 401.1 - Unauthorized</h3>
<h4>You do not have permission to view this directory or page using the credentials that you supplied.</h4>
</div>
<div class="content-container">
<fieldset><h4>Most likely causes:</h4>
<ul> <li>The username supplied to IIS is invalid.</li> <li>The password supplied to IIS was not typed correctly. </li> <li>Incorrect credentials were cached by the browser.</li> <li>IIS could not verify the identity of the username and password provided.</li> <li>The resource is configured for Anonymous authentication, but the configured anonymous account either has an invalid password or was disabled.</li> <li>The server is configured to deny login privileges to the authenticating user or the group in which the user is a member.</li> <li>Invalid Kerberos configuration may be the cause if all of the following are true:</li> <ul> <li>Integrated authentication was used.</li> <li>the application pool identity is a custom account.</li> <li>the server is a member of a domain.</li> </ul> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Things you can try:</h4>
<ul> <li>Verify that the username and password are correct, and are not cached by the browser.</li> <li>Use a different username and password.</li> <li>If you are using a custom anonymous account, verify that the password has not expired.</li> <li>Verify that the authenticating user or the user's group, has not been denied login access to the server.</li> <li>Verify that the account was not locked out due to numerous failed login attempts.</li> <li>If you are using authentication and the server is a member of a domain, verify that you have configured the application pool identity using the utility SETSPN.exe, or changed the configuration so that NTLM is the favored authentication type.</li> <li>Create a tracing rule to track failed requests for this HTTP status code. For more information about creating a tracing rule for failed requests, click <a href="http://go.microsoft.com/fwlink/?LinkID=66439">here</a>. </li> </ul>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>Detailed Error Information:</h4>
<div id="details-left">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Module</th><td> WindowsAuthenticationModule</td></tr>
<tr><th>Notification</th><td> AuthenticateRequest</td></tr>
<tr class="alt"><th>Handler</th><td> ExtensionlessUrlHandler-Integrated-4.0</td></tr>
<tr><th>Error Code</th><td> 0xc000006d</td></tr>
</table>
</div>
<div id="details-right">
<table border="0" cellpadding="0" cellspacing="0">
<tr class="alt"><th>Requested URL</th><td> https://crminternal.cohencpa.com:443/COHEN/api/data/v8.2/ccseq_globalfieldnamemaps?$select=ccseq_system,ccseq_entitytype,ccseq_fieldtype,ccseq_name,ccseq_datatype</td></tr>
<tr><th>Physical Path</th><td> C:\Program Files\Microsoft Dynamics CRM\CRMWeb\COHEN\api\data\v8.2\ccseq_globalfieldnamemaps</td></tr>
<tr class="alt"><th>Logon Method</th><td> Not yet determined</td></tr>
<tr><th>Logon User</th><td> Not yet determined</td></tr>
</table>
<div class="clear"></div>
</div>
</fieldset>
</div>
<div class="content-container">
<fieldset><h4>More Information:</h4>
This error occurs when either the username or password supplied to IIS is invalid, or when IIS cannot use the username and password to authenticate the user.
<p><a href="http://go.microsoft.com/fwlink/?LinkID=62293&IIS70Error=401,1,0xc000006d,9600">View more information »</a></p>
<p>Microsoft Knowledge Base Articles:</p>
<ul><li>907273</li><li>871179</li><li>896861</li></ul>
</fieldset>
</div>
</div>
</body>
</html>
我认为这里的答案是不要在插件中使用 Web API。
Web API
Use the Web API for any projects that access Dynamics 365 data with code that doesn’t run on the server, including requests from web resources and form scripts that run in Dynamics 365 application clients. At this time you can’t easily use the Web API for code that runs on the server, such as in plug-ins or workflow assemblies.
Organization service
Business logic that runs in plug-ins or workflow assemblies on the server expect to use the Organization service.
至于为什么您的插件跟踪日志中出现 401 - Unauthorized
。我怀疑这可能是因为您正在尝试让 CRM 自行调用,而它根本无法进行身份验证。无论如何,插件 Web Access 在这方面非常有限。
The following web access restrictions apply to this sandbox capability.
- Anonymous authentication is supported and recommended.
关于插件在调试时工作的原因,我猜是因为 HTTP 请求现在是从您的本地计算机而不是服务器发送的。我假设 Fiddler 日志来自您的机器。
终于调试成功了,最初的401接着就是成功;我相信 401 是一种凭据挑战,在许多身份验证方案中 common。
在调查 401.1 Unauthorized
错误时,我看到了 this 文章。这是相关的文章:
When you use the fully qualified domain name (FQDN) or a custom host header to browse a local Web site that is hosted on a computer that is running Microsoft Internet Information Services (IIS) 5.1 or a later version, you may receive an error message that resembles the following:
HTTP 401.1 - Unauthorized: Logon Failed
This issue occurs when the Web site uses Integrated Authentication and has a name that is mapped to the local loopback address.
Note You only receive this error message if you try to browse the Web site directly on the server. If you browse the Web site from a client computer, the Web site works as expected.
文章提供了几种解决问题的方法,但这里是对我们有用的方法(必须在服务器上完成):
- 使用 regedit 导航到 HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\LanmanServer\Parameters 并添加名为 DisableStrictNameChecking(REG-DWORD,十进制)的值为 1
- 使用 regedit 导航至 HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Lsa\MSV1_0 并添加名为 BackConnectionHostNames 的多字符串值,其值为您的网络主机名 api 端点
- 打开命令行并输入 iisreset(必须 运行 作为管理员)
- 重启服务器