How can I transfer Optionsets/Extensions with Microsoft Xrm Sdk - c#

I have a small tool for transfer Entities from microsoft dynamics 365 crm 2016 instance to another one. I succesfully transfered entities that don't have any dependices; but when i try to transfer entities that some optionsets setted up -like language,verticals,departments- i get error beacause of these optionsets are not exists at target instance.
I signed these optionsets at below image.
My problem is I don't know how i can retrive these extensions programatically. I already used below code for retrive all optionsets but the user defined languages,verticals and other optionsets were not exists at repsonse.
RetrieveAllOptionSetsRequest retrieveAllOptionSetsRequest = new RetrieveAllOptionSetsRequest();
var retrieveAllOptionSetsResponse =(RetrieveAllOptionSetsResponse)sourceService.Execute(retrieveAllOptionSetsRequest);
Any Idea ? Which request should I send to source crm instance for get all user defined optionsets ?

Those entities may have private option sets. You can retrieve using those option sets for each entity using these methods (pass the entity's logical name to the entity parameter):
using System;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;
using Microsoft.Xrm.Sdk.Metadata;
using Microsoft.Xrm.Tooling.Connector;
using System.Collections.Generic;
using System.Linq;
private List<AttributeMetadata> getPicklists(IOrganizationService svc, string entity)
{
return allAttributes(svc, entity).Where(a => a.AttributeType == AttributeTypeCode.Picklist).ToList();
}
//Retrieve all attributes of an entity
private List<AttributeMetadata> allAttributes(IOrganizationService svc, string entity)
{
var req = new RetrieveEntityRequest();
req.EntityFilters = EntityFilters.Attributes;
req.LogicalName = entity.ToLower();
var response = (RetrieveEntityResponse)svc.Execute(req);
return response.EntityMetadata.Attributes.ToList();
}

Related

Adding a DBContext to AWS Lambda causes it to hang

I am new to C# and Serverless development. I am trying to create an AWS Lambda that has an API Gateway trigger. When the Lambda triggers I want to write a User record to the database.
Lambda:
namespace CreateProfile;
using System.Net;
using Amazon.Lambda.APIGatewayEvents;
using Amazon.Lambda.Core;
using Database;
using Users.Models;
public class Function
{
/// <summary>
/// This Lambda function is for creating a user profile
/// </summary>
public APIGatewayHttpApiV2ProxyResponse FunctionHandler(User user, ILambdaContext context)
{
LambdaLogger.Log($"Calling function name: {context.FunctionName}\n");
LambdaLogger.Log($"Payload Received: {user}");
// 1. Populate the relevant table(s) from our input
using myDbContext ctx = new();
ctx.Users.Add(user);
ctx.SaveChanges();
APIGatewayHttpApiV2ProxyResponse response = new ()
{
StatusCode = (int)HttpStatusCode.OK,
Body = "Great Scott...it worked!",
Headers = new Dictionary<string, string> { { "Content-Type", "text/plain" } }
};
return response;
}
}
I am using the following Assembly:
using Amazon.Lambda.Core;
using Amazon.Lambda.Serialization.SystemTextJson;
// Assembly attribute to enable the Lambda function's JSON input to be converted into a .NET class.
[assembly: LambdaSerializer(typeof(
DefaultLambdaJsonSerializer
))]
I am using the following as my database context:
namespace Database;
using Users.Models;
using System.Data.Entity;
using System.Data.Entity.Infrastructure;
using Npgsql;
[DbConfigurationType(typeof(Config))]
public class MyDbContext: DbContext
{
public myDbContext(): base(MakeConnString()) {}
private static string MakeConnString()
{
// Will be moving these to a common location
string OptEnv(string key, string default_) =>
Environment.GetEnvironmentVariable(key) ?? default_;
string Env(string key) =>
Environment.GetEnvironmentVariable(key) ?? throw new MissingFieldException(key);
NpgsqlConnectionStringBuilder builder = new()
{
Host = Env("PGHOST"),
Port = int.Parse(OptEnv("PGPORT", "5432")),
SslMode = Enum.Parse<SslMode>(OptEnv("PGSSLMODE", "Require")),
TrustServerCertificate = true,
Database = OptEnv("PGDATABASE", "postgres"),
Username = OptEnv("PGUSER", "postgres"),
Password = Env("PGPASSWORD")
};
return builder.ConnectionString;
}
public DbSet<User> Users { get; set; }
}
When running this my Lambda hangs and I can't figure out why.
I'm assuming the database you are trying to interact with is an RDS instance or running on an EC2 instance in the same account, right?
If so, are your Lambda function deployed into your VPC? If not, the Lambda needs to be in order to talk to a VPC resource. The default is the Lambdas are NOT deployed in your VPC.
If you are using Serverless Framework then you need to add the following config to the provider section of your serverless.yml [https://www.serverless.com/framework/docs/providers/aws/guide/serverless.yml]
provider:
# Optional VPC settings
# If you use VPC then both securityGroupIds and subnetIds are required
vpc:
securityGroupIds:
- securityGroupId1
subnetIds:
- subnetId1
- subnetId2
The subnets you reference need to have a route to the subnets your database is provisioned into. They can be in the same subnets as the ones your RDS instance or EC2 is running the in DB.
Lastly, you need to ensure that the Security Group allows outbound traffic on the correct port for your Lambda Security Group, as well as, ensure that the Security Group on your database (EC2 or RDS) allows traffic from either the Lambda SG or the CIDR/IP ranges of the subnets you are deploying the Lambdas into on the correct port #.
The hanging is typically the request not making it to the DB - if you are already set up with your Lambda deployed in your VPC, then you should check the routing and Security Groups mentioned.

Acumatica validation error when using PXSelect

Every time I try to select a specific data record based on a column criteria Acumatica throws an error saying that the type name does not exist, when in the table it absolutely does.
Can someone tell me what I am doing wrong?
If I remove the "where" part of the statement, it validates fine; however that is not what I need to do.
Here is the error message
\App_RuntimeCode\CRActivityMaint.cs(34): error CS0426: The type name 'NoteID' does not exist in the type 'Contact'
Here is the code
using System.Diagnostics.Eventing.Reader;
using System.Linq;
using PX.Common;
using PX.CS;
using PX.Data.EP;
using PX.Objects.CR;
using PX.Data;
using System;
using System.Collections;
using PX.Objects.GL;
using PX.Objects.PM;
using PX.Objects.CS;
using PX.Objects.Common.GraphExtensions.Abstract;
using System.Web.Compilation;
using PX.Objects;
using PX.Objects.EP;
using PX.Data.BQL.Fluent;
using PX.Data.BQL;
namespace PX.Objects.EP
{
public class CRActivityMaint_Extension : PXGraphExtension<CRActivityMaint>
{
protected void CRActivity_RowSelected(PXCache sender, PXRowSelectedEventArgs e)
{
var task = (CR.CRActivity)e.Row;
var taskExt = task.GetExtension<CR.CRActivityExt>();
if (taskExt != null)
{
Contact contactInfo = PXSelect<Contact, Where<Contact.NoteID, Equal<Required<Contact.NoteID>>>>.Select(this.Base, 100862);
}
}
#region Event Handlers
#endregion
}
}```
NoteID is a GUID stored as an uniqueidentifier in SQL (Ex '5D0C3B2C-D87F-E411-BECA-00B56D0561C2'). I suggest you try using a GUID parameter.

fakeXrmEasy for crm testing initialization issues

I'm trying to follow the basic tutorial for FakeXrmEasy, but I'm not sure why I'm getting errors. I installed everything that needs to be installed to mock Dynamics 365, but I'm still getting errors. I can't figure out what I'm missing, I really want to be able to use this tool.
CS1950 The best overloaded Add method 'List.Add(Entity)' for the collection initializer has some invalid arguments unitTest c:\Users\acapell\documents\visual studio 2015\Projects\unitTest\unitTest\Program.cs 48 Active
CS0246 The type or namespace name 'Account' could not be found (are you missing a using directive or an assembly reference?) unitTest c:\Users\acapell\documents\visual studio 2015\Projects\unitTest\unitTest\Program.cs 45 Active
Didn't know if I was suppose to create an account class, I also tried that but that didn't work either. I got
CS1503 Argument 1: cannot convert from 'unitTest.Account' to 'Microsoft.Xrm.Sdk.Entity' unitTest c:\Users\acapell\documents\visual studio 2015\Projects\unitTest\unitTest\Program.cs 48 Active
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Xunit;
using FakeItEasy;
using FakeXrmEasy;
using Microsoft.Xrm.Sdk;
namespace unitTest
{
class Program
{
static void Main(string[] args)
{
}
}
class unitTest
{
public object ProxyTypesAssembly { get; private set; }
public void MyFirstTest()
{//test method body
var context = new XrmFakedContext();
//You can think of a context like an Organisation database which stores entities In Memory.
//We can also use TypedEntities but we need to tell the context where to look for them,
//this could be done, easily, like this:
context.ProxyTypesAssembly = Assembly.GetAssembly(typeof(Account));
//We have to define our initial state now,
//by calling the Initialize method, which expects a list of entities.
var account = new Account() { Id = Guid.NewGuid(), Name = "My First Faked Account yeah!" };
context.Initialize(new List<Entity>() {
account
});
}
}
}
Do you use early binding in your CRM project and got the references right? If you do not use early binding, you can try late binding, e.g.
//context.ProxyTypesAssembly = Assembly.GetAssembly(typeof(Account));
var account = new Entity();
account.LogicalName = "account";
account.Attributes["name"] = "your account name";

get GuiApplication of running Sap logon vb6 to c#

I have to migrate a vb6 program to C# .net 3.5
the user starts SAP logon and authenticates,
then he can use the tool to fetch and insert the data using the tool
the problem:
i can create a new GuiApplication with reflection, but i can't fetch currently opened GuiSessions with it :/
here is the vb6 part of the code that gets currently opened GuiApplication with all opened GuiSessions
Dim obj As Object
Set obj = CreateObject("SAPGUI")
Set obj = obj.GetScriptingEngine
If TypeName(obj) = "GuiApplication" Then
Set SapAutomationObject = obj
SapAutomationObject.AllowSystemMessages = False
Debug.Print "SAP Automation OK"
End If
i tried it with reflection:
GuiApplication Application = (GuiApplication)System.Activator.CreateInstance(Type.GetTypeFromProgID("SapGui.S‌​criptingCtrl.1"));
i got an instance but no existing sessions
public static void testConnection()
{
SapROTWr.CSapROTWrapper sapROTWrapper = new SapROTWr.CSapROTWrapper();
object SapGuilRot = sapROTWrapper.GetROTEntry("SAPGUI");
object engine = SapGuilRot.GetType().InvokeMember("GetSCriptingEngine", System.Reflection.BindingFlags.InvokeMethod,
null, SapGuilRot, null);
SAPconnection.sapGuiApp = engine as GuiApplication;
GuiConnection connection = sapGuiApp.Connections.ElementAt(0) as GuiConnection;
GuiSession session = connection.Children.ElementAt(0) as GuiSession;
MessageBox.Show(session.Info.User + " !!||!! " + session.Info.Transaction);
}
Use This method, you have to reference SapROTWr.DLL which is in the sapgui folder of your SAP installation.
This works for me (SAP 730 / Win7):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SAPFEWSELib;
using SapROTWr;
namespace FIT.SapHelper
{
public static class stcSapHelper
{
public static void testConnection()
{
SapROTWr.CSapROTWrapper sapROTWrapper = new SapROTWr.CSapROTWrapper();
object SapGuilRot = sapROTWrapper.GetROTEntry("SAPGUI");
object engine = SapGuilRot.GetType().InvokeMember("GetScriptingEngine", System.Reflection.BindingFlags.InvokeMethod, null, SapGuilRot, null);
GuiConnection connection = (engine as GuiApplication).OpenConnection("BOX DESCRIPTION");
GuiSession session = connection.Children.ElementAt(0) as GuiSession;
}
}
}
Assuming that SAPGUI is a COM object then you should be able to take a reference to it and create it as a new object without using reflection. i.e. Use early binding and not late binding even though the original VB6 code is using 'late binding'
Secondly, assuming late binding, shouldn't the Type.GetTypeFromProgID("SapGui.S‌criptingCtrl.1") fragment be Type.GetTypeFromProgID("SapGui") to match the original VB6? you might need to check on the object model for SAPGUI to make sure you're referencing the right object.
the only solution that i found to work with running sessions is to load that code in a dll and access it via c#
SAP released SAP .NET connector to provide standartized way to interact with SAP system from within of .NET application. Look at http://service.sap.com/connectors, you must be SAP partner to be able access to the page

How to access database in lightswitch in other class?

I just don't know how to explain this clearly. So I create a simple image pattern of what I did.
My question is, how would I be able to access my database in other class in LS?
I've been searching on net, but I didn't found any solution. I hope I'll find it here.
Thanks!.
Any suggestion is already appreciated.
Thanks for the answer Bryan, but I found the answer on my problem here Richard Waddell
Here is what I did to achieve my goal.
Switch your LS project to file view
Go to "Common" project, under "UserCode" folder, create a class (e.g. Authenticate.cs) and put this codes.
The code follows:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.LightSwitch;
namespace LightSwitchApplication
{
public class Authenticate
{
public static adminuser GetCurrentUser()
{
adminuser userFound = (from useritem in
Application.Current.CreateDataWorkspace().basecampcoreData.adminusers
where useritem.LoginID == Application.Current.User.Name
select useritem).SingleOrDefault();
if (userFound != null)
return userFound;
else
return null;
}
}
}
Then you can now call the Authenticate.GetCurrentUser() anywhere in the project.
Thanks!
The main difference is the first set of code that works is running inside a screen. For your Authenticate class, you need to do the following steps to access the Database.
Note: I'm assuming that your datasource has the default name of ApplicationData since you hid the name, if not, make the corresponding changes. If it's a completely different datasource, change "_IntrinsicData" in the steps below)
These steps are taken from the Lightswitch Help Website
Navigate to ..ServerGenerated\GeneratedArtifacts (in the LightSwitch project) and click on ApplicationData.cs and Add As Link.
Add the following code below, this code dynamically creates a connection to the database. LightSwitch uses “_IntrinsicData” as it’s connection string.
private ApplicationDataObjectContext m_context;
public ApplicationDataObjectContext Context
{
get
{
if (this.m_context == null)
{
string connString =
System.Web.Configuration.WebConfigurationManager
.ConnectionStrings["_IntrinsicData"].ConnectionString;
EntityConnectionStringBuilder builder = new EntityConnectionStringBuilder();
builder.Metadata =
"res://*/ApplicationData.csdl|res://*/ApplicationData.ssdl|res://*/ApplicationData.msl";
builder.Provider =
"System.Data.SqlClient";
builder.ProviderConnectionString = connString;
this.m_context = new ApplicationDataObjectContext(builder.ConnectionString);
}
return this.m_context;
}
}
You should be able to access it through Context.adminusers

Categories

Resources