How do you set the state and status of an email object using a SOAP call? - soap

I am really struggling to solve this. I have trawled the web and found some examples of how to set the state and status of an object, but none of them seem to work for me.
Does anyone have some example of how the soap envelope should look and what the properties of the Msxml2.XMLHTTP object should be for a synchronous call to the web service?
Thanks in advance,
Gray
EDIT
Ok ... so for an unexplained reason I got a downvote on this, and no answer, so I thought I would describe what I have currently got, and what I am getting.
This is the main function (pretty much lifted from one of the examples I found:
function setStateCodeForEntity(entityName, entityId, stateOptionsetValue, statusOptionsetValue) {
var request = "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
request += "<s:Body>";
request += "<Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
request += "<request i:type=\"b:SetStateRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\" xmlns:b=\"http://schemas.microsoft.com/crm/2011/Contracts\">";
request += "<a:Parameters xmlns:c=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
request += "<a:KeyValuePairOfstringanyType>";
request += "<c:key>EntityMoniker</c:key>";
request += "<c:value i:type=\"a:EntityReference\">";
request += "<a:Id>" + entityId + "</a:Id>";
request += "<a:LogicalName>" + entityName + "</a:LogicalName>";
request += "<a:Name i:nil=\"true\" />";
request += "</c:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "<a:KeyValuePairOfstringanyType>";
request += "<c:key>State</c:key>";
request += "<c:value i:type=\"a:OptionSetValue\">";
request += "<a:Value>"+stateOptionsetValue+"</a:Value>";
request += "</c:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "<a:KeyValuePairOfstringanyType>";
request += "<c:key>Status</c:key>";
request += "<c:value i:type=\"a:OptionSetValue\">";
request += "<a:Value>"+statusOptionsetValue+"</a:Value>";
request += "</c:value>";
request += "</a:KeyValuePairOfstringanyType>";
request += "</a:Parameters>";
request += "<a:RequestId i:nil=\"true\" />";
request += "<a:RequestName>SetState</a:RequestName>";
request += "</request>";
request += "</Execute>";
request += "</s:Body>";
request += "</s:Envelope>";
var ret = executeSoapRequest("execute", request);
}
The executeSoapRequest function looks like this:
function executeSoapRequest(action, xml) {
var actionUrl = "http://schemas.microsoft.com/crm/2007/WebServices/" + action;
var xmlHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
xmlHttpRequest.Open("POST", "/mscrmservices/2007/CrmService.asmx", false);
xmlHttpRequest.setRequestHeader("SOAPAction", actionUrl);
xmlHttpRequest.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlHttpRequest.setRequestHeader("Content-Length", xml.length);
xmlHttpRequest.send(xml);
return xmlHttpRequest.responseXML;
}
and I have tried calling the method described at the top with the calls (note that newGuid is assigned somewhere else, and contains the Guid of a new email record that I wish to set the state/status for):
setStateCodeForEntity("email", newGuid, 1, 2);
and
setStateCodeForEntity("email", newGuid, "Completed", 2);
What I am getting is a Server 500 error, with the following response:
"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n<head>\r\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=iso-8859-1\"/>\r\n<title>500 - Internal server error.</title>\r\n<style type=\"text/css\">\r\n<!--\r\nbody{margin:0;font-size:.7em;font-family:Verdana, Arial, Helvetica, sans-serif;background:#EEEEEE;}\r\nfieldset{padding:0 15px 10px 15px;} \r\nh1{font-size:2.4em;margin:0;color:#FFF;}\r\nh2{font-size:1.7em;margin:0;color:#CC0000;} \r\nh3{font-size:1.2em;margin:10px 0 0 0;color:#000000;} \r\n#header{width:96%;margin:0 0 0 0;padding:6px 2% 6px 2%;font-family:\"trebuchet MS\", Verdana, sans-serif;color:#FFF;\r\nbackground-color:#555555;}\r\n#content{margin:0 0 0 2%;position:relative;}\r\n.content-container{background:#FFF;width:96%;margin-top:8px;padding:10px;position:relative;}\r\n-->\r\n</style>\r\n</head>\r\n<body>\r\n<div id=\"header\"><h1>Server Error</h1></div>\r\n<div id=\"content\">\r\n <div class=\"content-container\"><fieldset>\r\n <h2>500 - Internal server error.</h2>\r\n <h3>There is a problem with the resource you are looking for, and it cannot be displayed.</h3>\r\n </fieldset></div>\r\n</div>\r\n</body>\r\n</html>\r\n<?xml version=\"1.0\" encoding=\"utf-8\"?><soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"><soap:Body><soap:Fault><faultcode>Server</faultcode><faultstring>Object reference not set to an instance of an object.</faultstring><detail><error xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\"><displaytitle /><displaytext /><description>Object reference not set to an instance of an object.</description><file>Not available</file><line>Not available</line><details>Not available</details><requesturl>http://[SERVERNAME]/mscrmservices/2007/CrmService.asmx</requesturl><pathAndQuery>/mscrmservices/2007/CrmService.asmx</pathAndQuery><source>SOAP</source><stacktrace /></error></detail></soap:Fault></soap:Body></soap:Envelope>"
HOWEVER ...
I have just noticed that I get a very similar responseText when I use the executeSoapRequest method that does succeed. When I make the call as described above the status of the email entity is not changed.
I am almost certainly doing something silly, but I have no idea what. Any constructive help would be a life saver at this time.
Gray

Ok ... for completeness, here is the answer:
The main function looks like this:
function setStateCodeForEntity(entityName, entityId, stateOptionsetValue, statusOptionsetValue) {
var request = [
"<soap:Envelope xmlns:soap='http://schemas.xmlsoap.org/soap/envelope/' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance' xmlns:xsd='http://www.w3.org/2001/XMLSchema'>",
GenerateAuthenticationHeader(),
"<soap:Body>",
"<Execute xmlns='http://schemas.microsoft.com/crm/2007/WebServices'>",
"<Request xsi:type='SetStateDynamicEntityRequest'>",
"<Entity>",
"<Name xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>", entityName, "</Name>",
"<Id xmlns='http://schemas.microsoft.com/crm/2006/CoreTypes'>", entityId, "</Id>",
"</Entity>",
"<State>", stateOptionsetValue, "</State>",
"<Status>", statusOptionsetValue, "</Status>",
"</Request>",
"</Execute>",
"</soap:Body>",
"</soap:Envelope>"
].join("");
var ret = executeSoapRequest("Execute", request);
}
Notice the Request type is 'SetStateDynamicEntityRequest', which seemed to be the main problem with my original attempt, but also this version is far more simple that I was originally using.
The method is called by
setStateCodeForEntity("email", newGuid, 'Completed', 2);
I was given the answer by a colleague who recommended the Crm Service Toolkit (http://crmtoolkit.codeplex.com/) and the code was pretty much lifted from there. Further information at http://danielcai.blogspot.co.uk/2010/07/crm-web-service-toolkit-for-javascript.html

Related

RESTful client in Unity - validation error

I have a RESTful server created with ASP.Net and am trying to connect to it with the use of a RESTful client from Unity. GET works perfectly, however I am getting a validation error when sending a POST request. At the same time both GET and POST work when sending requests from Postman.
My Server:
[HttpPost]
public IActionResult Create(User user){
Console.WriteLine("***POST***");
Console.WriteLine(user.Id+", "+user.sex+", "+user.age);
if(!ModelState.IsValid)
return BadRequest(ModelState);
_context.Users.Add(user);
_context.SaveChanges();
return CreatedAtRoute("GetUser", new { id = user.Id }, user);
}
My client:
IEnumerator PostRequest(string uri, User user){
string u = JsonUtility.ToJson(user);
Debug.Log(u);
using (UnityWebRequest webRequest = UnityWebRequest.Post(uri, u)){
webRequest.SetRequestHeader("Content-Type","application/json");
yield return webRequest.SendWebRequest();
string[] pages = uri.Split('/');
int page = pages.Length - 1;
if (webRequest.isNetworkError || webRequest.isHttpError){
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
else{
Debug.Log(pages[page] + ":\nReceived: " + webRequest.downloadHandler.text);
}
}
}
I was trying both with the Json conversion and writing the string on my own, also with the WWWForm, but the error stays.
The error says that it's an unknown HTTP error. When printing the returned text it says:
"One or more validation errors occurred.","status":400,"traceId":"|b95d39b7-4b773429a8f72b3c.","errors":{"$":["'%' is an invalid start of a value. Path: $ | LineNumber: 0 | BytePositionInLine: 0."]}}
On the server side it recognizes the correct method and controller, however, it doesn't even get to the first line of the method (Console.WriteLine). Then it says: "Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'".
Here're all of the server side messages:
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
Request starting HTTP/1.1 POST http://localhost:5001/user application/json 53
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[0]
Executing endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[3]
Route matched with {action = "Create", controller = "User"}. Executing controller action with signature Microsoft.AspNetCore.Mvc.IActionResult Create(TheNewestDbConnect.Data.Entities.User) on controller TheNewestDbConnect.Controllers.UserController (TheNewestDbConnect).
info: Microsoft.AspNetCore.Mvc.Infrastructure.ObjectResultExecutor[1]
Executing ObjectResult, writing value of type 'Microsoft.AspNetCore.Mvc.ValidationProblemDetails'.
info: Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker[2]
Executed action TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect) in 6.680400000000001ms
info: Microsoft.AspNetCore.Routing.EndpointMiddleware[1]
Executed endpoint 'TheNewestDbConnect.Controllers.UserController.Create (TheNewestDbConnect)'
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished in 11.3971ms 400 application/problem+json; charset=utf-8
info: Microsoft.AspNetCore.Hosting.Diagnostics[1]
I have no idea what is happening and how to solve it. Any help will be strongly appreciated!
Turned out I was just missing an upload handler. Adding this line solved it: webRequest.uploadHandler = new UploadHandlerRaw(System.Text.Encoding.UTF8.GetBytes(JsonObject));

Groovy script for Jenkins: execute HTTP request without 3rd party libraries

I need to create a Groovy post build script in Jenkins and I need to make a request without using any 3rd party libraries as those can't be referenced from Jenkins.
I tried something like this:
def connection = new URL( "https://query.yahooapis.com/v1/public/yql?q=" +
URLEncoder.encode(
"select wind from weather.forecast where woeid in " + "(select woeid from geo.places(1) where text='chicago, il')",
'UTF-8' ) )
.openConnection() as HttpURLConnection
// set some headers
connection.setRequestProperty( 'User-Agent', 'groovy-2.4.4' )
connection.setRequestProperty( 'Accept', 'application/json' )
// get the response code - automatically sends the request
println connection.responseCode + ": " + connection.inputStream.text
but I also need to pass a JSON in the POST request and I'm not sure how I can do that. Any suggestion appreciated.
Executing POST request is pretty similar to a GET one, for example:
import groovy.json.JsonSlurper
// POST example
try {
def body = '{"id": 120}'
def http = new URL("http://localhost:8080/your/target/url").openConnection() as HttpURLConnection
http.setRequestMethod('POST')
http.setDoOutput(true)
http.setRequestProperty("Accept", 'application/json')
http.setRequestProperty("Content-Type", 'application/json')
http.outputStream.write(body.getBytes("UTF-8"))
http.connect()
def response = [:]
if (http.responseCode == 200) {
response = new JsonSlurper().parseText(http.inputStream.getText('UTF-8'))
} else {
response = new JsonSlurper().parseText(http.errorStream.getText('UTF-8'))
}
println "response: ${response}"
} catch (Exception e) {
// handle exception, e.g. Host unreachable, timeout etc.
}
There are two main differences comparing to GET request example:
You have to set HTTP method to POST
http.setRequestMethod('POST')
You write your POST body to outputStream:
http.outputStream.write(body.getBytes("UTF-8"))
where body might be a JSON represented as string:
def body = '{"id": 120}'
Eventually it's good practice to check what HTTP status code returned: in case of e.g. HTTP 200 OK you will get your response from inputStream while in case of any error like 404, 500 etc. you will get your error response body from errorStream.

Retrieve all the entities via SOAP in Javascript (CRM 2011)

With the following SOAP query I'm trying to get all the entities in the solution but it doesn't return entity. Maybe a second eye could help. Do you see anything wrong that I can't see? Thank you !
JCL.RetrieveAllEntitiesRequest = function (fnCallBack) {
/// Returns a sorted array of entities
var request = "";
request += "<s:Envelope xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\">";
request += " <s:Body>";
request += " <Execute xmlns=\"http://schemas.microsoft.com/xrm/2011/Contracts/Services\" xmlns:i=\"http://www.w3.org/2001/XMLSchema-instance\">";
request += " <request i:type=\"a:RetrieveAllEntitiesRequest\" xmlns:a=\"http://schemas.microsoft.com/xrm/2011/Contracts\">";
request += " <a:Parameters xmlns:b=\"http://schemas.datacontract.org/2004/07/System.Collections.Generic\">";
request += " <a:KeyValuePairOfstringanyType>";
request += " <b:key>EntityFilters</b:key>";
request += " <b:value i:type=\"c:EntityFilters\" xmlns:c=\"http://schemas.microsoft.com/xrm/2011/Metadata\">Entity</b:value>";
request += " </a:KeyValuePairOfstringanyType>";
request += " <a:KeyValuePairOfstringanyType>";
request += " <b:key>RetrieveAsIfPublished</b:key>";
request += " <b:value i:type=\"c:boolean\" xmlns:c=\"http://www.w3.org/2001/XMLSchema\">true</b:value>";
request += " </a:KeyValuePairOfstringanyType>";
request += " </a:Parameters>";
request += " <a:RequestId i:nil=\"true\" />";
request += " <a:RequestName>RetrieveAllEntities</a:RequestName>";
request += " </request>";
request += " </Execute>";
request += " </s:Body>";
request += "</s:Envelope>";
return JCL._ExecuteRequest(request, "Execute", JCL._RetrieveAllEntitiesResponse, fnCallBack);
};
JCL._ExecuteRequest = function (sXml, sMessage, fInternalCallback, fUserCallback) {
'use strict';
var xmlhttp = new XMLHttpRequest();
xmlhttp.open("POST", JCL.server + "/XRMServices/2011/Organization.svc/web", (fUserCallback !== null));
xmlhttp.setRequestHeader("Accept", "application/xml, text/xml, */*");
xmlhttp.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
xmlhttp.setRequestHeader("SOAPAction", "http://schemas.microsoft.com/xrm/2011/Contracts/Services/IOrganizationService/" + sMessage);
if (fUserCallback !== null) {
// asynchronous: register callback function, then send the request.
xmlhttp.onreadystatechange = function () {
fInternalCallback.call(this, xmlhttp, fUserCallback);
};
xmlhttp.send(sXml);
} else {
// synchronous: send request, then call the callback function directly
xmlhttp.send(sXml);
return fInternalCallback.call(this, xmlhttp, null);
}
};
Update after #Paul Way replied to me:
This is the error message I get when I select the entity that I need to investigate in CRM Data Detective. I can't add any field to this entity that's why I am using CRM Data Detective to find out which field I could delete, but it happens that the solution couldn't also handle an entity with a maximum number of attributes. Could you please have a look Paul? thank you So much !
Well, I'm embarrassed :)
I've updated the CRM Data Detective and JCL libraries to support CRM 2011 pre UR 12.
https://crmdatadetective.codeplex.com/
https://github.com/paul-way/JCL
The problem has to do with how the returned XML is parsed. Let me know if this fixes your problems...
The CRM 2011 SDK includes some good sample code to do this...
http://msdn.microsoft.com/en-us/library/gg594428.aspx

Windows Azure REST API Update Role Doesn't Take Effect

I'm doing some proof of concept work on azure, trying to get a role using the Get Role URL:
https://management.core.windows.net/<subscription-id>/services/hostedservices/<cloudservice-name>/deployments/<deployment-name>/roles/<role-name>
And then update the role using the Update Role URL:
https://management.core.windows.net/<subscription-id>/services/hostedservices/<cloudservice-name>/deployments/<deployment-name>/roleinstances/<role-name>
Both of those URLs are straight from the msdn pages. The GET request works and I get XML that matches what I see in the management console.
When I then add an element to the xml and send that back with a PUT on the update URL, I get a 200 response, but I never see the change in the management console. I also don't see any error message when I send gibberish. I'm connecting from C#, and a coworker suggested I could get the response with this:
var response = (HttpWebResponse)request.GetResponse();
Console.WriteLine(response.ToString());
But that gets me a 404 error.
Is there an extra step to commit the update? And how can I see the response that msdn mentions?
2 suggestions:
When I am just doing quick SMAPI work I use AzureTools (http://blogs.msdn.com/b/kwill/archive/2013/08/26/azuretools-the-diagnostic-utility-used-by-the-windows-azure-developer-support-team.aspx). Specifically, look in the Misc Tools section under "Service Management REST API". This will show you the full response.
To answer your question about how to get the response (txtSMAPIResponse is where AzureTools puts the response info):
System.IO.Stream receiveStream;
System.IO.StreamReader readStream;
Encoding encode;
HttpWebResponse response = null;
try
{
response = (HttpWebResponse)request.GetResponse();
}
catch (WebException ex)
{
txtSMAPIRequest.Text = request.Headers.ToString();
txtSMAPIResponse.Text = ex.Message + Environment.NewLine + Environment.NewLine + ex.Response.Headers.ToString();
try
{
receiveStream = ex.Response.GetResponseStream();
encode = System.Text.Encoding.GetEncoding("utf-8");
// Pipes the stream to a higher level stream reader with the required encoding format.
readStream = new System.IO.StreamReader(receiveStream, encode);
txtSMAPIResponse.Text += readStream.ReadToEnd();
// Releases the resources of the response.
response.Close();
// Releases the resources of the Stream.
readStream.Close();
}
catch
{
}
return;
}
txtSMAPIRequest.Text = request.Method + " " + request.RequestUri + " " + request.ProtocolVersion + Environment.NewLine + Environment.NewLine;
txtSMAPIRequest.Text += request.Headers.ToString();
txtSMAPIResponse.Text = (int)response.StatusCode + " - " + response.StatusDescription + Environment.NewLine + Environment.NewLine;
txtSMAPIResponse.Text += response.Headers + Environment.NewLine + Environment.NewLine;
receiveStream = response.GetResponseStream();
encode = System.Text.Encoding.GetEncoding("utf-8");
// Pipes the stream to a higher level stream reader with the required encoding format.
readStream = new System.IO.StreamReader(receiveStream, encode);
txtSMAPIResponse.Text += readStream.ReadToEnd();
// Releases the resources of the response.
response.Close();
// Releases the resources of the Stream.
readStream.Close();
}
I've got the same problem. In my case EndPointACL is not getting updated. Very painful thing is for every update , we have to send the entire ConfigurationSet; There is no way to update the ACL for particular end point.
A typical update looks like this:
<?xml version="1.0"?>
<PersistentVMRole xmlns="http://schemas.microsoft.com/windowsazure" xmlns:i="http://www.w3.org/2001/XMLSchema-instance">
<ConfigurationSets>
<ConfigurationSet>
<ConfigurationSetType>NetworkConfiguration</ConfigurationSetType>
<InputEndpoints>
<InputEndpoint>
<LocalPort>100</LocalPort>
<Name>TCP-100</Name>
<Port>100</Port>
<Protocol>tcp</Protocol>
<EndpointACL>
<Rules>
<Rule>
<Order>1</Order>
<Action>deny</Action>
<RemoteSubnet>108.239.229.0/24</RemoteSubnet>
<Description>test-rule</Description>
</Rule>
</Rules>
</EndpointACL>
</InputEndpoint>
</InputEndpoints>
<SubnetNames>
<SubnetName>Subnet-1</SubnetName>
</SubnetNames>
</ConfigurationSet>
</ConfigurationSets>
</PersistentVMRole>

Facebook chat reports "not-authorized", although "xmpp_login" is granted

I am trying to integrate the facebook chat into our mobile Flash/AIR application, and am using XIFF for the XMPP stuff. Of course, I had to modify some files for the newer Facebook API that uses access_token instead of sig and secret.
For those familiar with the xiff/smack API, here is how I establish the connection:
XFacebookPlatform.setFacebookSessionValues(AppData.FACEBOOK_APP_ID, AppData.getInstance().getFBSession().accessToken);
XMPPConnection.registerSASLMechanism("X-FACEBOOK-PLATFORM", XFacebookPlatform);
var con :XMPPConnection = new XMPPConnection();
con.server = "chat.facebook.com";
con.useAnonymousLogin = true;
con.connect(XMPPConnection.STREAM_TYPE_STANDARD);
.
Basically, I get to the point where I answer the challenge with what IMO should be a correct format:
var responseMap:Dictionary = new Dictionary();
responseMap.api_key = fb_api_key;
responseMap.call_id = 0;
responseMap.method = incomingChallengeMap.method;
responseMap.nonce = incomingChallengeMap.nonce;
responseMap.access_token = user_access_token;
responseMap.v = "1.0";
var challengeResponse:String = "api_key=" + responseMap.api_key;
challengeResponse += "&call_id=" + responseMap.call_id;
challengeResponse += "&method=" + responseMap.method;
challengeResponse += "&nonce=" + responseMap.nonce;
challengeResponse += "&access_token=" + responseMap.access_token;
challengeResponse += "&v=" + responseMap.v;
challengeResponse = Base64.encode( challengeResponse );
.
The response is sent, but as an answer I receive the following:
<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
This sounds like I did not grant the "xmpp_login", but I did. I checked that via the Graph API explorer, and for the same access_token it shows:
{
"data": [
{
"installed": 1,
"xmpp_login": 1,
"user_online_presence": 1,
"friends_online_presence": 1
}
]
}
This should be more than enough, I guess.
But still I get the "not-authorized" failure.
Any ideas what went wrong here?
Funny enough, the problem was this line:
var con :XMPPConnection = new XMPPConnection();
Which has to be replaced with this line:
var con :XMPPTLSConnection = new XMPPTLSConnection();
That's it. The facebook chat only authenticates with a TLS connection.
.
While that does make sense, the error message of
<failure xmlns="urn:ietf:params:xml:ns:xmpp-sasl">
<not-authorized xmlns="urn:ietf:params:xml:ns:xmpp-sasl"/>
is very misleading here, as it implies that something with the rights would be wrong.