Creating multiple entities in single request in Microsoft Dynamics CRM (OData) - odata

I know how to create a single entity in single request. However, one requirement wants me to create multiple entities (in my case it's multiple entries in ContactSet). I tried putting array to
POST /XRMServices/2011/OrganizationData.svc/ContactSet
[{
"MobilePhone": "+0012 555 555 555",
"YomiFullName" : "Demo User 1",
"GenderCode" : {
"Value" : 1
}
.....
<data removed for sanity>
.....
},
{
"MobilePhone": "+0012 555 555 111",
"YomiFullName" : "Demo User 2",
"GenderCode" : {
"Value" : 1
}
.....
<data removed for sanity>
.....
}]
However this does not work and I could not find any documentation explaining me ways to achieve this. Any help would be greatly appreciated.

You need to use an ExecuteMultipleRequest, I don't believe this is available in Rest service however, but is available in the SOAP service.
// Get a reference to the organization service.
using (_serviceProxy = new OrganizationServiceProxy(serverConfig.OrganizationUri, serverConfig.HomeRealmUri,serverConfig.Credentials, serverConfig.DeviceCredentials))
{
// Enable early-bound type support to add/update entity records required for this sample.
_serviceProxy.EnableProxyTypes();
#region Execute Multiple with Results
// Create an ExecuteMultipleRequest object.
requestWithResults = new ExecuteMultipleRequest()
{
// Assign settings that define execution behavior: continue on error, return responses.
Settings = new ExecuteMultipleSettings()
{
ContinueOnError = false,
ReturnResponses = true
},
// Create an empty organization request collection.
Requests = new OrganizationRequestCollection()
};
// Create several (local, in memory) entities in a collection.
EntityCollection input = GetCollectionOfEntitiesToCreate();
// Add a CreateRequest for each entity to the request collection.
foreach (var entity in input.Entities)
{
CreateRequest createRequest = new CreateRequest { Target = entity };
requestWithResults.Requests.Add(createRequest);
}
// Execute all the requests in the request collection using a single web method call.
ExecuteMultipleResponse responseWithResults =
(ExecuteMultipleResponse)_serviceProxy.Execute(requestWithResults);
// Display the results returned in the responses.
foreach (var responseItem in responseWithResults.Responses)
{
// A valid response.
if (responseItem.Response != null)
DisplayResponse(requestWithResults.Requests[responseItem.RequestIndex], responseItem.Response);
// An error has occurred.
else if (responseItem.Fault != null)
DisplayFault(requestWithResults.Requests[responseItem.RequestIndex],
responseItem.RequestIndex, responseItem.Fault);
}
}

ExecuteMultipleRequest is a good but not the only way. If you use CRM 2016 you can use Batch operations that is available in new WebApi. Check article that describes it - https://msdn.microsoft.com/en-us/library/mt607719.aspx

You can use a Web API action (see MSDN) to execute an ExecuteTransactionRequest, as described here. Subject of the example on MSDN is the WinOpportunityRequest, but it should work with any supported request, including custom actions.

Related

SAPUI5 OData V2 Batch Operations with multiple differed groups

I'm trying to do a batch operation with multiple groupids in a single batch request. and need to get results in two different batch responses.
But when I initiate the request only one group has been submitted and only get one batch response.
Here is my code
oModel = this.getOwnerComponent().getModel("mymodel");
$.sap.itemArray.forEach(function (entry) {
if (p < $.sap.itemArray.length) {
var oData = {
"AUTO_ID": entry.Id,
"VALUE": entry.Value,
};
mParameters.groupId = "createGroup1";
oModel .create("/Table1", oData, mParameters);
}
p++;
});
for (p = 0; p < $.sap.itemArray2.length; p++) {
var oData = {
"Item2ID" : $.sap.itemArray2[p].ItemsId,
"Value" : $.sap.itemArray2[p].Value
};
mParameters.groupId = "createGroup2";
oModel .create("/Table2", oData, mParameters);
}
oModel.setDeferredGroups(["createGroup1","createGroup2"]);
oStyleSizeModel.submitChanges({
success: function(recievedObject){
var responses = recievedObject.__batchResponses;
},
error: function (oError) {
var oBody = oError.responseText;
}
});
Here is the response I got.
And here it only execute the first group's requests and only returned one batch response.
How to execute multiple batch requests with different group Ids and get each group's responses.
I believe you want to group each change separately. You need to use the concept of Change Set (not Group).
Use createEntry method instead of create.
For each call, use different changeSetId, but same groupId.
Call submitChanges passing the groupId.

HTPP POST to Google Forms or Alternative

I have a google form setup that emails me upon a manual submission when somebody fills it out (new lead) and transfers the information to a Google spreadsheet. Easy enough to figure that out.
However, now I'm trying to figure out how to send the same information information contained within a url string and automatically POST that information to the form. Or find a company who offers that ability, via an api or other means. So far I've tested out jotform and a few others. The information passed along fine, but it doesn't auto populate the fields. I assume it's because it doesn't know that x=y due to the fields being named differently. I've found a ton of documentation about pre-populating the forms, but not much about filling out a form every time a new POST url is generated.
URL looks like the following
VARhttps://script.google.com/macros/s/XXXXXXXXXXXXXXXX/exec?/--A--
first_name--B--/--A--last_name--B--/--A--address1--B--/--A--city--B--/--A--
state--B--/--A--postal_code--B--/--A--phone_number--B--/--A--date_of_birth--
B--/--A--email--B--
Information passed is as follows
https://website
here.com/Pamela/Urne/123+Test+Street/Henderson/TX/75652/281XXXXXX/1974-01-
01/test0101cw#test.com
The script I'm testing out
// original from: http://mashe.hawksey.info/2014/07/google-sheets-as-a-database-insert-with-apps-script-using-postget-methods-with-ajax-example/
// original gist: https://gist.github.com/willpatera/ee41ae374d3c9839c2d6
function doGet(e){
return handleResponse(e);
}
// Enter sheet name where data is to be written below
var SHEET_NAME = "Sheet1";
var SCRIPT_PROP = PropertiesService.getScriptProperties(); // new property service
function handleResponse(e) {
// shortly after my original solution Google announced the LockService[1]
// this prevents concurrent access overwritting data
// [1] http://googleappsdeveloper.blogspot.co.uk/2011/10/concurrency-and-google-apps-script.html
// we want a public lock, one that locks for all invocations
var lock = LockService.getPublicLock();
lock.waitLock(30000); // wait 30 seconds before conceding defeat.
try {
// next set where we write the data - you could write to multiple/alternate destinations
var doc = SpreadsheetApp.openById(SCRIPT_PROP.getProperty("key"));
var sheet = doc.getSheetByName(SHEET_NAME);
// we'll assume header is in row 1 but you can override with header_row in GET/POST data
var headRow = e.parameter.header_row || 1;
var headers = sheet.getRange(1, 1, 1, sheet.getLastColumn()).getValues()[0];
var nextRow = sheet.getLastRow()+1; // get next row
var row = [];
// loop through the header columns
for (i in headers){
if (headers[i] == "Timestamp"){ // special case if you include a 'Timestamp' column
row.push(new Date());
} else { // else use header name to get data
row.push(e.parameter[headers[i]]);
}
}
// more efficient to set values as [][] array than individually
sheet.getRange(nextRow, 1, 1, row.length).setValues([row]);
// return json success results
return ContentService
.createTextOutput(JSON.stringify({"result":"success", "row": nextRow}))
.setMimeType(ContentService.MimeType.JSON);
} catch(e){
// if error return this
return ContentService
.createTextOutput(JSON.stringify({"result":"error", "error": e}))
.setMimeType(ContentService.MimeType.JSON);
} finally { //release lock
lock.releaseLock();
}
}
function setup() {
var doc = SpreadsheetApp.getActiveSpreadsheet();
SCRIPT_PROP.setProperty("key", doc.getId());
}
I get a success message after accessing the url, but all information listed in the spreadsheet is "Undefined."
That's as far as I got so far. If somebody knows an easier solution or can point me in the right direction I'd appreciate it.

passing parameters to power bi filter programmatically from asp.net MVC

I have developed a powerBI report and deployed the same in Workspace.
From PowerBI interface I viewed the report and am able to add filter like this:
filter=tablename~2Fcolumnname eq 4
The condition is working fine from the interface. But, when I add filter condition in the code of my asp.ner MVC application, filter does not work.
The condition is working fine from the interface.
But, when I add filter condition in the code of my asp.ner MVC application, filter does not work.
My sample code:
var client = new PowerBIClient(new Uri(ApiUrl), tokenCredentials);
var reports = await client.Reports.GetReportsInGroupAsync(WorkspaceId);
report = reports.Value.FirstOrDefault(r => r.Id == "aa07v254-8t46-2387-4k53-2725y90n3456");
report.EmbedUrl = report.EmbedUrl + "?filter=tablename/columnname%20eq%204";
Please help me diagnose, why the filter is not working.
You don't need to change the embed url, instead try to use the following example:
// Build the filter you want to use. For more information, See Constructing
// Filters in https://github.com/Microsoft/PowerBI-JavaScript/wiki/Filters.
const filter = {
$schema: "http://powerbi.com/product/schema#basic",
target: {
table: "Geo",
column: "Region"
},
operator: "In",
values: ["West"]
};
// Get a reference to the embedded report HTML element
var embedContainer = $('#embedContainer')[0];
// Get a reference to the embedded report.
report = powerbi.get(embedContainer);
// Set the filter for the report.
// Pay attention that setFilters receives an array.
report.setFilters([filter])
.then(function () {
Log.logText("Report filter was set.");
})
.catch(function (errors) {
Log.log(errors);
});

Rally Authentication issue in Getting results

I am using asp.net MVC application and consuming Rally web API for integration. I want fetch the data from rally site.
in Login Controller
RallyRestApi restApi = new RallyRestApi(webServiceVersion: "v2.0");
dynamic authenticateUser=restApi.Authenticate(usr.UserName, usr.Password, "https://rally1.rallydev.com/", allowSSO: false);
dynamic objUserName;
if (authenticateUser.ToString().ToLower() == "authenticated")
{
Session["Username"] = usr.UserName;
Session["Password"] = usr.Password;
FormsAuthentication.SetAuthCookie(usr.UserName, true);
FormsAuthentication.SetAuthCookie(usr.Password, true);
objUserName = restApi.GetCurrentUser();
Session["DisplayName"] = objUserName["DisplayName"];
return RedirectToAction("Home", "PortfolioItem");
}
Here Authentication is successful. But as per my research, if we want to fetch data every time, I think we need to pass user authentication details like below:
CreateResult createResult = restApi.Create("defect", toCreate); // need to get with same restApi object or authentication details
OperationResult updateResult = restApi.Update(createResult.Reference, toUpdate);
//Get the item
DynamicJsonObject item = restApi.GetByReference(createResult.Reference);// need to get with same restApi object or authentication details
//Query for items
Request request = new Request("defect");
request.Fetch = new List<string>() { "Name", "Description", "FormattedID" };
request.Query = new Query("Name", Query.Operator.Equals, "My Defect");
QueryResult queryResult = restApi.Query(request); // need to get with same restApi object or authentication details
Like above, is it if we need to fetch anything, we need to authenticate first and every time? please clarify on this.
You'll need to authenticate once for each instance of RallyRestApi you create. In general it is better to create one, use it, and then dispose of it rather than creating it once and then keeping it around in session forever.

Unable to figure out how to use post method, for a suitescript written in Netsuite

I am trying to do use the post method for a simple suitescript program, i am very new to this.
In Netsuite i have written a suitescript as follows.
function restPost()
{
var i = nlapiLoadRecord('department', 115);
var memo = nlapisetfieldvalue('custrecord225', ' ');// this is a customfield, which i want to populate the memo field, using rest client in firefox
var recordId = nlapiSubmitRecord(i);
}
i have created a script record and uploaded this suitescript and even copied the external URL to paste it in restclient.
In Restclient(firefox plugin), pasted the external URL, i have given the method as post, header authorization given, content-type: application/json, and in body i put in {"memo":"mynamehere"};
In this the error i get is
message": "missing ) after argument list
I even tried it by writting other suitescript programs the errors i get is as follows:
Unexpected token in object literal (null$lib#3) Empty JSON string
Invalid data format. You should return TEXT.
I am kinda new to the programming world, so any help would be really good.
I think you are trying to create a RESTlet for POST method. Following is the sample code for POST method -
function createRecord(datain)
{
var err = new Object();
// Validate if mandatory record type is set in the request
if (!datain.recordtype)
{
err.status = "failed";
err.message= "missing recordtype";
return err;
}
var record = nlapiCreateRecord(datain.recordtype);
for (var fieldname in datain)
{
if (datain.hasOwnProperty(fieldname))
{
if (fieldname != 'recordtype' && fieldname != 'id')
{
var value = datain[fieldname];
if (value && typeof value != 'object') // ignore other type of parameters
{
record.setFieldValue(fieldname, value);
}
}
}
}
var recordId = nlapiSubmitRecord(record);
nlapiLogExecution('DEBUG','id='+recordId);
var nlobj = nlapiLoadRecord(datain.recordtype,recordId);
return nlobj;
}
So after deploying this RESTlet you can call this POST method by passing following sample JSON payload -
{"recordtype":"customer","entityid":"John Doe","companyname":"ABCTools Inc","subsidiary":"1","email":"jdoe#email.com"}
For Authorization you have to pass request headers as follows -
var headers = {
"Authorization": "NLAuth nlauth_account=" + cred.account + ", nlauth_email=" + cred.email +
", nlauth_signature= " + cred.password + ", nlauth_role=" + cred.role,
"Content-Type": "application/json"};
I can understand your requirement and the answer posted by Parsun & NetSuite-Expert is good. You can follow that code. That is a generic code that can accept any master record without child records. For Example Customer Without Contact or Addressbook.
I would like to suggest a small change in the code and i have given it in my solution.
Changes Below
var isExistRec = isExistingRecord(objDataIn);
var record = (isExistRec) ? nlapiLoadRecord(objDataIn.recordtype, objDataIn.internalid, {
recordmode: 'dynamic'
}) : nlapiCreateRecord(objDataIn.recordtype);
//Check for Record is Existing in Netsuite or Not using a custom function
function isExistingRecord(objDataIn) {
if (objDataIn.internalid != null && objDataIn.internalid != '' && objDataIn.internalid.trim().length > 0)
return true;
else
return false;
}
So whenever you pass JSON data to the REStlet, keep in mind you have
to pass the internalid, recordtype as mandatory values.
Thanks
Frederick
I believe you will want to return something from your function. An empty object should do fine, or something like {success : true}.
Welcome to Netsuite Suitescripting #Vin :)
I strongly recommend to go through SuiteScript API Overview & SuiteScript API - Alphabetized Index in NS help Center, which is the only and most obvious place to learn the basics of Suitescripting.
nlapiLoadRecord(type, id, initializeValues)
Loads an existing record from the system and returns an nlobjRecord object containing all the field data for that record. You can then extract the desired information from the loaded record using the methods available on the returned record object. This API is a core API. It is available in both client and server contexts.
function restPost(dataIn) {
var record = nlapiLoadRecord('department', 115); // returns nlobjRecord
record.setFieldValue('custrecord225', dataIn.memo); // set the value in custom field
var recordId = nlapiSubmitRecord(record);
return recordId;
}

Resources