Managed C++ Web reference to WCF service problems - c++

I deveploped a simple WCF service called CLSAPIService that it's Contract contains a method named UpdateLastOpenCloseCall:
[OperationContract(Name = "UpdateLastOpenCloseCall", Action = "http://uniform.com/UpdateLastOpenCloseCall")]
CallResult UpdateLastOpenCloseCall(int iSwitchID, int iAgentID, string strExtension, BusinessDataField[] bdFields);
One of its parameters is a simple DataContract:
[DataContract]
public struct BusinessDataField
{
[DataMember]
public string Name;
[DataMember]
public object Value;
}
Then I created a simple testing project in Managed C++ in Visual .Net 2005, and created web reference for the service:
CLSAPIProxy::CLSAPIService^ service = gcnew CLSAPIProxy::CLSAPIService();
CLSAPIProxy::BusinessDataField ^f1 = gcnew CLSAPIProxy::BusinessDataField();
f1->Name = L"test_string";
f1->Value = L"string";
CLSAPIProxy::BusinessDataField ^f2 = gcnew CLSAPIProxy::BusinessDataField();
f2->Name = L"test_int";
f2->Value = 123;
System::Collections::Generic::List<CLSAPIProxy::BusinessDataField^> ^list = gcnew;
System::Collections::Generic::List<CLSAPIProxy::BusinessDataField^>();
list->Add(f1);
list->Add(f2);
service->UpdateLastOpenCloseCall(1,true,22817,true,L"24319",list->ToArray());
When the BusinessDataField structure arrives to the WCF method, it appears that only the Value property is updated, and the Name property is null, even though I assiged it a value.
What could be the problem?

please add Order to your data member.
[DataMember(Name = "FirstName", IsRequired = true, Order = 2)]
and consult the following article:
Change The Order Of data members

Related

How to simulate a CRM plugin sandbox isolation mode in unit tests?

Context
I would like to write some unit tests against classes what will be utilized by CRM 2016 CodeActivity and Plugin classes. The final assembly will be registered in sandbox isolation mode.
I want to be sure if a test case is green when running unit tests, it will not be more restricted in sandbox isolation security restrictions when registered and run in CRM.
Question
Is there any way to simulate the sandbox isolation when running unit tests?
That's a really good question. You can maybe simulate running the plugin assemblies and code activities in a sandbox based on this Sandbox example.
With that example you could run the codeactivity with a limited set of permissions.
Now, what are the exact limitations of CRM online? Found this article. There is a Sandbox Limitations sections with some of them. If you find another one please let me know. Cause I'd be keen on adding this feature to FakeXrmEasy
Cheers,
I found this today: https://github.com/carltoncolter/DynamicsPlugin/blob/master/DynamicsPlugin.Tests/PluginContainer.cs
Which I used to turn into this:
using System;
using System.Diagnostics;
using System.Globalization;
using System.Net;
using System.Net.NetworkInformation;
using System.Reflection;
using System.Security;
using System.Security.Permissions;
using System.Text.RegularExpressions;
namespace Core.DLaB.Xrm.Tests.Sandbox
{
public static class SandboxWrapper
{
public static T Instantiate<T>(object[] constructorArguments = null)
{
return new SandboxWrapper<T>().Instantiate(constructorArguments);
}
public static T InstantiatePlugin<T>(string unsecureConfig = null, string secureConfig = null)
{
object[] args = null;
if (secureConfig == null)
{
if (unsecureConfig != null)
{
args = new object[] {unsecureConfig};
}
}
else
{
args = new object[]{unsecureConfig, secureConfig};
}
return new SandboxWrapper<T>().Instantiate(args);
}
}
public class SandboxWrapper<T> : MarshalByRefObject, IDisposable
{
private const string DomainSuffix = "Sandbox";
/// <summary>
/// The Sandbox AppDomain to execute the plugin
/// </summary>
public AppDomain SandboxedAppDomain { get; private set; }
public T Instantiate(object[] constructorArguments = null)
{
/*
* Sandboxed plug-ins and custom workflow activities can access the network through the HTTP and HTTPS protocols. This capability provides
support for accessing popular web resources like social sites, news feeds, web services, and more. The following web access restrictions
apply to this sandbox capability.
* Only the HTTP and HTTPS protocols are allowed.
* Access to localhost (loopback) is not permitted.
* IP addresses cannot be used. You must use a named web address that requires DNS name resolution.
* Anonymous authentication is supported and recommended. There is no provision for prompting the
on user for credentials or saving those credentials.
*/
constructorArguments = constructorArguments ?? new object[] { };
var type = typeof(T);
var source = type.Assembly.Location;
var sourceAssembly = Assembly.UnsafeLoadFrom(source);
var setup = new AppDomainSetup
{
ApplicationBase = AppDomain.CurrentDomain.BaseDirectory,
ApplicationName = $"{sourceAssembly.GetName().Name}{DomainSuffix}",
DisallowBindingRedirects = true,
DisallowCodeDownload = true,
DisallowPublisherPolicy = true
};
var ps = new PermissionSet(PermissionState.None);
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.SerializationFormatter));
ps.AddPermission(new SecurityPermission(SecurityPermissionFlag.Execution));
ps.AddPermission(new FileIOPermission(PermissionState.None));
ps.AddPermission(new ReflectionPermission(ReflectionPermissionFlag.RestrictedMemberAccess));
//RegEx pattern taken from: https://msdn.microsoft.com/en-us/library/gg334752.aspx
ps.AddPermission(new WebPermission(NetworkAccess.Connect,
new Regex(
#"^http[s]?://(?!((localhost[:/])|(\[.*\])|([0-9]+[:/])|(0x[0-9a-f]+[:/])|(((([0-9]+)|(0x[0-9A-F]+))\.){3}(([0-9]+)|(0x[0-9A-F]+))[:/]))).+")));
// We don't need to add these, but it is important to note that there is no access to the following
ps.AddPermission(new NetworkInformationPermission(NetworkInformationAccess.None));
ps.AddPermission(new EnvironmentPermission(PermissionState.None));
ps.AddPermission(new RegistryPermission(PermissionState.None));
ps.AddPermission(new EventLogPermission(PermissionState.None));
SandboxedAppDomain = AppDomain.CreateDomain(DomainSuffix, null, setup, ps, null);
return Create(constructorArguments);
}
private T Create(object[] constructorArguments)
{
var type = typeof(T);
return (T)Activator.CreateInstanceFrom(
SandboxedAppDomain,
type.Assembly.ManifestModule.FullyQualifiedName,
// ReSharper disable once AssignNullToNotNullAttribute
type.FullName, false, BindingFlags.CreateInstance,
null, constructorArguments,
CultureInfo.CurrentCulture, null
).Unwrap();
}
#region IDisposable Support
//Implementing IDisposable Pattern: https://learn.microsoft.com/en-us/dotnet/standard/design-guidelines/dispose-pattern
private bool _disposed; // To detect redundant calls
protected virtual void Dispose(bool disposing)
{
if (_disposed) return;
if (disposing)
{
if (SandboxedAppDomain != null)
{
AppDomain.Unload(SandboxedAppDomain);
SandboxedAppDomain = null;
}
}
_disposed = true;
}
// This code added to correctly implement the disposable pattern.
void IDisposable.Dispose()
{
// Do not change this code. Put cleanup code in Dispose(bool disposing) above.
Dispose(true);
}
#endregion
}
}
Which can be used as such:
SandboxWrapper.InstantiatePlugin<YourPluginType>(unsecureString, secureString)
Not sure how much of it is valid or not, but it worked for handling my testing of xml and JSON serialization correctly.

Salesforce Apex web service test class error

I'm working on Salesforce Apex web service to create record. Below is the apex web service class that I have written:
global class createCloudRecord {
global class projectInputs{
webService Integer ProjectID;
webService String ProjectName;
}
webService static Boolean createSFRecords(List<projectInputs> inputs) {
cv__Designation__c desg = new cv__Designation__c();
desg.cv__Active__c = true;
desg.cv__Default__c = false;
desg.cv__Description__c = 'Test Desc';
desg.OwnerId = '002B0000000K9soIAD';
desg.Name = inputs[0].ProjectName;
desg.cv__ExternalId__c = string.valueof(inputs[0].ProjectID);
insert desg;
return true;
}
}
It's working fine and creating records on SF cloud via SOAP API call. Now I have to written the test class for above web service with code coverage of min 75%.
Below is the code that I have written for my test class:
#isTest
private class createCloudRecordTest {
static testMethod void testCreateSFRecords() {
createCloudRecord.projectInputs project = new createCloudRecord.projectInputs();
project.ProjectID = 12345;
project.ProjectName = 'TestProject';
createCloudRecord.createSFRecords(project);
}
}
But this is showing an error for this line createCloudRecord.createSFRecords(project);:
Error: Compile Error: Method does not exist or incorrect signature.
Anyone has any idea how can I make this working.
Thanks!
I got the solution for my question. The problem was in my web service I've defined param as list but above in test class I'm passing param as single record.
So it should be something like below:
#isTest
private class createCloudRecordTest {
static testMethod void testCreateSFRecords() {
createCloudRecord.projectInputs project = new createCloudRecord.projectInputs();
project.ProjectID = 12345;
project.ProjectName = 'TestProject';
list<createCloudRecord.projectInputs> projects = new list<createCloudRecord.projectInputs>();
projects.add(project);
createCloudRecord.createSFRecords(projects);
}
}

How to get value of 'CARBON_HOME' in java code

I was trying to implement an Axis2 service that receives user requests and publishes them as events to a CEP using carbon databridge thrift (via 'org.wso2.carbon.databridge.agent.thrift.DataPublisher')
I followed the code sample provided in wso2cep-3.1.0/samples/producers/activity-monitor
please see the following code snippet
public class GatewayServiceSkeleton{
private static Logger logger = Logger.getLogger(GatewayServiceSkeleton.class);
public RequestResponse request(Request request)throws AgentException,
MalformedStreamDefinitionException,StreamDefinitionException,
DifferentStreamDefinitionAlreadyDefinedException,
MalformedURLException,AuthenticationException,DataBridgeException,
NoStreamDefinitionExistException,TransportException, SocketException,
org.wso2.carbon.databridge.commons.exception.AuthenticationException
{
final String GATEWAY_SERVICE_STREAM = "gateway.cep";
final String VERSION = "1.0.0";
final String PROTOCOL = "tcp://";
final String CEPHOST = "cep.gubnoi.com";
final String CEPPORT = "7611";
final String CEPUSERNAME = "admin";
final String CEPPASSWORD = "admin";
Object[] metadata = { request.getDeviceID(), request.getViewID()};
Object[] correlationdata = { request.getSessionID()};
Object[] payloaddata = {request.getBucket()};
KeyStoreUtil.setTrustStoreParams();
KeyStoreUtil.setKeyStoreParams();
DataPublisher dataPublisher = new DataPublisher(PROTOCOL + CEPHOST + ":" + CEPPORT, CEPUSERNAME, CEPPASSWORD);
//create event
Event event = new Event (GATEWAY_SERVICE_STREAM + ":" + VERSION, System.currentTimeMillis(), metadata, correlationdata, payloaddata);
//Publish event for a valid stream
dataPublisher.publish(event);
//stop
dataPublisher.stop();
RequestResponse response = new RequestResponse();
response.setSessionID(request.getSessionID());
response.setDeviceID(request.getDeviceID());
response.setViewID(request.getViewID());
response.setBucket(request.getBucket());
return response;
}
there is also a utility class that set the key store parameters as following
public class KeyStoreUtil {
static File filePath = new File("../../../repository/resources/security");
public static void setTrustStoreParams() {
String trustStore = filePath.getAbsolutePath();
System.setProperty("javax.net.ssl.trustStore", trustStore + "/client-truststore.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "wso2carbon");
}
public static void setKeyStoreParams() {
String keyStore = filePath.getAbsolutePath();
System.setProperty("Security.KeyStore.Location", keyStore + "/wso2carbon.jks");
System.setProperty("Security.KeyStore.Password", "wso2carbon");
}
}
I uploaded the service into a wso2as-5.2.1, and called the service using SOAPUI
the request returned an error message "cannot borrow client for TCP"
I debug, and found out the problem might lies with the class 'KeyStoreUtil',
where the 'filePath' somehow retuned a 'null',
static File filePath = new File("../../../repository/resources/security");
and caused the failure on this line
DataPublisher dataPublisher = new DataPublisher(PROTOCOL + CEPHOST + ":" + CEPPORT, CEPUSERNAME, CEPPASSWORD);
I guess it could be a better idea if I use the value of "CARBON_HOME" to figure out the location of Key Store
so my question is :
How may I be able to get the value of 'CARBON_HOME' in the Java code?
that said. If you think a bit more:
the service will be called numerous time; whileas the 'setTrustStoreParams' and the 'setKeyStoreParams' will only be needed to executed once at the server/service initiate.
So, are there any even better ways to remove 'setTrustStoreParams' and 'setKeyStoreParams' out of the service code, or implement as configurable items?
Please advise
thanks
so my question is :
How may I be able to get the value of 'CARBON_HOME' in the Java code?
You should use the property carbon.home like following which will retrieve the WSO2 product's home directory.
System.getProperty("carbon.home");

MS CRM 2013 Attribute parentcustomeridtype must not be NULL if attribute parentcustomerid is not NULL

Dear smart developers out there,
I encounter a problem when I want to create a contact belonging to an organization in Microsoft Dynamics CRM 2013 via web services
client = new OrganizationServiceClient("CustomBinding_IOrganizationService");
var newContactProperties = new Dictionary<string, object> {
{ "lastname", "TestContact"},
{ "firstname", "A"},
{ "fullname", "A TestContact"}
};
/* organizationType is a CRM.CRMWebServices.OptionSetValue
* with ExtensionData null, PropertyChanged null and a valid Value
*
* orgReference is a CRM.CRMWebServices.EntityReference
* with a valid Id
*/
newContactProperties.Add("parentcustomeridtype", organizationType);
newContactProperties.Add("parentcustomerid", orgReference);
var entity = new Entity();
entity.LogicalName = "contact";
entity.Attributes = new AttributeCollection();
entity.Attributes.AddRange(newContactProperties);
client.Create(entity);
This gives me error 'Attribute parentcustomeridtype must not be NULL if attribute parentcustomerid is not NULL'
I am puzzled why this happens and how I can solve this problem. Please help me if you can.
Thank you,
AllWorkNoPlay
You don't need to set "parentcustomeridtype" attribute separately. It's a system field, will be set by platform and in parentcustomerid exists for legacy reason, when it was Customer type in earlier versions of Dynamics CRM.
You need to specify only EntityReference in lookup field.
newContactProperties.Add("parentcustomerid", new EntityReference("account", new Guid("{accountid guid}")));
Also it's not clear what type you use in "orgReference" field. For contact valid entity types should be "account" or "contact".
thank you for the answers, I did not manage to get it right using web services this way.
I tried using Early Bound access with success:
Generated proxy objects using https://xrmearlyboundgenerator.codeplex.com/
Added line [assembly: Microsoft.Xrm.Sdk.Client.ProxyTypesAssemblyAttribute()] to assemblyInfo to have Intellisense available (even for customized fields)
Now I manage to create a contact and assign it to an organization (something like this):
var contact = new Contact()
{
FirstName = "Bob",
LastName = "Dobalina",
Address1_Line1 = "123 Strasse",
Address1_City = "Berlin",
Address1_PostalCode = "32254",
Telephone1 = "425-555-5678",
EMailAddress1 = "bob.dobalina#germany.de"
};
var account = new Account()
{
Name = "Siemens Germany",
};
context.AddObject(contact);
context.AddObject(account);
context.AddLink(account, "contact_customer_accounts", contact);
context.SaveChanges();
}

How to create new record from web service in ADF?

I have created a class and published it as web service. I have created a web method like this:
public void addNewRow(MyObject cob) {
MyAppModule myAppModule = new MyAppModule();
try {
ViewObjectImpl vo = myAppModule.getMyVewObject1();
================> vo object is now null
Row r = vo.createRow();
r.setAttribute("Param1", cob.getParam1());
r.setAttribute("Param2", cob.getParam2());
vo.executeQuery();
getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
}
}
As I have written in code, myAppModule.getMyVewObject1() returns a null object. I do not understand why! As far as I know AppModule has to initialize the object by itself when I call "getMyVewObject1()" but maybe I am wrong, or maybe this is not the way it should be for web methods. Has anyone ever faced this issue? Any help would be very appreciated.
You can check nice tutorial: Building and Using Web Services with JDeveloper
It gives you general idea about how you should build your webservices with ADF.
Another approach is when you need to call existing Application Module from some bean that doesn't have needed environment (servlet, etc), then you can initialize it like this:
String appModuleName = "org.my.package.name.model.AppModule";
String appModuleConfig = "AppModuleLocal";
ApplicationModule am = Configuration.createRootApplicationModule(appModuleName, appModuleConfig);
Don't forget to release it:
Configuration.releaseRootApplicationModule(am, true);
And why you shouldn't really do it like this.
And even more...
Better aproach is to get access to binding layer and do call from there.
Here is a nice article.
Per Our PM : If you don't use it in the context of an ADF application then the following code should be used (sample code is from a project I am involved in). Note the release of the AM at the end of the request
#WebService(serviceName = "LightViewerSoapService")
public class LightViewerSoapService {
private final String amDef = " oracle.demo.lightbox.model.viewer.soap.services.LightBoxViewerService";
private final String config = "LightBoxViewerServiceLocal";
LightBoxViewerServiceImpl service;
public LightViewerSoapService() {
super();
}
#WebMethod
public List<Presentations> getAllUserPresentations(#WebParam(name = "userId") Long userId){
ArrayList<Presentations> al = new ArrayList<Presentations>();
service = (LightBoxViewerServiceImpl)getApplicationModule(amDef,config);
ViewObject vo = service.findViewObject("UserOwnedPresentations");
VariableValueManager vm = vo.ensureVariableManager();
vm.setVariableValue("userIdVariable", userId.toString());
vo.applyViewCriteria(vo.getViewCriteriaManager().getViewCriteria("byUserIdViewCriteria"));
Row rw = vo.first();
if(rw != null){
Presentations p = createPresentationFromRow(rw);
al.add(p);
while(vo.hasNext()){
rw = vo.next();
p = createPresentationFromRow(rw);
al.add(p);
}
}
releaseAm((ApplicationModule)service);
return al;
}
Have a look here too:
http://www.youtube.com/watch?v=jDBd3JuroMQ