Java 和 MS CRM 2016 Web API 更新
Java and MS CRM 2016 Web API Updates
我有一个 java 应用程序,我正在尝试通过 crm 网络 api 更新商机。当我尝试使用像 PATCH 这样的非标准 HTTP 方法(这是更新所必需的)并用 "X-HTTP-Method-Override" 覆盖它时,就像我在各种示例代码中发现的那样,它不起作用。
商机更新代码:
public int updateOpportunity(OpportunityDaoModel model) throws IOException, URISyntaxException {
JSONObject opportunity = new JSONObject();
opportunity.put("name", model.getTopic());
HttpURLConnection connection = null;
URL url = new URL(RESOURCE + "/api/data/"+API_VERSION+"/opportunities(" + model.getCrmguid() + ")");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-HTTP-Method-Override", "PATCH");
connection.setRequestProperty("OData-MaxVersion", "4.0");
connection.setRequestProperty("OData-Version", "4.0");
connection.setRequestProperty("Accept", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + token);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(opportunity.toString());
out.flush();
out.close();
int responseCode = connection.getResponseCode();
return responseCode;
}
执行此方法后出现以下错误:
{
"error":{
"code":"","message":"Unmapped Request found, PathTemplate:~/entityset/key, HttpVerb:POST","innererror":{
"message":"Unmapped Request found, PathTemplate:~/entityset/key, HttpVerb:POST","type":"Microsoft.Crm.CrmHttpException","stacktrace":" at Microsoft.Crm.Extensibility.OData.EntityController.HandleUnmappedRequest(ODataPath path)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
在网络上找不到关于此错误的任何信息后,我尝试了一个不同的条目并希望通过 PUT 使用单个属性更新。这对于普通属性(如许多实体上的名称属性)是成功的,但是当我尝试更新查找字段时,我得到了一个不同的错误。但首先我的方法:
单个属性更新代码:
public int updateAttribute(String entity, String id, String attribute, String value) throws IOException, URISyntaxException {
JSONObject opportunity = new JSONObject();
HttpURLConnection connection = null;
String urlString = "";
if(attribute.contains("@odata.bind")) { // lookup value
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")";
opportunity.put(attribute, value);
} else { // text value
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")/" + attribute;
opportunity.put("value", value);
}
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setRequestProperty("OData-MaxVersion", "4.0");
connection.setRequestProperty("OData-Version", "4.0");
connection.setRequestProperty("Accept", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + token);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(opportunity.toString());
out.flush();
out.close();
int responseCode = connection.getResponseCode();
return responseCode;
}
我通过
调用这个方法
updateAttribute("opportunities", model.getCrmguid(), "lookupentityid@odata.bind", "/entityendpointwiths("+model.getProgress()+")");
错误信息:
{
"error":{
"code":"","message":"Operation not supported on opportunity","innererror":{
"message":"Operation not supported on opportunity","type":"Microsoft.Crm.CrmHttpException","stacktrace":" at Microsoft.Crm.Extensibility.OData.EntityController.PutEntity(String entityName, String key, EdmEntityObject entity)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
感谢您的帮助。
亲切的问候,丹尼斯
如果其他人处于这个位置,我很乐意向您展示我的答案。而不是使用 x-http-override header 你应该使用 java.
的 HTTPPatch-Class
方法:
public String updateAttribute(String entity, String id, List<Map<String, Object>> parameters) throws IOException, URISyntaxException {
JSONObject object = new JSONObject();
for (Map<String, Object> map : parameters) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
object.put(key, value);
}
}
String urlString = "";
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")/";
StringEntity stringEntity = new StringEntity(object.toString());
URL url = new URL(urlString);
HttpPatch httpPatch = new HttpPatch(urlString);
httpPatch.addHeader("OData-MaxVersion", "4.0");
httpPatch.addHeader("OData-Version", "4.0");
httpPatch.addHeader("Accept", "application/json");
httpPatch.addHeader("Authorization", "Bearer " + token);
httpPatch.addHeader("Content-Type", "application/json");
httpPatch.setEntity(stringEntity);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpResponse httpResponse = httpClient.execute(httpPatch);
int responseCode = httpResponse.getStatusLine().getStatusCode();
if (responseCode > 299) {
InputStream inputStream = httpResponse.getEntity().getContent();
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
throw new IOException(result.toString("UTF-8"));
}
return responseCode;
}
通过以下方式调用方法:
List<Map<String,Object>> opportunityParameterList = new ArrayList<>();
Map<String, Object> opportunityParameters = new HashMap<>();
opportunityParameters.put("name", opportunityDaoModel.getTopic());
opportunityParameters.put("lookupfield@odata.bind", "/lookupentityendpoint("+opportunityDaoModel.getProgress()+")");
opportunityParameterList.add(opportunityParameters);
this.crmHelper.updateAttribute("opportunities", opportunityDaoModel.getCrmguid(), opportunityParameterList);
我有一个 java 应用程序,我正在尝试通过 crm 网络 api 更新商机。当我尝试使用像 PATCH 这样的非标准 HTTP 方法(这是更新所必需的)并用 "X-HTTP-Method-Override" 覆盖它时,就像我在各种示例代码中发现的那样,它不起作用。
商机更新代码:
public int updateOpportunity(OpportunityDaoModel model) throws IOException, URISyntaxException {
JSONObject opportunity = new JSONObject();
opportunity.put("name", model.getTopic());
HttpURLConnection connection = null;
URL url = new URL(RESOURCE + "/api/data/"+API_VERSION+"/opportunities(" + model.getCrmguid() + ")");
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("POST");
connection.setRequestProperty("X-HTTP-Method-Override", "PATCH");
connection.setRequestProperty("OData-MaxVersion", "4.0");
connection.setRequestProperty("OData-Version", "4.0");
connection.setRequestProperty("Accept", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + token);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(opportunity.toString());
out.flush();
out.close();
int responseCode = connection.getResponseCode();
return responseCode;
}
执行此方法后出现以下错误:
{
"error":{
"code":"","message":"Unmapped Request found, PathTemplate:~/entityset/key, HttpVerb:POST","innererror":{
"message":"Unmapped Request found, PathTemplate:~/entityset/key, HttpVerb:POST","type":"Microsoft.Crm.CrmHttpException","stacktrace":" at Microsoft.Crm.Extensibility.OData.EntityController.HandleUnmappedRequest(ODataPath path)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
在网络上找不到关于此错误的任何信息后,我尝试了一个不同的条目并希望通过 PUT 使用单个属性更新。这对于普通属性(如许多实体上的名称属性)是成功的,但是当我尝试更新查找字段时,我得到了一个不同的错误。但首先我的方法:
单个属性更新代码:
public int updateAttribute(String entity, String id, String attribute, String value) throws IOException, URISyntaxException {
JSONObject opportunity = new JSONObject();
HttpURLConnection connection = null;
String urlString = "";
if(attribute.contains("@odata.bind")) { // lookup value
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")";
opportunity.put(attribute, value);
} else { // text value
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")/" + attribute;
opportunity.put("value", value);
}
URL url = new URL(urlString);
connection = (HttpURLConnection) url.openConnection();
connection.setRequestMethod("PUT");
connection.setRequestProperty("OData-MaxVersion", "4.0");
connection.setRequestProperty("OData-Version", "4.0");
connection.setRequestProperty("Accept", "application/json");
connection.addRequestProperty("Authorization", "Bearer " + token);
connection.setUseCaches(false);
connection.setRequestProperty("Content-Type", "application/json");
connection.setDoOutput(true);
connection.connect();
OutputStreamWriter out = new OutputStreamWriter(connection.getOutputStream());
out.write(opportunity.toString());
out.flush();
out.close();
int responseCode = connection.getResponseCode();
return responseCode;
}
我通过
调用这个方法 updateAttribute("opportunities", model.getCrmguid(), "lookupentityid@odata.bind", "/entityendpointwiths("+model.getProgress()+")");
错误信息:
{
"error":{
"code":"","message":"Operation not supported on opportunity","innererror":{
"message":"Operation not supported on opportunity","type":"Microsoft.Crm.CrmHttpException","stacktrace":" at Microsoft.Crm.Extensibility.OData.EntityController.PutEntity(String entityName, String key, EdmEntityObject entity)\r\n at lambda_method(Closure , Object , Object[] )\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ActionExecutor.<>c__DisplayClass10.<GetExecutor>b__9(Object instance, Object[] methodParameters)\r\n at System.Web.Http.Controllers.ReflectedHttpActionDescriptor.ExecuteAsync(HttpControllerContext controllerContext, IDictionary`2 arguments, CancellationToken cancellationToken)\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.<InvokeActionAsyncCore>d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.<ExecuteAsync>d__2.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.<SendAsync>d__1.MoveNext()"
}
}
}
感谢您的帮助。
亲切的问候,丹尼斯
如果其他人处于这个位置,我很乐意向您展示我的答案。而不是使用 x-http-override header 你应该使用 java.
的 HTTPPatch-Class方法:
public String updateAttribute(String entity, String id, List<Map<String, Object>> parameters) throws IOException, URISyntaxException {
JSONObject object = new JSONObject();
for (Map<String, Object> map : parameters) {
for (Map.Entry<String, Object> entry : map.entrySet()) {
String key = entry.getKey();
Object value = entry.getValue();
object.put(key, value);
}
}
String urlString = "";
urlString = RESOURCE + "/api/data/"+API_VERSION+"/"+entity+"(" + id + ")/";
StringEntity stringEntity = new StringEntity(object.toString());
URL url = new URL(urlString);
HttpPatch httpPatch = new HttpPatch(urlString);
httpPatch.addHeader("OData-MaxVersion", "4.0");
httpPatch.addHeader("OData-Version", "4.0");
httpPatch.addHeader("Accept", "application/json");
httpPatch.addHeader("Authorization", "Bearer " + token);
httpPatch.addHeader("Content-Type", "application/json");
httpPatch.setEntity(stringEntity);
CloseableHttpClient httpClient = HttpClients.createDefault();
HttpResponse httpResponse = httpClient.execute(httpPatch);
int responseCode = httpResponse.getStatusLine().getStatusCode();
if (responseCode > 299) {
InputStream inputStream = httpResponse.getEntity().getContent();
ByteArrayOutputStream result = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int length;
while ((length = inputStream.read(buffer)) != -1) {
result.write(buffer, 0, length);
}
throw new IOException(result.toString("UTF-8"));
}
return responseCode;
}
通过以下方式调用方法:
List<Map<String,Object>> opportunityParameterList = new ArrayList<>();
Map<String, Object> opportunityParameters = new HashMap<>();
opportunityParameters.put("name", opportunityDaoModel.getTopic());
opportunityParameters.put("lookupfield@odata.bind", "/lookupentityendpoint("+opportunityDaoModel.getProgress()+")");
opportunityParameterList.add(opportunityParameters);
this.crmHelper.updateAttribute("opportunities", opportunityDaoModel.getCrmguid(), opportunityParameterList);